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