Update from Andrew: tweaks for cross-staff chords snippet.
[lilypond.git] / flower / file-path.cc
blob175357d88962d232328d70f796732ee22ce0b7de
1 /*
2 file-path.cc - implement File_path
4 source file of the Flower Library
6 (c) 1997--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 Jan Nieuwenhuizen <janneke@gnu.org>
8 */
10 #include "file-path.hh"
12 #include <cstdio>
13 #include <cerrno>
15 #include "config.hh"
16 #if HAVE_SYS_STAT_H
17 #include <sys/stat.h>
18 #endif
20 #ifdef __CYGWIN__
21 #include <sys/cygwin.h>
22 #endif
24 #include "file-name.hh"
25 #include "warn.hh"
27 #ifndef PATHSEP
28 #define PATHSEP ':'
29 #endif
31 vector<string>
32 File_path::directories () const
34 return dirs_;
37 #include <algorithm>
38 void
39 File_path::parse_path (string p)
41 concat (dirs_, string_split (p, PATHSEP));
44 bool
45 is_file (string file_name)
47 #if !STAT_MACROS_BROKEN
48 struct stat sbuf;
49 if (stat (file_name.c_str (), &sbuf) != 0)
50 return false;
52 return !S_ISDIR (sbuf.st_mode);
53 #endif
55 if (FILE *f = fopen (file_name.c_str (), "r"))
57 fclose (f);
58 return true;
61 return false;
64 bool
65 is_dir (string file_name)
68 canonicalize; in particular, trailing slashes should disappear.
70 file_name = File_name (file_name).to_string ();
72 #if !STAT_MACROS_BROKEN
73 struct stat sbuf;
74 if (stat (file_name.c_str (), &sbuf) != 0)
75 return false;
77 return S_ISDIR (sbuf.st_mode);
78 #endif
80 if (FILE *f = fopen (file_name.c_str (), "r"))
82 fclose (f);
83 return true;
85 return false;
88 /** Find a file.
90 Check absolute file name, search in the current dir (DUH! FIXME!),
91 in the construction-arg (what's that?), and in any other appended
92 directory, in this order.
94 @return
95 The file name if found, or empty string if not found. */
97 string
98 File_path::find (string name) const
100 if (!name.length () || (name == "-"))
101 return name;
103 #ifdef __MINGW32__
104 if (name.find ('\\') != NPOS)
105 programming_error ("file name not normalized: " + name);
106 #endif /* __MINGW32__ */
108 /* Handle absolute file name. */
109 File_name file_name (name);
110 if (file_name.dir_[0] == DIRSEP && is_file (file_name.to_string ()))
111 return file_name.to_string ();
113 for (vsize i = 0; i < dirs_.size (); i++)
115 File_name file_name (name);
116 File_name dir = (string) dirs_[i];
117 file_name.root_ = dir.root_;
118 dir.root_ = "";
119 if (file_name.dir_.empty ())
120 file_name.dir_ = dir.to_string ();
121 else if (!dir.to_string ().empty ())
122 file_name.dir_ = dir.to_string ()
123 + ::to_string (DIRSEP) + file_name.dir_;
124 if (is_file (file_name.to_string ()))
125 return file_name.to_string ();
127 return "";
131 Try to find
133 file.EXT,
135 where EXT is from EXTENSIONS.
137 string
138 File_path::find (string name, char const *extensions[])
140 if (name.empty () || name == "-")
141 return name;
143 File_name file_name (name);
144 string orig_ext = file_name.ext_;
145 for (int i = 0; extensions[i]; i++)
147 file_name.ext_ = orig_ext;
148 if (*extensions[i] && !file_name.ext_.empty ())
149 file_name.ext_ += ".";
150 file_name.ext_ += extensions[i];
151 string found = find (file_name.to_string ());
152 if (!found.empty ())
153 return found;
156 return "";
159 /** Append a directory, return false if failed. */
160 bool
161 File_path::try_append (string s)
163 if (s == "")
164 s = ".";
165 if (is_dir (s))
167 append (s);
168 return true;
170 return false;
173 string
174 File_path::to_string () const
176 string s;
177 for (vsize i = 0; i < dirs_.size (); i++)
179 s = s + dirs_[i];
180 if (i < dirs_.size () - 1)
181 s += ::to_string (PATHSEP);
183 return s;
186 void
187 File_path::append (string str)
189 dirs_.push_back (str);
192 void
193 File_path::prepend (string str)
195 dirs_.insert (dirs_.begin (), str);