]> git.donarmstrong.com Git - lilypond.git/blob - flower/file-path.cc
* flower/include/std-string.hh:
[lilypond.git] / flower / file-path.cc
1 /*
2   file-path.cc - implement File_path
3
4   source file of the Flower Library
5
6   (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
7   Jan Nieuwenhuizen <janneke@gnu.org>
8 */
9
10 #include "file-path.hh"
11
12 #include "std-string.hh"
13
14 #include <cstdio>
15 #include <cerrno>
16
17 #include "config.hh"
18 #if HAVE_SYS_STAT_H
19 #include <sys/stat.h>
20 #endif
21
22 #ifdef __CYGWIN__
23 #include <sys/cygwin.h>
24 #endif
25
26 #include "file-name.hh"
27 #include "warn.hh"
28
29 #ifndef PATHSEP
30 #define PATHSEP ':'
31 #endif
32
33 vector<string>
34 File_path::directories () const
35 {
36   return dirs_;
37 }
38
39 /*
40   TODO: use split_string.
41   
42  */
43
44 #include <algorithm>
45 void
46 File_path::parse_path (string p)
47 {
48   ssize len;
49   while ((len = p.length ()))
50     {
51       ssize i = p.find (PATHSEP);
52       if (i == NPOS)
53         i = len;
54       append (p.substr (0, i));
55       p = p.substr (min (len, i + 1));
56     }
57 }
58
59 bool
60 is_file (string file_name)
61 {
62 #if !STAT_MACROS_BROKEN
63   struct stat sbuf;
64   if (stat (file_name.c_str (), &sbuf) != 0)
65     return false;
66
67   return !S_ISDIR (sbuf.st_mode);
68 #endif
69
70   if (FILE *f = fopen (file_name.c_str (), "r"))
71     {
72       fclose (f);
73       return true;
74     }
75
76   return false;
77 }
78
79 bool
80 is_dir (string file_name)
81 {
82 #if !STAT_MACROS_BROKEN
83   struct stat sbuf;
84   if (stat (file_name.c_str (), &sbuf) != 0)
85     return false;
86
87   return S_ISDIR (sbuf.st_mode);
88 #endif
89
90   if (FILE *f = fopen (file_name.c_str (), "r"))
91     {
92       fclose (f);
93       return true;
94     }
95   return false;
96 }
97
98 /** Find a file.
99
100 Check absolute file name, search in the current dir (DUH! FIXME!),
101 in the construction-arg (what's that?), and in any other appended
102 directory, in this order.
103
104 @return
105 The file name if found, or empty string if not found. */
106
107 string
108 File_path::find (string name) const
109 {
110   if (!name.length () || (name == "-"))
111     return name;
112
113 #ifdef __MINGW32__
114   if (name.find ('\\') != NPOS)
115     programming_error ("file name not normalized: " + name);
116 #endif /* __MINGW32__ */
117
118   /* Handle absolute file name.  */
119   File_name file_name (name);
120   if (file_name.dir_[0] == DIRSEP && is_file (file_name.to_string ()))
121     return file_name.to_string ();
122
123   for (vsize i = 0; i < dirs_.size (); i++)
124     {
125       File_name file_name (name);
126       File_name dir = (string) dirs_[i];
127       file_name.root_ = dir.root_;
128       dir.root_ = "";
129       if (file_name.dir_.empty ())
130         file_name.dir_ = dir.to_string ();
131       else if (!dir.to_string ().empty ())
132         file_name.dir_ = dir.to_string ()
133           + ::to_string (DIRSEP) + file_name.dir_;
134       if (is_file (file_name.to_string ()))
135         return file_name.to_string ();
136     }
137   return "";
138 }
139
140 /*
141   Try to find
142
143   file.EXT,
144
145   where EXT is from EXTENSIONS.
146 */
147 string
148 File_path::find (string name, char const *extensions[])
149 {
150   if (name.empty () || name == "-")
151     return name;
152   
153   File_name file_name (name);
154   string orig_ext = file_name.ext_;
155   for (int i = 0; extensions[i]; i++)
156     {
157       file_name.ext_ = orig_ext;
158       if (*extensions[i] && !file_name.ext_.empty ())
159         file_name.ext_ += ".";
160       file_name.ext_ += extensions[i];
161       string found = find (file_name.to_string ());
162       if (!found.empty ())
163         return found;
164     }
165   
166   return "";
167 }
168
169 /** Append a directory, return false if failed.  */
170 bool
171 File_path::try_append (string s)
172 {
173   if (s == "")
174     s = ".";
175   if (is_dir (s))
176     {
177       append (s);
178       return true;
179     }
180   return false;
181 }
182
183 string
184 File_path::to_string () const
185 {
186   string s;
187   for (vsize i = 0; i < dirs_.size (); i++)
188     {
189       s = s + dirs_[i];
190       if (i < dirs_.size () - 1)
191         s += ::to_string (PATHSEP);
192     }
193   return s;
194 }
195
196 void
197 File_path::append (string str)
198 {
199   dirs_.push_back (str);
200 }
201
202 void
203 File_path::prepend (string str)
204 {
205   dirs_.insert (dirs_.begin (), str);
206 }