Commit e318123ba7d7dfb05133dcdc482a35494f82350e
1 parent
25d8d20b
changed stim::filename extensively, but the old class is available in filename_old.h
Showing
1 changed file
with
448 additions
and
0 deletions
Show diff stats
1 | +#ifndef STIM_FILENAME_H | |
2 | +#define STIM_FILENAME_H | |
3 | + | |
4 | +#include <stdio.h> /* defines FILENAME_MAX */ | |
5 | +#ifdef _WIN32 | |
6 | + #include <windows.h> | |
7 | + #include <direct.h> | |
8 | + #define GetCurrentDir _getcwd | |
9 | + #define STIM_FILENAME_DIV '/' | |
10 | +#else | |
11 | + #include <unistd.h> | |
12 | + #define GetCurrentDir getcwd | |
13 | + #define STIM_FILENAME_DIV '/' | |
14 | + #endif | |
15 | + | |
16 | +#include <string> | |
17 | +#include <sstream> | |
18 | +#include <iomanip> | |
19 | +#include <vector> | |
20 | +#include <stack> | |
21 | +#include <algorithm> | |
22 | +#include <iostream> | |
23 | + | |
24 | +#include "../parser/parser.h" | |
25 | +#ifdef BOOST_PRECOMPILED | |
26 | +#include <boost/filesystem.hpp> | |
27 | +#endif | |
28 | +namespace stim{ | |
29 | + | |
30 | +//filename class designed to work with both Windows and Unix | |
31 | + | |
32 | +class filename{ | |
33 | + | |
34 | +private: | |
35 | + void init(){ | |
36 | + | |
37 | + absolute = false; | |
38 | + | |
39 | + } | |
40 | + | |
41 | +protected: | |
42 | + | |
43 | + std::string drive; //drive letter (for Windows) | |
44 | + std::vector<std::string> path; //directory hierarchy | |
45 | + std::string pref; //file prefix (without extension) | |
46 | + std::string ext; //file extension | |
47 | + | |
48 | + bool absolute; //filename is an absolute path | |
49 | + | |
50 | + //replaces win32 dividers with the Linux standard | |
51 | + std::string unix_div(std::string s) { | |
52 | + std::replace( s.begin(), s.end(), '\\', '/'); | |
53 | + return s; | |
54 | + } | |
55 | + | |
56 | + //break up a filename into a prefix and extension | |
57 | + void parse_name(std::string fname){ | |
58 | + | |
59 | + //find the extension | |
60 | + size_t xpos = fname.find_last_of('.'); //find the position of the extension period (if there is one) | |
61 | + if(xpos != std::string::npos){ //split the prefix and extension | |
62 | + pref = fname.substr(0, xpos); | |
63 | + ext = fname.substr(xpos + 1); | |
64 | + } | |
65 | + else | |
66 | + pref = fname; | |
67 | + } | |
68 | + | |
69 | + /// Parse a file locator into its component parts | |
70 | + void parse(std::string &dr, std::vector<std::string> &p, std::string &pre, std::string &ex, bool &abs, std::string loc){ | |
71 | + dr = ""; //initialize the drive to NULL (in a Unix system, this will always be NULL) | |
72 | + p.clear(); //empty out the path array | |
73 | + pre = ""; //initialize the file prefix to NULL (if no file name is given, this will remain NULL) | |
74 | + ex = ""; //initialize the file extension to NULL (if no extension exists, this will remain NULL) | |
75 | + abs = false; //the default path is relative | |
76 | + | |
77 | + loc = unix_div(loc); //convert to unix style divisions (default representation) | |
78 | + | |
79 | + if(loc.size() == 0) return; //if the locator is NULL, just return (everything else will be NULL) | |
80 | + | |
81 | + //determine the drive (if Windows) | |
82 | + #ifdef _WIN32 | |
83 | + if(loc[1] == ':'){ //if the second character is a colon, the character right before it is the drive | |
84 | + abs = true; //this is an absolute path | |
85 | + dr = loc[0]; //copy the drive letter | |
86 | + loc = loc.substr(3); //remove the drive information from the locator string | |
87 | + } | |
88 | + #else | |
89 | + if(loc[0] == STIM_FILENAME_DIV){ | |
90 | + absolute = true; | |
91 | + loc = loc.substr(1); | |
92 | + } | |
93 | + #endif | |
94 | + | |
95 | + std::string fname = loc.substr( loc.find_last_of('/') + 1 ); //find the file name (including extension) | |
96 | + | |
97 | + //find the extension and prefix | |
98 | + size_t xpos = fname.find_last_of('.'); //find the position of the extension period (if there is one) | |
99 | + if(xpos != std::string::npos){ //split the prefix and extension | |
100 | + pre = fname.substr(0, xpos); | |
101 | + ex = fname.substr(xpos + 1); | |
102 | + } | |
103 | + else | |
104 | + pre = fname; | |
105 | + } | |
106 | + | |
107 | + //parse a file locator string | |
108 | + void parse(std::string loc){ | |
109 | + if(loc.size() == 0) return; | |
110 | + | |
111 | + loc = unix_div(loc); | |
112 | + | |
113 | + //determine the drive (if Windows) | |
114 | + drive = ""; | |
115 | + #ifdef _WIN32 | |
116 | + //if the second character is a colon, the character right before it is the drive | |
117 | + if(loc[1] == ':'){ | |
118 | + absolute = true; //this is an absolute path | |
119 | + drive = loc[0]; //copy the drive letter | |
120 | + loc = loc.substr(3); //remove the drive information from the locator string | |
121 | + } | |
122 | + #else | |
123 | + if(loc[0] == STIM_FILENAME_DIV){ | |
124 | + absolute = true; | |
125 | + loc = loc.substr(1); | |
126 | + } | |
127 | + #endif | |
128 | + | |
129 | + //determine the file name | |
130 | + std::string fname = loc.substr( loc.find_last_of('/') + 1 ); //find the file name (including extension) | |
131 | + | |
132 | + //parse the file name | |
133 | + parse_name(fname); | |
134 | + | |
135 | + //find the directory hierarchy | |
136 | + std::string dir = loc.substr(0, loc.find_last_of('/') + 1 ); | |
137 | + path = stim::parser::split(dir, '/'); | |
138 | + } | |
139 | + | |
140 | +public: | |
141 | + | |
142 | + filename(){ | |
143 | + init(); | |
144 | + } | |
145 | + | |
146 | + filename(std::string loc){ | |
147 | + init(); | |
148 | + parse(loc); | |
149 | + } | |
150 | + | |
151 | + | |
152 | + /// Outputs the file name (including prefix and extension) | |
153 | + std::string get_name(){ | |
154 | + if(pref == "" && ext == "") | |
155 | + return ""; | |
156 | + else | |
157 | + return pref + "." + ext; | |
158 | + } | |
159 | + | |
160 | + /// Output the file extension only (usually three characters after a '.') | |
161 | + std::string get_extension(){ | |
162 | + return ext; | |
163 | + } | |
164 | + | |
165 | + std::string extension(){ | |
166 | + return ext; | |
167 | + } | |
168 | + | |
169 | + void extension(std::string e){ | |
170 | + ext = e; | |
171 | + } | |
172 | + | |
173 | + /// Output the file prefix only (name before the extension) | |
174 | + std::string get_prefix(){ | |
175 | + return pref; | |
176 | + } | |
177 | + | |
178 | + std::string prefix(){ | |
179 | + return pref; | |
180 | + } | |
181 | + | |
182 | + void prefix(std::string p){ | |
183 | + pref = p; | |
184 | + } | |
185 | + | |
186 | + /// Output the entire path (not including the filename) | |
187 | + /// ex. "c:\this\is\the\directory\" | |
188 | + std::string dir(){ | |
189 | + std::stringstream ss; | |
190 | + | |
191 | + //if the path is absolute | |
192 | + if(absolute){ | |
193 | + //output the drive letter if in Windows | |
194 | + #ifdef _WIN32 | |
195 | + ss<<drive<<":"; | |
196 | + #endif | |
197 | + ss<<STIM_FILENAME_DIV; | |
198 | + } | |
199 | + | |
200 | + //output the directory | |
201 | + for(unsigned int d = 0; d < path.size(); d++) | |
202 | + ss<<path[d]<<STIM_FILENAME_DIV; | |
203 | + | |
204 | + return ss.str(); | |
205 | + | |
206 | + } | |
207 | + | |
208 | + void clear() | |
209 | + { | |
210 | + drive = ""; //drive letter (for Windows) | |
211 | + path.resize(0); | |
212 | + pref= ""; //file prefix (without extension) | |
213 | + ext = ""; //file extension | |
214 | + } | |
215 | + | |
216 | + /// Output the entire string, including the path and filename | |
217 | + /// ex. "c:\this\is\a\directory\file.txt" | |
218 | + std::string str(){ | |
219 | + std::stringstream ss; //create a string stream | |
220 | + ss<<dir()<<get_name(); //push the directory and filename to that stream | |
221 | + return ss.str(); //convert the stream to a string and return it | |
222 | + } | |
223 | + | |
224 | + //***************************************************************************************************************** | |
225 | + // output is the directory and the prefix and the extension of the files, which are looking for in that directory. | |
226 | + /// David: I have no idea what this is doing. It looks identical to dir() | |
227 | + std::string dir_fname(){ | |
228 | + std::stringstream ss; | |
229 | + | |
230 | + //if the path is absolute | |
231 | + if(absolute){ | |
232 | + //output the drive letter if in Windows | |
233 | + #ifdef _WIN32 | |
234 | + ss<<drive<<":"; | |
235 | + #endif | |
236 | + ss<<STIM_FILENAME_DIV; | |
237 | + } | |
238 | + | |
239 | + | |
240 | + for(unsigned int d = 0; d < path.size(); d++) | |
241 | + ss<<path[d]<<STIM_FILENAME_DIV; | |
242 | + ss<<get_name(); | |
243 | + | |
244 | + return ss.str(); | |
245 | + | |
246 | + } | |
247 | + | |
248 | + // output is the directory and the name of the file which are found in that given directory | |
249 | + std::string f_name(std::string file_name){ | |
250 | + std::stringstream ss; | |
251 | + | |
252 | + if(absolute){ //if the path is absolute | |
253 | + #ifdef _WIN32 | |
254 | + ss<<drive<<":"; //output the drive letter if in Windows | |
255 | + #endif | |
256 | + ss<<STIM_FILENAME_DIV; //output a path divider | |
257 | + } | |
258 | + | |
259 | + for(unsigned int d = 0; d < path.size(); d++) //for each directory in the current path | |
260 | + ss<<path[d]<<STIM_FILENAME_DIV; //add that directory, interspersing path dividers | |
261 | + | |
262 | + stim::filename fn = file_name; | |
263 | + std::string fn_prefix = fn.pref; | |
264 | + std::string fn_ext = fn.ext; | |
265 | + ss<<fn_prefix + '.' + fn_ext; | |
266 | + | |
267 | + return ss.str(); | |
268 | + | |
269 | + } | |
270 | + | |
271 | + /// Returns a list of files using the current filename as a template. | |
272 | + /// For example: | |
273 | + /// C:\this\is\a\path\file*.txt | |
274 | + /// can be used as a template to find a series of files file001.txt, file002.txt, file003.txt, etc. | |
275 | + std::vector<stim::filename> get_list(){ | |
276 | + //this is OS dependent, so we're starting with Windows | |
277 | + //the Unix version requires Boost | |
278 | + | |
279 | +#ifdef _WIN32 | |
280 | + stim::filename filepath(dir_fname()); //initialize filepath with the mask | |
281 | + | |
282 | + HANDLE hFind = INVALID_HANDLE_VALUE; //allocate data structures for looping through files | |
283 | + WIN32_FIND_DATAA FindFileData; | |
284 | + std::vector<stim::filename> file_list; //initialize a list to hold all matching filenames | |
285 | + | |
286 | + hFind = FindFirstFileA((filepath.str().c_str()), &FindFileData); //find the first file that matches the specified file path | |
287 | + | |
288 | + if (hFind == INVALID_HANDLE_VALUE) { //if there are no matching files | |
289 | + printf ("Invalid file handle. Error is %u.\n", GetLastError()); //print an error | |
290 | + } | |
291 | + else { | |
292 | + std::string file_name = FindFileData.cFileName; //save the file name | |
293 | + std::string file_path = dir(); //the file is in the specified directory, so save it | |
294 | + stim::filename current_file(file_path + file_name); //create a stim::filename structure representing this file | |
295 | + file_list.push_back(current_file); //push the new stim::filename to the file list | |
296 | + | |
297 | + // List all the other files in the directory. | |
298 | + while (FindNextFileA(hFind, &FindFileData) != 0){ //iterate until there are no more matching files | |
299 | + file_name = FindFileData.cFileName; //save the next file | |
300 | + current_file = (f_name(file_name)); //append the directory | |
301 | + file_list.push_back(current_file); //push it to the list | |
302 | + } | |
303 | + FindClose(hFind); //close the file data structure | |
304 | + } | |
305 | + return file_list; //return the list of files | |
306 | + | |
307 | +#elif BOOST_PRECOMPILED | |
308 | + | |
309 | + boost::filesystem::path p(dir()); //create a path from the current filename | |
310 | + std::vector<stim::filename> file_list; | |
311 | + if(boost::filesystem::exists(p)){ | |
312 | + if(boost::filesystem::is_directory(p)){ | |
313 | + typedef std::vector<boost::filesystem::path> vec; // store paths, | |
314 | + vec v; // so we can sort them later | |
315 | + std::copy(boost::filesystem::directory_iterator(p), boost::filesystem::directory_iterator(), back_inserter(v)); | |
316 | + std::sort(v.begin(), v.end()); // sort, since directory iteration | |
317 | + // is not ordered on some file systems | |
318 | + //compare file names to the current template (look for wild cards) | |
319 | + for (vec::const_iterator it(v.begin()), it_end(v.end()); it != it_end; ++it) | |
320 | + { | |
321 | + //if the filename is a wild card *or* it matches the read file name | |
322 | + if( prefix == "*" || prefix == (*it).filename().stem().string()){ | |
323 | + //if the extension is a wild card *or* it matches the read file extension | |
324 | + if( ext == "*" || "." + ext == (*it).filename().extension().string()){ | |
325 | + file_list.push_back((*it).string()); //include it in the final list | |
326 | + } | |
327 | + | |
328 | + } | |
329 | + | |
330 | + | |
331 | + | |
332 | + } | |
333 | + | |
334 | + } | |
335 | + | |
336 | + } | |
337 | + return file_list; | |
338 | +#else | |
339 | + std::cout<<"ERROR: UNIX systems don't support file lists without the Boost precompiled libraries."<<std::endl; | |
340 | + exit(1); | |
341 | +#endif | |
342 | + | |
343 | + } | |
344 | + //************************************************************************************************** | |
345 | + | |
346 | + //gets the current working directory | |
347 | + static stim::filename cwd(){ | |
348 | + | |
349 | + | |
350 | + char cCurrentPath[FILENAME_MAX]; | |
351 | + | |
352 | + if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))){ | |
353 | + std::cout<<"ERROR getting current working directory."<<std::endl; | |
354 | + exit(1); | |
355 | + } | |
356 | + | |
357 | + std::cout<<cCurrentPath<<std::endl; | |
358 | + return stim::filename(std::string(cCurrentPath) + STIM_FILENAME_DIV); | |
359 | + } | |
360 | + | |
361 | + void set_name(std::string fname){ | |
362 | + parse_name(fname); | |
363 | + } | |
364 | + | |
365 | + //append a string to the filename and return a new filename | |
366 | + stim::filename append(std::string s){ | |
367 | + stim::filename result = *this; //create a new filename, copy the current filename | |
368 | + result.pref = pref + s; //append the string to the filename | |
369 | + return result; | |
370 | + } | |
371 | + | |
372 | + //get a path relative to the current one | |
373 | + stim::filename get_relative(std::string rel){ | |
374 | + | |
375 | + std::vector<std::string> rel_path = stim::parser::split(rel, STIM_FILENAME_DIV); | |
376 | + | |
377 | + //if the relative path doesn't contain a file, add a blank string to be used as the filename | |
378 | + if(rel[rel.size()-1] == STIM_FILENAME_DIV) | |
379 | + rel_path.push_back(""); | |
380 | + | |
381 | + //create a stack representing the current absolute path | |
382 | + std::stack<std::string, std::vector<std::string> > s(path); | |
383 | + | |
384 | + //for each token in the relative path | |
385 | + for(int d=0; d<rel_path.size() - 1; d++){ | |
386 | + | |
387 | + //if the token is a double-dot, pop a directory off of the stack | |
388 | + if(rel_path[d] == "..") | |
389 | + s.pop(); | |
390 | + else | |
391 | + s.push(rel_path[d]); | |
392 | + } | |
393 | + | |
394 | + std::string* end = &s.top() + 1; | |
395 | + std::string* begin = end - s.size(); | |
396 | + std::vector<std::string> result_path(begin, end); | |
397 | + | |
398 | + //create a new path to be returned | |
399 | + stim::filename result = *this; | |
400 | + result.path = result_path; | |
401 | + result.set_name(rel_path.back()); | |
402 | + | |
403 | + return result; | |
404 | + } | |
405 | + | |
406 | + /// This function replaces a wildcard in the prefix with the specified string | |
407 | + stim::filename insert(std::string str){ | |
408 | + | |
409 | + stim::filename result = *this; //initialize the result filename to the current filename | |
410 | + size_t loc = result.pref.find('*'); //find a wild card in the string | |
411 | + if(loc == std::string::npos) //if a wildcard isn't found | |
412 | + result.pref += str; //append the value to the prefix | |
413 | + else | |
414 | + result.pref.replace(loc, 1, str); //replace the wildcard with the string | |
415 | + return result; //return the result | |
416 | + } | |
417 | + | |
418 | + stim::filename insert(size_t i, size_t n = 2){ | |
419 | + | |
420 | + std::stringstream ss; | |
421 | + ss << std::setw(n) << std::setfill('0') << i; | |
422 | + return insert(ss.str()); | |
423 | + } | |
424 | + | |
425 | + bool is_relative(){ | |
426 | + return !absolute; | |
427 | + } | |
428 | + | |
429 | + bool is_absolute(){ | |
430 | + return absolute; | |
431 | + } | |
432 | + | |
433 | + | |
434 | + | |
435 | + | |
436 | + | |
437 | + | |
438 | + | |
439 | + | |
440 | + | |
441 | +}; | |
442 | + | |
443 | + | |
444 | +} //end namespace stim | |
445 | + | |
446 | + | |
447 | +#endif | |
448 | + | ... | ... |