Visualization Library 2.1.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
DiskDirectory.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #include <vlCore/DiskDirectory.hpp>
33 #include <vlCore/DiskFile.hpp>
34 #include <algorithm>
35 
36 #if defined(__GNUG__)
37  #include <sys/types.h>
38  #include <dirent.h>
39  #if defined(__APPLE__) || (__FreeBSD__)
40  #define dirent64 dirent
41  #define readdir64_r readdir_r
42  #endif
43 #endif
44 
45 using namespace vl;
46 
47 //-----------------------------------------------------------------------------
48 // DiskDirectory
49 //-----------------------------------------------------------------------------
51 {
52  setPath(name);
53 }
54 //-----------------------------------------------------------------------------
56 {
57 }
58 //-----------------------------------------------------------------------------
59 void DiskDirectory::listFilesRecursive(std::vector<String>& file_list) const
60 {
61  file_list.clear();
62  listFilesRecursive_internal(file_list);
63 }
64 //-----------------------------------------------------------------------------
66 {
67  if (path().empty())
68  {
69  Log::error( "VirtualDirectory::path() must not be empty!\n" );
70  return NULL;
71  }
72 
73  std::vector<String> dir_list;
74  String p = translatePath(subdir_name).right(-path().length()-1);
75  this->listSubDirs(dir_list);
76  String cur_p = path();
77  for(int i=0; i<(int)dir_list.size(); ++i)
78  {
79  dir_list[i] = dir_list[i].right(-cur_p.length()-1);
80  if (p.startsWith(dir_list[i]+'/') || p == dir_list[i])
81  {
82  ref<DiskDirectory> dir = new DiskDirectory(cur_p + '/' + dir_list[i]);
83  if (!dir)
84  return NULL;
85  cur_p = cur_p + '/' + dir_list[i];
86  p = p.right(-dir_list[i].length()-1);
87  dir->listSubDirs(dir_list);
88  i=-1;
89  if (p.empty())
90  return dir;
91  }
92  }
93  return NULL;
94 }
95 //-----------------------------------------------------------------------------
97 {
98  if (path().empty())
99  {
100  Log::error( "VirtualDirectory::path() must not be empty!\n" );
101  return false;
102  }
103  #if defined(VL_PLATFORM_WINDOWS)
104  WIN32_FIND_DATA FindFileData;
105  memset( &FindFileData, 0, sizeof(FindFileData) );
106  String wild = path() + "*";
107  HANDLE hFind = FindFirstFile( (wchar_t*)wild.ptr(), &FindFileData );
108  if( hFind == INVALID_HANDLE_VALUE )
109  return false;
110  else
111  {
112  FindClose(hFind);
113  return true;
114  }
115  #elif defined(__GNUG__)
116  std::vector<unsigned char> utf8;
117  path().toUTF8( utf8, false );
118  DIR* dp = opendir((char*)&utf8[0]);
119  if(dp == NULL)
120  return false;
121  else
122  {
123  closedir(dp);
124  return true;
125  }
126  #endif
127 }
128 //-----------------------------------------------------------------------------
129 void DiskDirectory::listSubDirs(std::vector<String>& dirs, bool append) const
130 {
131  if (!append)
132  dirs.clear();
133  if (path().empty())
134  {
135  Log::error( "VirtualDirectory::path() must not be empty!\n" );
136  return;
137  }
138  #if defined(VL_PLATFORM_WINDOWS)
139  WIN32_FIND_DATA FindFileData;
140  memset( &FindFileData, 0, sizeof(FindFileData) );
141  String wild = path() + "*";
142  HANDLE hFind = FindFirstFile( (wchar_t*)wild.ptr(), &FindFileData );
143  if( hFind == INVALID_HANDLE_VALUE )
144  Log::error( Say("Cannot open directory '%s' for directory listing.\n") << path() );
145  else
146  {
147  do
148  {
149  if ( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
150  {
151  String name;
152  name = FindFileData.cFileName;
153  if (name != L"." && name != L"..")
154  dirs.push_back( path() + name + '/' );
155  }
156  } while( FindNextFile(hFind, &FindFileData) != 0 );
157 
158  DWORD dwError = GetLastError();
159  FindClose(hFind);
160  if (dwError != ERROR_NO_MORE_FILES)
161  {
162  // do nothing
163  // printf ("FindNextFile error. Error code is %u\n", dwError);
164  }
165  }
166  #elif defined(__GNUG__)
167  std::vector<unsigned char> utf8;
168  path().toUTF8( utf8, false );
169  struct dirent64 dirp;
170  struct dirent64* dirp2;
171  DIR* dp = opendir((char*)&utf8[0]);
172  if(dp != NULL)
173  {
174  while(readdir64_r(dp, &dirp, &dirp2) == 0 && dirp2 != NULL)
175  {
176  String name = dirp.d_name;
177  if (name == ".." || name == ".")
178  continue;
179 
180  name = path() + name + '/';
181  // To discover the linked directories we try to open them instead of reading 'dirp.d_type'
182  name.toUTF8( utf8, false );
183  DIR* is_dir = opendir((char*)&utf8[0]);
184  if (is_dir)
185  closedir(is_dir);
186  // 4 = directory
187  // 8 = file
188  // 10 = file or directory link
189  // to discover directory links you can try to open them with opendir()
190  // if (dirp.d_type == 4 )
191  if (is_dir)
192  dirs.push_back( name );
193  }
194  closedir(dp);
195  }
196  else
197  Log::error( Say("Cannot open directory '%s' for directory listing.\n") << path() );
198  #endif
199 }
200 //-----------------------------------------------------------------------------
201 void DiskDirectory::listFiles(std::vector< ref<DiskFile> >& file_list, bool append) const
202 {
203  // fixme: test
204  if (!append)
205  file_list.clear();
206  std::vector<String> file_names;
207  listFiles(file_names,false);
208  for(unsigned i=0; i<file_names.size(); ++i)
209  {
211  // file->setPath( path() + file_names[i] );
212  file->setPath( file_names[i] );
213  file_list.push_back(file);
214  }
215 }
216 //-----------------------------------------------------------------------------
217 void DiskDirectory::listFiles(std::vector<String>& files, bool append) const
218 {
219  if (!append)
220  files.clear();
221  if (path().empty())
222  {
223  Log::error( "VirtualDirectory::path() must not be empty!\n" );
224  return;
225  }
226  #if defined(VL_PLATFORM_WINDOWS)
227  WIN32_FIND_DATA FindFileData;
228  memset( &FindFileData, 0, sizeof(FindFileData) );
229  String wild = path() + "/*";
230  HANDLE hFind = FindFirstFile( (wchar_t*)wild.ptr(), &FindFileData );
231  if( hFind == INVALID_HANDLE_VALUE )
232  {
233  Log::error( Say("Cannot open directory '%s' for file listing.\n") << path() );
234  }
235  else
236  {
237  do
238  {
239  if ( (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 )
240  {
241  String name;
242  name = FindFileData.cFileName;
243  // the paths are relative
244  files.push_back( path() + name );
245  }
246  } while( FindNextFile(hFind, &FindFileData) != 0 );
247 
248  DWORD dwError = GetLastError();
249  FindClose(hFind);
250  if (dwError != ERROR_NO_MORE_FILES)
251  {
252  // do nothing
253  // printf ("FindNextFile error. Error is %u\n", dwError);
254  }
255  }
256  #elif defined(__GNUG__)
257  std::vector<unsigned char> utf8;
258  path().toUTF8( utf8, false );
259  struct dirent64 dirp;
260  struct dirent64* dirp2;
261  DIR* dp = opendir((char*)&utf8[0]);
262  if(dp != NULL)
263  {
264  while(readdir64_r(dp, &dirp, &dirp2) == 0 && dirp2 != NULL)
265  {
266  String name = dirp.d_name;
267  if (name == ".." || name == ".")
268  continue;
269 
270  name = path() + name;
271  // whatever is not a directory is a file for us
272  name.toUTF8( utf8, false );
273  DIR* is_dir = opendir((char*)&utf8[0]);
274  if (is_dir)
275  closedir(is_dir);
276  // 4 = directory
277  // 8 = file
278  // 10 = file or directory link
279  // to discover directory links you can try to open them with opendir()
280  // if (dirp.d_type == 4 )
281  if (!is_dir)
282  files.push_back( name );
283  }
284  closedir(dp);
285  }
286  else
287  Log::error( Say("Cannot open directory '%s' for file listing.\n") << path() );
288  #endif
289 }
290 //-----------------------------------------------------------------------------
292 {
293  return diskFile(name);
294 }
295 //-----------------------------------------------------------------------------
297 {
298  String p = translatePath(name);
299  ref<DiskFile> file = new DiskFile(p);
300  if (file->exists())
301  return file;
302  else
303  return NULL;
304 }
305 //-----------------------------------------------------------------------------
306 void DiskDirectory::listFilesRecursive_internal(std::vector<String>& file_list) const
307 {
308  // add local child
309  listFiles(file_list, true);
310  // descend recursively
311  std::vector<String> dir_list;
312  listSubDirs(dir_list);
313  for(unsigned i=0; i<dir_list.size(); ++i)
314  {
315  VL_CHECK(dir_list[i] != ".")
316  VL_CHECK(dir_list[i] != "..")
317 
318  DiskDirectory sub_dir( dir_list[i] );
319  sub_dir.listFilesRecursive_internal(file_list);
320  }
321 }
322 //-----------------------------------------------------------------------------
virtual bool setPath(const String &path)
Changes the path name of a VirtualDirectory. Must not be an empty string.
A simple String formatting class.
Definition: Say.hpp:124
virtual ref< VirtualFile > file(const String &name) const
Returns the VirtualFile with the given name if any, NULL otherwise.
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
bool exists() const
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
void listFiles(std::vector< String > &file_list, bool append=false) const
A VirtualDirectory that operates on reguar disk directories.
void listFilesRecursive_internal(std::vector< String > &file_list) const
ref< DiskDirectory > diskSubDir(const String &subdir_name) const
const wchar_t * ptr() const
Returns the 0-terminated utf16 string.
Definition: String.hpp:127
void toUTF8(std::vector< unsigned char > &utf8, bool include_utf8_signature=true) const
Encodes the String into a UTF8 encoded string.
Definition: String.cpp:1218
Visualization Library main namespace.
virtual const String & path() const
void listSubDirs(std::vector< String > &dirs, bool append=false) const
int length() const
Returns the length of the string.
Definition: String.hpp:133
bool empty() const
Returns true if length() == 0.
Definition: String.hpp:136
bool startsWith(const String &str) const
Returns true if a String starts with the specified String str.
Definition: String.cpp:720
#define NULL
Definition: OpenGLDefs.hpp:81
void setPath(const String &name)
Changes the path bound to a VirtualFile. Use carefully this function, you shouldn&#39;t rename a VirtualF...
A VirtualFile that operates on regular disk files.
Definition: DiskFile.hpp:64
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
T length(T v)
Definition: glsl_math.hpp:1084
String right(int count) const
Returns the count rightmost caracters of a String. If count is negative the function returns all but ...
Definition: String.cpp:822
virtual bool exists() const
Returns true if the file exists.
Definition: DiskFile.cpp:172
void listFilesRecursive(std::vector< String > &file_list) const
Use carefully this function, since this search the whole given file system tree.
#define VL_CHECK(expr)
Definition: checks.hpp:73
virtual ref< DiskFile > diskFile(const String &name) const
String translatePath(const String &p) const