1 | /*M/////////////////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. |
4 | // |
5 | // By downloading, copying, installing or using the software you agree to this license. |
6 | // If you do not agree to this license, do not download, install, |
7 | // copy or use the software. |
8 | // |
9 | // |
10 | // License Agreement |
11 | // For Open Source Computer Vision Library |
12 | // |
13 | // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. |
14 | // Copyright (C) 2008-2013, Willow Garage Inc., all rights reserved. |
15 | // Third party copyrights are property of their respective owners. |
16 | // |
17 | // Redistribution and use in source and binary forms, with or without modification, |
18 | // are permitted provided that the following conditions are met: |
19 | // |
20 | // * Redistribution's of source code must retain the above copyright notice, |
21 | // this list of conditions and the following disclaimer. |
22 | // |
23 | // * Redistribution's in binary form must reproduce the above copyright notice, |
24 | // this list of conditions and the following disclaimer in the documentation |
25 | // and / or other materials provided with the distribution. |
26 | // |
27 | // * The name of the copyright holders may not be used to endorse or promote products |
28 | // derived from this software without specific prior written permission. |
29 | // |
30 | // This software is provided by the copyright holders and contributors "as is" and |
31 | // any express or implied warranties, including, but not limited to, the implied |
32 | // warranties of merchantability and fitness for a particular purpose are disclaimed. |
33 | // In no event shall the Intel Corporation or contributors be liable for any direct, |
34 | // indirect, incidental, special, exemplary, or consequential damages |
35 | // (including, but not limited to, procurement of substitute goods or services; |
36 | // loss of use, data, or profits; or business interruption) however caused |
37 | // and on any theory of liability, whether in contract, strict liability, |
38 | // or tort (including negligence or otherwise) arising in any way out of |
39 | // the use of this software, even if advised of the possibility of such damage. |
40 | // |
41 | //M*/ |
42 | |
43 | #include "precomp.hpp" |
44 | |
45 | #include "opencv2/core/utils/filesystem.hpp" |
46 | #include "opencv2/core/utils/filesystem.private.hpp" |
47 | |
48 | #if OPENCV_HAVE_FILESYSTEM_SUPPORT |
49 | #if defined _WIN32 || defined WINCE |
50 | # include <windows.h> |
51 | const char dir_separators[] = "/\\" ; |
52 | |
53 | namespace |
54 | { |
55 | struct dirent |
56 | { |
57 | const char* d_name; |
58 | }; |
59 | |
60 | struct DIR |
61 | { |
62 | #if defined(WINRT) || defined(_WIN32_WCE) |
63 | WIN32_FIND_DATAW data; |
64 | #else |
65 | WIN32_FIND_DATAA data; |
66 | #endif |
67 | HANDLE handle; |
68 | dirent ent; |
69 | #ifdef WINRT |
70 | DIR() { } |
71 | ~DIR() |
72 | { |
73 | if (ent.d_name) |
74 | delete[] ent.d_name; |
75 | } |
76 | #endif |
77 | }; |
78 | |
79 | DIR* opendir(const char* path) |
80 | { |
81 | DIR* dir = new DIR; |
82 | dir->ent.d_name = 0; |
83 | #if defined(WINRT) || defined(_WIN32_WCE) |
84 | cv::String full_path = cv::String(path) + "\\*" ; |
85 | wchar_t wfull_path[MAX_PATH]; |
86 | size_t copied = mbstowcs(wfull_path, full_path.c_str(), MAX_PATH); |
87 | CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1)); |
88 | dir->handle = ::FindFirstFileExW(wfull_path, FindExInfoStandard, |
89 | &dir->data, FindExSearchNameMatch, NULL, 0); |
90 | #else |
91 | dir->handle = ::FindFirstFileExA((cv::String(path) + "\\*" ).c_str(), |
92 | FindExInfoStandard, &dir->data, FindExSearchNameMatch, NULL, 0); |
93 | #endif |
94 | if(dir->handle == INVALID_HANDLE_VALUE) |
95 | { |
96 | /*closedir will do all cleanup*/ |
97 | delete dir; |
98 | return 0; |
99 | } |
100 | return dir; |
101 | } |
102 | |
103 | dirent* readdir(DIR* dir) |
104 | { |
105 | #if defined(WINRT) || defined(_WIN32_WCE) |
106 | if (dir->ent.d_name != 0) |
107 | { |
108 | if (::FindNextFileW(dir->handle, &dir->data) != TRUE) |
109 | return 0; |
110 | } |
111 | size_t asize = wcstombs(NULL, dir->data.cFileName, 0); |
112 | CV_Assert((asize != 0) && (asize != (size_t)-1)); |
113 | char* aname = new char[asize+1]; |
114 | aname[asize] = 0; |
115 | wcstombs(aname, dir->data.cFileName, asize); |
116 | dir->ent.d_name = aname; |
117 | #else |
118 | if (dir->ent.d_name != 0) |
119 | { |
120 | if (::FindNextFileA(dir->handle, &dir->data) != TRUE) |
121 | return 0; |
122 | } |
123 | dir->ent.d_name = dir->data.cFileName; |
124 | #endif |
125 | return &dir->ent; |
126 | } |
127 | |
128 | void closedir(DIR* dir) |
129 | { |
130 | ::FindClose(dir->handle); |
131 | delete dir; |
132 | } |
133 | |
134 | |
135 | } |
136 | #else // defined _WIN32 || defined WINCE |
137 | # include <dirent.h> |
138 | # include <sys/stat.h> |
139 | const char dir_separators[] = "/" ; |
140 | #endif // defined _WIN32 || defined WINCE |
141 | #endif // OPENCV_HAVE_FILESYSTEM_SUPPORT |
142 | |
143 | |
144 | #if OPENCV_HAVE_FILESYSTEM_SUPPORT |
145 | static bool isDir(const cv::String& path, DIR* dir) |
146 | { |
147 | #if defined _WIN32 || defined _WIN32_WCE |
148 | DWORD attributes; |
149 | BOOL status = TRUE; |
150 | if (dir) |
151 | attributes = dir->data.dwFileAttributes; |
152 | else |
153 | { |
154 | WIN32_FILE_ATTRIBUTE_DATA all_attrs; |
155 | #if defined WINRT || defined _WIN32_WCE |
156 | wchar_t wpath[MAX_PATH]; |
157 | size_t copied = mbstowcs(wpath, path.c_str(), MAX_PATH); |
158 | CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1)); |
159 | status = ::GetFileAttributesExW(wpath, GetFileExInfoStandard, &all_attrs); |
160 | #else |
161 | status = ::GetFileAttributesExA(path.c_str(), GetFileExInfoStandard, &all_attrs); |
162 | #endif |
163 | attributes = all_attrs.dwFileAttributes; |
164 | } |
165 | |
166 | return status && ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); |
167 | #else |
168 | CV_UNUSED(dir); |
169 | struct stat stat_buf; |
170 | if (0 != stat( file: path.c_str(), buf: &stat_buf)) |
171 | return false; |
172 | int is_dir = S_ISDIR( stat_buf.st_mode); |
173 | return is_dir != 0; |
174 | #endif |
175 | } |
176 | #endif // OPENCV_HAVE_FILESYSTEM_SUPPORT |
177 | |
178 | bool cv::utils::fs::isDirectory(const cv::String& path) |
179 | { |
180 | #if OPENCV_HAVE_FILESYSTEM_SUPPORT |
181 | CV_INSTRUMENT_REGION(); |
182 | return isDir(path, NULL); |
183 | #else |
184 | CV_UNUSED(path); |
185 | CV_Error(Error::StsNotImplemented, "File system support is disabled in this OpenCV build!" ); |
186 | #endif |
187 | } |
188 | |
189 | #if OPENCV_HAVE_FILESYSTEM_SUPPORT |
190 | static bool wildcmp(const char *string, const char *wild) |
191 | { |
192 | // Based on wildcmp written by Jack Handy - <A href="mailto:jakkhandy@hotmail.com">jakkhandy@hotmail.com</A> |
193 | const char *cp = 0, *mp = 0; |
194 | |
195 | while ((*string) && (*wild != '*')) |
196 | { |
197 | if ((*wild != *string) && (*wild != '?')) |
198 | { |
199 | return false; |
200 | } |
201 | |
202 | wild++; |
203 | string++; |
204 | } |
205 | |
206 | while (*string) |
207 | { |
208 | if (*wild == '*') |
209 | { |
210 | if (!*++wild) |
211 | { |
212 | return true; |
213 | } |
214 | |
215 | mp = wild; |
216 | cp = string + 1; |
217 | } |
218 | else if ((*wild == *string) || (*wild == '?')) |
219 | { |
220 | wild++; |
221 | string++; |
222 | } |
223 | else |
224 | { |
225 | wild = mp; |
226 | string = cp++; |
227 | } |
228 | } |
229 | |
230 | while (*wild == '*') |
231 | { |
232 | wild++; |
233 | } |
234 | |
235 | return *wild == 0; |
236 | } |
237 | |
238 | static void glob_rec(const cv::String& directory, const cv::String& wildchart, std::vector<cv::String>& result, |
239 | bool recursive, bool includeDirectories, const cv::String& pathPrefix) |
240 | { |
241 | DIR *dir; |
242 | |
243 | if ((dir = opendir (name: directory.c_str())) != 0) |
244 | { |
245 | /* find all the files and directories within directory */ |
246 | try |
247 | { |
248 | struct dirent *ent; |
249 | while ((ent = readdir (dirp: dir)) != 0) |
250 | { |
251 | const char* name = ent->d_name; |
252 | if((name[0] == 0) || (name[0] == '.' && name[1] == 0) || (name[0] == '.' && name[1] == '.' && name[2] == 0)) |
253 | continue; |
254 | |
255 | cv::String path = cv::utils::fs::join(base: directory, path: name); |
256 | cv::String entry = cv::utils::fs::join(base: pathPrefix, path: name); |
257 | |
258 | if (isDir(path, dir)) |
259 | { |
260 | if (recursive) |
261 | glob_rec(directory: path, wildchart, result, recursive, includeDirectories, pathPrefix: entry); |
262 | if (!includeDirectories) |
263 | continue; |
264 | } |
265 | |
266 | if (wildchart.empty() || wildcmp(string: name, wild: wildchart.c_str())) |
267 | result.push_back(x: entry); |
268 | } |
269 | } |
270 | catch (...) |
271 | { |
272 | closedir(dirp: dir); |
273 | throw; |
274 | } |
275 | closedir(dirp: dir); |
276 | } |
277 | else |
278 | { |
279 | CV_Error_(cv::Error::StsObjectNotFound, ("could not open directory: %s" , directory.c_str())); |
280 | } |
281 | } |
282 | #endif // OPENCV_HAVE_FILESYSTEM_SUPPORT |
283 | |
284 | void cv::glob(String pattern, std::vector<String>& result, bool recursive) |
285 | { |
286 | #if OPENCV_HAVE_FILESYSTEM_SUPPORT |
287 | CV_INSTRUMENT_REGION(); |
288 | |
289 | result.clear(); |
290 | String path, wildchart; |
291 | |
292 | if (isDir(path: pattern, dir: 0)) |
293 | { |
294 | if(strchr(s: dir_separators, c: pattern[pattern.size() - 1]) != 0) |
295 | { |
296 | path = pattern.substr(pos: 0, n: pattern.size() - 1); |
297 | } |
298 | else |
299 | { |
300 | path = pattern; |
301 | } |
302 | } |
303 | else |
304 | { |
305 | size_t pos = pattern.find_last_of(s: dir_separators); |
306 | if (pos == String::npos) |
307 | { |
308 | wildchart = pattern; |
309 | path = "." ; |
310 | } |
311 | else |
312 | { |
313 | path = pattern.substr(pos: 0, n: pos); |
314 | wildchart = pattern.substr(pos: pos + 1); |
315 | } |
316 | } |
317 | |
318 | glob_rec(directory: path, wildchart, result, recursive, includeDirectories: false, pathPrefix: path); |
319 | std::sort(first: result.begin(), last: result.end()); |
320 | #else // OPENCV_HAVE_FILESYSTEM_SUPPORT |
321 | CV_UNUSED(pattern); |
322 | CV_UNUSED(result); |
323 | CV_UNUSED(recursive); |
324 | CV_Error(Error::StsNotImplemented, "File system support is disabled in this OpenCV build!" ); |
325 | #endif // OPENCV_HAVE_FILESYSTEM_SUPPORT |
326 | } |
327 | |
328 | void cv::utils::fs::glob(const cv::String& directory, const cv::String& pattern, |
329 | std::vector<cv::String>& result, |
330 | bool recursive, bool includeDirectories) |
331 | { |
332 | #if OPENCV_HAVE_FILESYSTEM_SUPPORT |
333 | glob_rec(directory, wildchart: pattern, result, recursive, includeDirectories, pathPrefix: directory); |
334 | std::sort(first: result.begin(), last: result.end()); |
335 | #else // OPENCV_HAVE_FILESYSTEM_SUPPORT |
336 | CV_UNUSED(directory); |
337 | CV_UNUSED(pattern); |
338 | CV_UNUSED(result); |
339 | CV_UNUSED(recursive); |
340 | CV_UNUSED(includeDirectories); |
341 | CV_Error(Error::StsNotImplemented, "File system support is disabled in this OpenCV build!" ); |
342 | #endif // OPENCV_HAVE_FILESYSTEM_SUPPORT |
343 | } |
344 | |
345 | void cv::utils::fs::glob_relative(const cv::String& directory, const cv::String& pattern, |
346 | std::vector<cv::String>& result, |
347 | bool recursive, bool includeDirectories) |
348 | { |
349 | #if OPENCV_HAVE_FILESYSTEM_SUPPORT |
350 | glob_rec(directory, wildchart: pattern, result, recursive, includeDirectories, pathPrefix: cv::String()); |
351 | std::sort(first: result.begin(), last: result.end()); |
352 | #else // OPENCV_HAVE_FILESYSTEM_SUPPORT |
353 | CV_UNUSED(directory); |
354 | CV_UNUSED(pattern); |
355 | CV_UNUSED(result); |
356 | CV_UNUSED(recursive); |
357 | CV_UNUSED(includeDirectories); |
358 | CV_Error(Error::StsNotImplemented, "File system support is disabled in this OpenCV build!" ); |
359 | #endif // OPENCV_HAVE_FILESYSTEM_SUPPORT |
360 | } |
361 | |