1 /*! 2 @file 3 @author Albert Semenov 4 @date 09/2009 5 @module 6 */ 7 #ifndef FILE_SYSTEM_INFO_H_ 8 #define FILE_SYSTEM_INFO_H_ 9 10 #include <MyGUI.h> 11 #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32 12 #include <windows.h> 13 #include <io.h> 14 #else 15 #include <unistd.h> 16 #include <dirent.h> 17 #include <sys/types.h> 18 #include <sys/stat.h> 19 #include <unistd.h> 20 #include <fnmatch.h> 21 #endif 22 23 #include <string> 24 #include <vector> 25 #include <locale> 26 27 namespace common 28 { 29 30 struct FileInfo 31 { FileInfoFileInfo32 FileInfo(const std::wstring& _name, bool _folder) : name(_name), folder(_folder) { } 33 std::wstring name; 34 bool folder; 35 }; 36 typedef std::vector<FileInfo> VectorFileInfo; 37 toLower(const std::wstring & _input)38 inline std::wstring toLower(const std::wstring& _input) 39 { 40 std::wstring result; 41 result.resize(_input.size()); 42 static std::locale sLocale(""); 43 for (unsigned int i=0; i<_input.size(); ++i) 44 result[i] = std::tolower(_input[i], sLocale); 45 return result; 46 } 47 sortFiles(const common::FileInfo & left,const common::FileInfo & right)48 inline bool sortFiles(const common::FileInfo& left, const common::FileInfo& right) 49 { 50 if (left.folder < right.folder) 51 return true; 52 if (left.folder > right.folder) 53 return false; 54 55 return toLower(left.name) < toLower(right.name); 56 } 57 isAbsolutePath(const wchar_t * path)58 inline bool isAbsolutePath(const wchar_t* path) 59 { 60 #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32 61 if (IsCharAlphaW(path[0]) && path[1] == ':') 62 return true; 63 #endif 64 return path[0] == '/' || path[0] == '\\'; 65 } 66 endWith(const std::wstring & _source,const std::wstring & _value)67 inline bool endWith(const std::wstring& _source, const std::wstring& _value) 68 { 69 size_t count = _value.size(); 70 if (_source.size() < count) 71 return false; 72 size_t offset = _source.size() - count; 73 for (size_t index = 0; index < count; ++ index) 74 { 75 if (_source[index + offset] != _value[index]) 76 return false; 77 } 78 return true; 79 } 80 concatenatePath(const std::wstring & _base,const std::wstring & _name)81 inline std::wstring concatenatePath(const std::wstring& _base, const std::wstring& _name) 82 { 83 if (_base.empty() || isAbsolutePath(_name.c_str())) 84 { 85 return _name; 86 } 87 else 88 { 89 if (endWith(_base, L"\\") || endWith(_base, L"/")) 90 return _base + _name; 91 92 #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32 93 return _base + L'\\' + _name; 94 #else 95 return _base + L'/' + _name; 96 #endif 97 } 98 } 99 isReservedDir(const wchar_t * _fn)100 inline bool isReservedDir (const wchar_t* _fn) 101 { 102 // if "." 103 return (_fn [0] == '.' && _fn [1] == 0); 104 } 105 isParentDir(const wchar_t * _fn)106 inline bool isParentDir (const wchar_t* _fn) 107 { 108 // if ".." 109 return (_fn [0] == '.' && _fn [1] == '.' && _fn [2] == 0); 110 } 111 112 inline void getSystemFileList(VectorFileInfo& _result, const std::wstring& _folder, const std::wstring& _mask, bool _sorted = true) 113 { 114 #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32 115 //FIXME add optional parameter? 116 bool ms_IgnoreHidden = true; 117 118 intptr_t lHandle; 119 int res; 120 struct _wfinddata_t tagData; 121 122 // pattern can contain a directory name, separate it from mask 123 size_t pos = _mask.find_last_of(L"/\\"); 124 std::wstring directory; 125 if (pos != _mask.npos) 126 directory = _mask.substr (0, pos); 127 128 std::wstring full_mask = concatenatePath(_folder, _mask); 129 130 lHandle = _wfindfirst(full_mask.c_str(), &tagData); 131 res = 0; 132 while (lHandle != -1 && res != -1) 133 { 134 if (( !ms_IgnoreHidden || (tagData.attrib & _A_HIDDEN) == 0 ) && 135 !isReservedDir(tagData.name)) 136 { 137 _result.push_back(FileInfo(concatenatePath(directory, tagData.name), (tagData.attrib & _A_SUBDIR) != 0)); 138 } 139 res = _wfindnext( lHandle, &tagData ); 140 } 141 // Close if we found any files 142 if (lHandle != -1) 143 _findclose(lHandle); 144 #else 145 DIR* dir = opendir(MyGUI::UString(_folder).asUTF8_c_str()); 146 struct dirent* dp; 147 148 if (dir == nullptr) 149 { 150 /* opendir() failed */ 151 MYGUI_LOG(Error, (std::string("Can't open ") + MyGUI::UString(_folder).asUTF8_c_str())); 152 return; 153 } 154 155 rewinddir (dir); 156 157 while ((dp = readdir (dir)) != nullptr) 158 { 159 if ((fnmatch(MyGUI::UString(_mask).asUTF8_c_str(), dp->d_name, 0) == 0) && !isReservedDir(MyGUI::UString(dp->d_name).asWStr_c_str())) 160 { 161 struct stat fInfo; 162 std::string path = MyGUI::UString(_folder).asUTF8() + "/" + dp->d_name; 163 if (stat(path.c_str(), &fInfo) == -1)perror("stat"); 164 _result.push_back(FileInfo(MyGUI::UString(dp->d_name).asWStr(), (S_ISDIR(fInfo.st_mode)))); 165 } 166 } 167 168 closedir(dir); 169 #endif 170 if (_sorted) 171 { 172 std::sort(_result.begin(), _result.end(), sortFiles); 173 } 174 } 175 getSystemCurrentFolder()176 inline std::wstring getSystemCurrentFolder() 177 { 178 #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32 179 wchar_t buff[MAX_PATH+1]; 180 ::GetCurrentDirectoryW(MAX_PATH, buff); 181 return buff; 182 #else 183 # ifndef PATH_MAX 184 # define PATH_MAX 256 185 # endif 186 char buff[PATH_MAX+1]; 187 return getcwd(buff, PATH_MAX) ? MyGUI::UString(buff).asWStr() : std::wstring(); 188 #endif 189 } 190 191 typedef std::vector<std::wstring> VectorWString; scanFolder(VectorWString & _result,const std::wstring & _folder,bool _recursive,const std::wstring & _mask,bool _fullpath)192 inline void scanFolder(VectorWString& _result, const std::wstring& _folder, bool _recursive, const std::wstring& _mask, bool _fullpath) 193 { 194 std::wstring folder = _folder; 195 if (!folder.empty() && *folder.rbegin() != '/' && *folder.rbegin() != '\\') folder += L"/"; 196 197 VectorFileInfo result; 198 getSystemFileList(result, folder, _mask); 199 200 for (VectorFileInfo::const_iterator item = result.begin(); item != result.end(); ++item) 201 { 202 if (item->folder) continue; 203 204 if (_fullpath) 205 _result.push_back(folder + item->name); 206 else 207 _result.push_back(item->name); 208 } 209 210 if (_recursive) 211 { 212 getSystemFileList(result, folder, L"*"); 213 214 for (VectorFileInfo::const_iterator item = result.begin(); item != result.end(); ++item) 215 { 216 if (!item->folder 217 || item->name == L".." 218 || item->name == L".") continue; 219 scanFolder(_result, folder + item->name, _recursive, _mask, _fullpath); 220 } 221 222 } 223 } 224 225 } 226 227 #endif // FILE_SYSTEM_INFO_H_ 228