1 #ifndef FILESYSTEM_UTILS_H
2 #define FILESYSTEM_UTILS_H
3
4 #include <stdio.h>
5 #include <vector>
6 #include <string>
7 #include <algorithm>
8
9 #if _WIN32
10 #include <windows.h>
11 #include "win32dirent.h"
12 #else // _WIN32
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <unistd.h>
16 #include <dirent.h>
17 #endif // _WIN32
18
19 #if _WIN32
20 typedef std::wstring path_t;
21 #define PATHSTR(X) L##X
22 #else
23 typedef std::string path_t;
24 #define PATHSTR(X) X
25 #endif
26
27 #if _WIN32
path_is_directory(const path_t & path)28 static bool path_is_directory(const path_t& path)
29 {
30 DWORD attr = GetFileAttributesW(path.c_str());
31 return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
32 }
33
list_directory(const path_t & dirpath,std::vector<path_t> & imagepaths)34 static int list_directory(const path_t& dirpath, std::vector<path_t>& imagepaths)
35 {
36 imagepaths.clear();
37
38 _WDIR* dir = _wopendir(dirpath.c_str());
39 if (!dir)
40 {
41 fwprintf(stderr, L"opendir failed %ls\n", dirpath.c_str());
42 return -1;
43 }
44
45 struct _wdirent* ent = 0;
46 while ((ent = _wreaddir(dir)))
47 {
48 if (ent->d_type != DT_REG)
49 continue;
50
51 imagepaths.push_back(path_t(ent->d_name));
52 }
53
54 _wclosedir(dir);
55 std::sort(imagepaths.begin(), imagepaths.end());
56
57 return 0;
58 }
59 #else // _WIN32
path_is_directory(const path_t & path)60 static bool path_is_directory(const path_t& path)
61 {
62 struct stat s;
63 if (stat(path.c_str(), &s) != 0)
64 return false;
65 return S_ISDIR(s.st_mode);
66 }
67
list_directory(const path_t & dirpath,std::vector<path_t> & imagepaths)68 static int list_directory(const path_t& dirpath, std::vector<path_t>& imagepaths)
69 {
70 imagepaths.clear();
71
72 DIR* dir = opendir(dirpath.c_str());
73 if (!dir)
74 {
75 fprintf(stderr, "opendir failed %s\n", dirpath.c_str());
76 return -1;
77 }
78
79 struct dirent* ent = 0;
80 while ((ent = readdir(dir)))
81 {
82 if (ent->d_type != DT_REG)
83 continue;
84
85 imagepaths.push_back(path_t(ent->d_name));
86 }
87
88 closedir(dir);
89 std::sort(imagepaths.begin(), imagepaths.end());
90
91 return 0;
92 }
93 #endif // _WIN32
94
get_file_name_without_extension(const path_t & path)95 static path_t get_file_name_without_extension(const path_t& path)
96 {
97 size_t dot = path.rfind(PATHSTR('.'));
98 if (dot == path_t::npos)
99 return path;
100
101 return path.substr(0, dot);
102 }
103
get_file_extension(const path_t & path)104 static path_t get_file_extension(const path_t& path)
105 {
106 size_t dot = path.rfind(PATHSTR('.'));
107 if (dot == path_t::npos)
108 return path_t();
109
110 return path.substr(dot + 1);
111 }
112
113 #if _WIN32
get_executable_directory()114 static path_t get_executable_directory()
115 {
116 wchar_t filepath[256];
117 GetModuleFileNameW(NULL, filepath, 256);
118
119 wchar_t* backslash = wcsrchr(filepath, L'\\');
120 backslash[1] = L'\0';
121
122 return path_t(filepath);
123 }
124 #else // _WIN32
get_executable_directory()125 static path_t get_executable_directory()
126 {
127 char filepath[256];
128 readlink("/proc/self/exe", filepath, 256);
129
130 char* slash = strrchr(filepath, '/');
131 slash[1] = '\0';
132
133 return path_t(filepath);
134 }
135 #endif // _WIN32
136
filepath_is_readable(const path_t & path)137 static bool filepath_is_readable(const path_t& path)
138 {
139 #if _WIN32
140 FILE* fp = _wfopen(path.c_str(), L"rb");
141 #else // _WIN32
142 FILE* fp = fopen(path.c_str(), "rb");
143 #endif // _WIN32
144 if (!fp)
145 return false;
146
147 fclose(fp);
148 return true;
149 }
150
sanitize_filepath(const path_t & path)151 static path_t sanitize_filepath(const path_t& path)
152 {
153 if (filepath_is_readable(path))
154 return path;
155
156 return get_executable_directory() + path;
157 }
158
159 #endif // FILESYSTEM_UTILS_H
160