#ifndef STIM_FILENAME_H #define STIM_FILENAME_H #include /* defines FILENAME_MAX */ #include #include #include #include #include #include // set OS dependent defines, including: // 1) path division character ('/' or '\') used for output only // 2) command for getting the current working directory // 3) header files for getting the current working directory // 4) include BOOST filesystem class if compiling on GCC #define STIM_DIV '/' #ifdef _WIN32 #include #include #define GetCurrentDir _getcwd #define STIM_FILENAME_DIV '\\' #else #ifdef BOOST_PRECOMPILED #include #endif #include #define GetCurrentDir getcwd #define STIM_FILENAME_DIV '/' #endif namespace stim{ class filepath{ protected: std::string _drive; //drive on which the file is located (used for Windows) std::vector _path; //path for the specified file (list of hierarchical directories) /// replaces win32 dividers with the Linux standard (used internally by default) std::string unix_div(std::string s) { std::replace( s.begin(), s.end(), '\\', '/'); return s; } /// gets the directory hierarchy for the current working directory static std::string cwd(){ char cCurrentPath[FILENAME_MAX]; if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))){ std::cout<<"ERROR getting current working directory."< &absolute, std::vector relative){ std::string current = cwd(); //get the current directory as a string std::string current_drive; std::vector current_dir; parse_path(current_drive, current_dir, current); //get the current drive and directories // step through each directory in the relative path, adjusting the current directory // index depending on whether the relative path is specified with '.' or '..' int current_i = (int)current_dir.size() - 1; int relative_i; for(relative_i = 0; relative_i < relative.size(); relative_i++){ if(relative[relative_i] == "..") current_i--; else if(relative[relative_i] != ".") break; } if(current_i < 0){ std::cerr<<"ERROR stim::filepath - relative path is incompatible with working directory"< &absolute, std::string dir){ drive = ""; //initialize the drive to NULL (it will stay that way for Windows) std::vector path; bool relative = true; //the default path is relative if(dir.length() == 0) return; //return if the file locator is empty std::string unix_dir = unix_div(dir); //replace any Windows division characters with Unix if(unix_dir.length() > 1 && unix_dir[1] == ':'){ //if a drive identifier is given if(unix_dir[0] > 64 && unix_dir[0] < 91) //if the drive letter is upper case _drive = unix_dir[0] + 32; //convert it to lower case else if(unix_dir[0] > 96 && unix_dir[0] < 123) //if the drive character is lower case _drive = unix_dir[0]; //store it as-is else{ //otherwise throw an error std::cerr<<"ERROR stim::filename - drive letter is invalid: "< get_list(){ //this is OS dependent, so we're starting with Windows //the Unix version requires Boost #ifdef _WIN32 HANDLE hFind = INVALID_HANDLE_VALUE; //allocate data structures for looping through files WIN32_FIND_DATAA FindFileData; std::vector file_list; //initialize a list to hold all matching filenames std::string path_string = str(); hFind = FindFirstFileA(path_string.c_str(), &FindFileData); //find the first file that matches the specified file path if (hFind == INVALID_HANDLE_VALUE) { //if there are no matching files //printf ("Invalid file handle. Error is %u.\n", GetLastError()); //print an error return file_list; } else { std::string file_name = FindFileData.cFileName; //save the file name std::string file_path = path(); //the file is in the specified directory, so save it stim::filename current_file(file_path + file_name); //create a stim::filename structure representing this file if(!(FindFileData.cFileName[0] == '.' && FindFileData.cFileName[1] == '\0')) file_list.push_back(current_file); //push the new stim::filename to the file list // List all the other files in the directory. while (FindNextFileA(hFind, &FindFileData) != 0){ //iterate until there are no more matching files if(!(FindFileData.cFileName[0] == '.' && FindFileData.cFileName[1] == '.' && FindFileData.cFileName[2] == '\0')){ //account for the possibility of the '..' filename file_name = FindFileData.cFileName; //save the next file current_file = fname(file_name); //append the directory file_list.push_back(current_file); //push it to the list } } FindClose(hFind); //close the file data structure } return file_list; //return the list of files #elif BOOST_PRECOMPILED boost::filesystem::path p(path()); //create a path from the current filename std::vector file_list; if(boost::filesystem::exists(p)){ if(boost::filesystem::is_directory(p)){ typedef std::vector vec; // store paths, vec v; // so we can sort them later std::copy(boost::filesystem::directory_iterator(p), boost::filesystem::directory_iterator(), back_inserter(v)); std::sort(v.begin(), v.end()); // sort, since directory iteration // is not ordered on some file systems //compare file names to the current template (look for wild cards) for (vec::const_iterator it(v.begin()), it_end(v.end()); it != it_end; ++it) { //if the filename is a wild card *or* it matches the read file name if( _prefix == "*" || _prefix == (*it).filename().stem().string()){ //if the extension is a wild card *or* it matches the read file extension if( _extension == "*" || "." + _extension == (*it).filename().extension().string()){ file_list.push_back((*it).string()); //include it in the final list } } } } } return file_list; #else std::cout<<"ERROR: UNIX systems don't support file lists without the Boost precompiled libraries."<