1 // ----------------------------------------------------------------------------
2 // - Open3D: www.open3d.org -
3 // ----------------------------------------------------------------------------
4 // The MIT License (MIT)
5 //
6 // Copyright (c) 2018 www.open3d.org
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // ----------------------------------------------------------------------------
26
27 #include "FileSystem.h"
28
29 #include <algorithm>
30 #include <cstdio>
31 #include <cstdlib>
32 #ifdef WINDOWS
33 #include <dirent/dirent.h>
34 #include <direct.h>
35 #ifndef PATH_MAX
36 #define PATH_MAX MAX_PATH
37 #endif
38 #else
39 #include <sys/stat.h>
40 #include <dirent.h>
41 #include <unistd.h>
42 #include <limits.h>
43 #endif
44
45 namespace three{
46
47 namespace filesystem {
48
GetFileExtensionInLowerCase(const std::string & filename)49 std::string GetFileExtensionInLowerCase(const std::string &filename)
50 {
51 size_t dot_pos = filename.find_last_of(".");
52 if (dot_pos == std::string::npos || dot_pos == filename.length() - 1) {
53 return "";
54 }
55 std::string filename_ext = filename.substr(dot_pos + 1);
56 if (filename_ext.find_first_of("/\\") != std::string::npos) {
57 return "";
58 }
59 std::transform(filename_ext.begin(), filename_ext.end(),
60 filename_ext.begin(), ::tolower);
61 return filename_ext;
62 }
63
GetFileNameWithoutExtension(const std::string & filename)64 std::string GetFileNameWithoutExtension(const std::string &filename)
65 {
66 std::string ext = GetFileExtensionInLowerCase(filename);
67 if (ext.length() >= filename.length() - 1) {
68 return "";
69 } else {
70 return filename.substr(0, filename.length() - ext.length() - 1);
71 }
72 }
73
GetFileNameWithoutDirectory(const std::string & filename)74 std::string GetFileNameWithoutDirectory(const std::string &filename)
75 {
76 size_t slash_pos = filename.find_last_of("/\\");
77 if (slash_pos == std::string::npos) {
78 return filename;
79 } else {
80 return filename.substr(slash_pos + 1);
81 }
82 }
83
GetFileParentDirectory(const std::string & filename)84 std::string GetFileParentDirectory(const std::string &filename)
85 {
86 size_t slash_pos = filename.find_last_of("/\\");
87 if (slash_pos == std::string::npos) {
88 return "";
89 } else {
90 return filename.substr(0, slash_pos + 1);
91 }
92 }
93
GetRegularizedDirectoryName(const std::string & directory)94 std::string GetRegularizedDirectoryName(const std::string &directory)
95 {
96 if (directory.back() != '/' && directory.back() != '\\') {
97 return directory + "/";
98 } else {
99 return directory;
100 }
101 }
102
GetWorkingDirectory()103 std::string GetWorkingDirectory()
104 {
105 char buff[PATH_MAX + 1];
106 getcwd(buff, PATH_MAX + 1);
107 return std::string(buff);
108 }
109
ChangeWorkingDirectory(const std::string & directory)110 bool ChangeWorkingDirectory(const std::string &directory)
111 {
112 return (chdir(directory.c_str()) == 0);
113 }
114
DirectoryExists(const std::string & directory)115 bool DirectoryExists(const std::string &directory)
116 {
117 struct stat info;
118 if (stat(directory.c_str(), &info) == -1)
119 return false;
120 return S_ISDIR(info.st_mode);
121 }
122
MakeDirectory(const std::string & directory)123 bool MakeDirectory(const std::string &directory)
124 {
125 #ifdef WINDOWS
126 return (_mkdir(directory.c_str()) == 0);
127 #else
128 return (mkdir(directory.c_str(), S_IRWXU) == 0);
129 #endif
130 }
131
MakeDirectoryHierarchy(const std::string & directory)132 bool MakeDirectoryHierarchy(const std::string &directory)
133 {
134 std::string full_path = GetRegularizedDirectoryName(directory);
135 size_t curr_pos = full_path.find_first_of("/\\", 1);
136 while (curr_pos != std::string::npos) {
137 std::string subdir = full_path.substr(0, curr_pos + 1);
138 if (DirectoryExists(subdir) == false) {
139 if (MakeDirectory(subdir) == false) {
140 return false;
141 }
142 }
143 curr_pos = full_path.find_first_of("/\\", curr_pos + 1);
144 }
145 return true;
146 }
147
DeleteDirectory(const std::string & directory)148 bool DeleteDirectory(const std::string &directory)
149 {
150 #ifdef WINDOWS
151 return (_rmdir(directory.c_str()) == 0);
152 #else
153 return (rmdir(directory.c_str()) == 0);
154 #endif
155 }
156
FileExists(const std::string & filename)157 bool FileExists(const std::string &filename)
158 {
159 #ifdef WINDOWS
160 struct _stat64 info;
161 if (_stat64(filename.c_str(), &info) == -1)
162 return false;
163 return S_ISREG(info.st_mode);
164 #else
165 struct stat info;
166 if (stat(filename.c_str(), &info) == -1)
167 return false;
168 return S_ISREG(info.st_mode);
169 #endif
170 }
171
RemoveFile(const std::string & filename)172 bool RemoveFile(const std::string &filename)
173 {
174 return (std::remove(filename.c_str()) == 0);
175 }
176
ListFilesInDirectory(const std::string & directory,std::vector<std::string> & filenames)177 bool ListFilesInDirectory(const std::string &directory,
178 std::vector<std::string> &filenames)
179 {
180 if (directory.empty()) {
181 return false;
182 }
183 DIR *dir;
184 struct dirent *ent;
185 struct stat st;
186 dir = opendir(directory.c_str());
187 if (!dir) {
188 return false;
189 }
190 filenames.clear();
191 while ((ent = readdir(dir)) != NULL) {
192 const std::string file_name = ent->d_name;
193 if (file_name[0] == '.')
194 continue;
195 std::string full_file_name = GetRegularizedDirectoryName(directory) +
196 file_name;
197 if (stat(full_file_name.c_str(), &st) == -1)
198 continue;
199 if (S_ISREG(st.st_mode))
200 filenames.push_back(full_file_name);
201 }
202 closedir(dir);
203 return true;
204 }
205
ListFilesInDirectoryWithExtension(const std::string & directory,const std::string & extname,std::vector<std::string> & filenames)206 bool ListFilesInDirectoryWithExtension(const std::string &directory,
207 const std::string &extname, std::vector<std::string> &filenames)
208 {
209 std::vector<std::string> all_files;
210 if (ListFilesInDirectory(directory, all_files) == false) {
211 return false;
212 }
213 std::string ext_in_lower = extname;
214 std::transform(ext_in_lower.begin(), ext_in_lower.end(),
215 ext_in_lower.begin(), ::tolower);
216 filenames.clear();
217 for (const auto &fn : all_files) {
218 if (GetFileExtensionInLowerCase(fn) == ext_in_lower) {
219 filenames.push_back(fn);
220 }
221 }
222 return true;
223 }
224
225 } // namespace three::filesystem
226
227 } // namespace three
228