Leviathan  0.8.0.0
Leviathan game engine
FileSystem.cpp
Go to the documentation of this file.
1 // ------------------------------------ //
2 #include "FileSystem.h"
4 
5 #ifndef ALTERNATIVE_EXCEPTIONS_FATAL
6 #include "Exceptions.h"
7 #endif
8 #include "TimeIncludes.h"
9 
10 #include <fstream>
11 #include <ostream>
12 
13 #include <boost/filesystem.hpp>
14 
15 #ifdef __linux__
16 #include <dirent.h>
17 #include <sys/stat.h>
18 #else
19 #endif
20 #ifdef _WIN32
21 
22 #include "WindowsInclude.h"
23 
24 #endif //_WIN32
25 #include <iosfwd>
26 using namespace Leviathan;
27 using namespace std;
28 // ------------------------------------ //
30 {
31  // set static access //
32  Staticaccess = this;
33  // set default values //
34  CurrentFileExtID = 25;
35 
36  // index creation flags //
37  IsAllIndexed = IsTextureIndexed = IsModelIndexed = IsSoundIndexed = IsScriptIndexed =
38  IsSorted = IsBeingSorted = ShouldSortStop = false;
39 }
40 
42 {
43 
44  // Helps catch errors with tests etc.
45  if(Staticaccess == this)
46  Staticaccess = nullptr;
47 
48  SAFE_DELETE_VECTOR(FileTypes);
49 
50  AllFiles.clear();
51 
52  TextureFiles.clear();
53  ModelFiles.clear();
54  SoundFiles.clear();
55  ScriptFiles.clear();
56 
57  // Clear indexes //
58  IsAllIndexed = false;
59  SAFE_DELETE_VECTOR(AllIndexes);
60 
61  IsTextureIndexed = false;
62  SAFE_DELETE_VECTOR(TextureIndexes);
63 
64  IsModelIndexed = false;
65  SAFE_DELETE_VECTOR(ModelIndexes);
66 
67  IsSoundIndexed = false;
68  SAFE_DELETE_VECTOR(SoundIndexes);
69 
70  IsScriptIndexed = false;
71  SAFE_DELETE_VECTOR(ScriptIndexes);
72 }
73 
75 {
76 
77  return Staticaccess;
78 }
79 
80 string Leviathan::FileSystem::DataFolder = "./Data/";
81 string Leviathan::FileSystem::ModelsFolder = "Models/";
82 string Leviathan::FileSystem::ScriptsFolder = "Scripts/";
83 string Leviathan::FileSystem::ShaderFolder = "Shaders/";
84 string Leviathan::FileSystem::TextureFolder = "Textures/";
85 string Leviathan::FileSystem::MaterialFolder = "Materials/";
86 string Leviathan::FileSystem::FontFolder = "Fonts/";
87 string Leviathan::FileSystem::SoundFolder = "Sound/";
88 
89 FileSystem* Leviathan::FileSystem::Staticaccess = NULL;
90 // ------------------------------------ //
92 {
93 
94  ErrorReporter = errorreport;
95 
96  IsSorted = false;
97 
98  // use find files function on data folder and then save results to appropriate vectors //
99  vector<string> files;
100 #ifdef _WIN32
101  GetFilesInDirectory(files, "./Data/");
102 #else
103  GetFilesInDirectory(files, "./Data");
104 #endif
105 
106  if(files.size() < 1) {
107 
108  ErrorReporter->Error(
109  std::string("FileSystem: SearchFiles: No files inside data folder, "
110  "cannot possibly work"));
111  return false;
112  }
113 
114  // save to appropriate places //
115  for(size_t i = 0; i < files.size(); i++) {
116 
117  // create new object for storing this //
118  auto tmpptr = make_shared<FileDefinitionType>(this, files[i]);
119 
120  if(files[i].find("./Data/Textures/") == 0) {
121 
122  // add to texture files //
123  TextureFiles.push_back((tmpptr));
124 
125  } else if(files[i].find("./Data/Models/") == 0) {
126 
127  // add to texture files //
128  ModelFiles.push_back(tmpptr);
129 
130  } else if(files[i].find("./Data/Sound/") == 0) {
131 
132  // add to texture files //
133  SoundFiles.push_back(tmpptr);
134 
135  } else if(files[i].find("./Data/Scripts/") == 0) {
136 
137  // add to texture files //
138  ScriptFiles.push_back(tmpptr);
139  }
140 
141  // everything should be in AllFiles vector //
142  AllFiles.push_back(tmpptr);
143  }
144  // print some info //
145  ErrorReporter->Info("FileSystem: found " + Convert::ToString(AllFiles.size()) +
146  " files in Data folder with " + Convert::ToString(FileTypes.size()) +
147  " different types of extensions");
148 
149  // sort for quick finding //
150  auto starttime = Time::GetTimeMicro64();
151  CreateIndexesForVecs();
152 
153  auto elapsed = Time::GetTimeMicro64() - starttime;
154 
155  // print info //
156  ErrorReporter->Info("FileSystem: vectors sorted and indexes created, took " +
157  Convert::ToString(elapsed) + " micro seconds");
158 
159  return true;
160 }
161 
163 {
164 
165  // Reset values //
166  CurrentFileExtID = 25;
167  IsSorted = false;
168 
169  SAFE_DELETE_VECTOR(FileTypes);
170 
171  AllFiles.clear();
172 
173  TextureFiles.clear();
174  ModelFiles.clear();
175  SoundFiles.clear();
176  ScriptFiles.clear();
177 
178  // Clear indexes //
179  IsAllIndexed = false;
180  SAFE_DELETE_VECTOR(AllIndexes);
181 
182  IsTextureIndexed = false;
183  SAFE_DELETE_VECTOR(TextureIndexes);
184 
185  IsModelIndexed = false;
186  SAFE_DELETE_VECTOR(ModelIndexes);
187 
188  IsSoundIndexed = false;
189  SAFE_DELETE_VECTOR(SoundIndexes);
190 
191  IsScriptIndexed = false;
192  SAFE_DELETE_VECTOR(ScriptIndexes);
193 
194  // Search again //
195  return Init(ErrorReporter);
196 }
197 // ------------------------------------ //
199 {
200 
201  return (DataFolder);
202 }
203 
205 {
206 
207  return (DataFolder + ModelsFolder);
208 }
209 
211 {
212 
213  return (DataFolder + ScriptsFolder);
214 }
215 
217 {
218 
219  return (DataFolder + ShaderFolder);
220 }
221 
223 {
224 
225  return (DataFolder + TextureFolder);
226 }
227 
229 {
230 
231  return (DataFolder + FontFolder);
232 }
233 
235 {
236 
237  return (DataFolder + SoundFolder);
238 }
239 // ------------------------------------ //
241  FileDefinitionType* file, const vector<int>& Ids)
242 {
243  // check does file contain an extension id that is in the vector //
244  for(size_t i = 0; i < Ids.size(); i++) {
245  if(file->ExtensionID == Ids[i]) {
246  // match found //
247  return true;
248  }
249  }
250  return false;
251 }
252 
253 // ------------------------------------ //
254 #ifdef _WIN32
255 void Leviathan::FileSystem::GetWindowsFolder(wstring& path)
256 {
257  wchar_t winddir[MAX_PATH];
258  if(GetWindowsDirectoryW(winddir, MAX_PATH) > 0)
259  path = winddir;
260  if(path.back() != L'/')
261  path += L'/';
262 }
263 
264 void Leviathan::FileSystem::GetSpecialFolder(wstring& path, int specialtype)
265 {
266  wchar_t directory[MAX_PATH];
267  SHGetSpecialFolderPathW(NULL, directory, specialtype, false);
268  path = directory;
269  if(path.back() != L'/')
270  path += L'/';
271 }
272 #endif
273 // ------------------------------------ //
275 {
276 
277  DataFolder = folder;
278 }
279 
280 void Leviathan::FileSystem::SetModelsFolder(const string& folder)
281 {
282 
283  ModelsFolder = folder;
284 }
285 
286 void Leviathan::FileSystem::SetScriptsFolder(const string& folder)
287 {
288 
289  ScriptsFolder = folder;
290 }
291 
292 void Leviathan::FileSystem::SetShaderFolder(const string& folder)
293 {
294 
295  ShaderFolder = folder;
296 }
297 
298 void Leviathan::FileSystem::SetTextureFolder(const string& folder)
299 {
300 
301  TextureFolder = folder;
302 }
303 // ------------------ File handling ------------------ //
304 DLLEXPORT bool FileSystem::LoadDataDump(const string& file,
305  vector<shared_ptr<NamedVariableList>>& vec, LErrorReporter* errorreport)
306 {
307  // Get data //
308  ifstream stream(file);
309 
310  if(!stream.good()) {
311  // no file ! //
312  errorreport->Error("FileSystem: LoadDataDump: Failed to read file: " + file);
313  return false;
314  }
315 
316  // count length //
317  stream.seekg(0, ios::end);
318  auto length = stream.tellg();
319  stream.seekg(0, ios::beg);
320 
321  if(length == std::streampos(0)) {
322 
323  // empty file ! //
324  return false;
325  }
326 
327  // TODO: directly copy into the string
328  unique_ptr<char[]> Buff(new char[(size_t)length + 1]);
329 
330  // set null terminator, just in case
331  (Buff.get())[length] = '\0';
332 
333  stream.read(Buff.get(), length);
334 
335  stream.close();
336 
337  string filecontents = Buff.get();
338 
339  // Create values //
340  return NamedVariableList::ProcessDataDump(filecontents, vec, errorreport);
341 }
342 
343 #ifdef _WIN32
344 DLLEXPORT bool Leviathan::FileSystem::GetFilesInDirectory(vector<string>& files,
345  const string& dirpath, const string& pattern, bool recursive /*= true*/)
346 {
347  string FilePath;
348  string Pattern;
349  HANDLE hFile;
350  WIN32_FIND_DATAA FileInfo;
351 
352  Pattern = dirpath + pattern;
353 
354  hFile = ::FindFirstFileA(Pattern.c_str(), &FileInfo);
355  if(hFile != INVALID_HANDLE_VALUE) {
356  do {
357 
358  if(FileInfo.cFileName[0] != '.') {
359  FilePath.erase();
360  FilePath = dirpath + FileInfo.cFileName + "/";
361 
362  if(FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
363 
364  if(recursive) {
365  // call self to search subdirectory
366  int retr = GetFilesInDirectory(files, FilePath, pattern, recursive);
367  if(!retr)
368  break; // failed //
369  }
370  } else {
371  // save file
372  files.push_back(dirpath + FileInfo.cFileName);
373  }
374  }
375  } while(::FindNextFileA(hFile, &FileInfo) == 1);
376 
377  // close handle //
378  FindClose(hFile);
379  }
380 
381  return true;
382 }
383 #else
385  const string& dirpath, const string& pattern /*= "*.*"*/, bool recursive /*= true*/)
386 {
387  dirent* ent;
388  struct stat st;
389 
390  // Start searching //
391  DIR* dir = opendir(dirpath.c_str());
392 
393  if(!dir) {
394 
395  // Non-existant directory
396  return false;
397  }
398 
399  while((ent = readdir(dir)) != NULL) {
400  const string file_name = ent->d_name;
401 
402  // Ignore if starts with a '.' //
403  if(file_name[0] == '.')
404  continue;
405 
406  const string full_file_name = dirpath + "/" + file_name;
407 
408  // Get info to determine if it is a dirpath //
409  if(stat(full_file_name.c_str(), &st) == -1)
410  continue;
411 
412  // Check if it is a dirpath //
413  if((st.st_mode & S_IFDIR) != 0) {
414  // Go into dirpath if recursive search //
415  if(recursive) {
416  // \todo fix performance //
417  GetFilesInDirectory(files, full_file_name, pattern, recursive);
418  }
419  continue;
420  }
421 
422  files.push_back(full_file_name);
423  }
424 
425  closedir(dir);
426 
427  return true;
428 }
429 #endif
430 // ------------------ File operations ------------------ //
431 size_t Leviathan::FileSystem::GetFileLength(const string& name)
432 {
433 
434  ifstream file(name, ios::binary);
435 
436  if(file.good()) {
437 
438  file.seekg(0, ios::end);
439  auto returnval = file.tellg();
440  file.close();
441  return returnval;
442  }
443 
444 #ifndef ALTERNATIVE_EXCEPTIONS_FATAL
445  throw InvalidArgument("Cannot determine file size it doesn't exist");
446 #else
447  return 0;
448 #endif
449 }
450 
452 {
453  return boost::filesystem::exists(name);
454 }
455 
456 bool Leviathan::FileSystem::WriteToFile(const string& data, const string& filename)
457 {
458  ofstream file(filename, ios::binary);
459  if(file.is_open()) {
460 
461  file << data;
462 
463  file.close();
464  return true;
465  }
466 
467  file.close();
468  return false;
469 }
470 
471 bool Leviathan::FileSystem::WriteToFile(const wstring& data, const wstring& filename)
472 {
473 #ifdef _WIN32
474  wofstream file(filename, ios::binary);
475 #else
476  wofstream file(Convert::Utf16ToUtf8(filename), ios::binary);
477 #endif
478  if(file.is_open()) {
479  file << data;
480 
481  file.close();
482  return true;
483  }
484 
485  file.close();
486  return false;
487 }
488 
489 bool Leviathan::FileSystem::AppendToFile(const string& data, const string& filepath)
490 {
491 
492  ofstream file(filepath, ofstream::app | ios::binary);
493 
494  if(file.is_open()) {
495 
496  file << data;
497 
498  file.close();
499  return true;
500  }
501 
502  file.close();
503  return false;
504 }
505 
507  const wstring& file, wstring& resultreceiver)
508 {
509 #ifdef _WIN32
510  wifstream reader(file, ios::in | ios::binary);
511 #else
512  wifstream reader(Convert::Utf16ToUtf8(file), ios::in | ios::binary);
513 #endif
514  if(reader) {
515 
516  // go to end to count length //
517  reader.seekg(0, ios::end);
518 
519  streamoff rpos = reader.tellg();
520 
521  // cannot be loaded //
522  LEVIATHAN_ASSERT(std::numeric_limits<streamoff>::max() >= rpos, "file is too large");
523 
524  resultreceiver.resize(static_cast<size_t>(rpos));
525  // back to start //
526  reader.seekg(0, ios::beg);
527  // read the actual data //
528  reader.read(&resultreceiver[0], resultreceiver.size());
529 
530  // done, cleanup //
531  reader.close();
532  return true;
533  }
534 
535  return false;
536 }
537 
539  const string& file, string& resultreceiver)
540 {
541 
542  ifstream reader(file, ios::in | ios::binary);
543 
544  if(reader) {
545 
546  // go to end to count length //
547  reader.seekg(0, ios::end);
548 
549  streamoff rpos = reader.tellg();
550 
551 
552  // cannot be loaded //
553  LEVIATHAN_ASSERT(std::numeric_limits<streamoff>::max() >= rpos, "file is too large");
554 
555  resultreceiver.resize(static_cast<size_t>(rpos));
556  // back to start //
557  reader.seekg(0, ios::beg);
558  // read the actual data //
559  reader.read(&resultreceiver[0], resultreceiver.size());
560 
561  // done, cleanup //
562  reader.close();
563  return true;
564  }
565 
566  return false;
567 }
568 // ------------------ Non static part ------------------ //
570 {
571  // check if already sorted //
572  if(IsSorted)
573  return;
574 
575  ShouldSortStop = false;
576  // call sort on the vectors //
577  IsBeingSorted = true;
578 
579  // looping so that other thread can cancel the action before it is finished //
580  for(int i = 0; i < 5; i++) {
581  // switch on index and call std sort //
582  switch(i) {
583  case 0: sort(AllFiles.begin(), AllFiles.end(), FileDefSorter()); break;
584  case 1: sort(TextureFiles.begin(), TextureFiles.end(), FileDefSorter()); break;
585  case 2: sort(ModelFiles.begin(), ModelFiles.end(), FileDefSorter()); break;
586  case 3: sort(SoundFiles.begin(), SoundFiles.end(), FileDefSorter()); break;
587  case 4: sort(ScriptFiles.begin(), ScriptFiles.end(), FileDefSorter()); break;
588  }
589 
590  // check for end
591  if(ShouldSortStop) {
592  // asked to stop //
593  goto end;
594  }
595  }
596  // sort done
597  IsSorted = true;
598 
599 end:
600  IsBeingSorted = false;
601 }
602 
603 DLLEXPORT void Leviathan::FileSystem::CreateIndexesForVecs(bool forcerecreation /*= false*/)
604 {
605  // check are vectors sorted, if not call sort //
606  if(!IsSorted) {
607 
608  SortFileVectors();
609  }
610 
611  _CreateIndexesIfMissing(AllFiles, AllIndexes, IsAllIndexed, forcerecreation);
612  _CreateIndexesIfMissing(TextureFiles, TextureIndexes, IsTextureIndexed, forcerecreation);
613  _CreateIndexesIfMissing(ModelFiles, ModelIndexes, IsModelIndexed, forcerecreation);
614  _CreateIndexesIfMissing(SoundFiles, SoundIndexes, IsSoundIndexed, forcerecreation);
615  _CreateIndexesIfMissing(ScriptFiles, ScriptIndexes, IsScriptIndexed, forcerecreation);
616 }
617 // ------------------------------------ //
619 {
620  // check does it exist //
621  for(size_t i = 0; i < FileTypes.size(); i++) {
622  if(StringOperations::CompareInsensitive(FileTypes[i]->Name, extension))
623  return FileTypes[i]->ID;
624  }
625 
626  // add //
627  CurrentFileExtID++;
628  FileTypes.push_back(new FileTypeHolder(CurrentFileExtID, extension));
629 
630  return CurrentFileExtID;
631 }
632 
633 void Leviathan::FileSystem::GetExtensionIDS(const string& extensions, vector<int>& ids)
634 {
635  // generate info about the extensions //
636  vector<string> Exts;
637  StringOperations::CutString(extensions, string("|"), Exts);
638  if(Exts.size() == 0) {
639  // just one extension //
640  ids.push_back(RegisterExtension(extensions));
641  return;
642  }
643 
644  for(size_t i = 0; i < Exts.size(); i++) {
645  ids.push_back(RegisterExtension(Exts[i]));
646  }
647 }
648 
650 {
651  // Look for it //
652  for(size_t i = 0; i < FileTypes.size(); i++) {
653  if(FileTypes[i]->ID == id)
654  return FileTypes[i]->Name;
655  }
656 
657  // Not found //
658 #ifndef ALTERNATIVE_EXCEPTIONS_FATAL
659  throw NotFound("No extension corresponds with id");
660 #else
661  LEVIATHAN_ASSERT(0, "No extension corresponds with id");
662  return FileTypes[0]->Name;
663 #endif // ALTERNATIVE_EXCEPTIONS_FATAL
664 }
665 // ------------------------------------ //
667  FILEGROUP which, const string& name, const string& extensions, bool searchall /*= true*/)
668 {
669  if(name.empty())
670  return "";
671 
672  // generate info about the search file //
673  vector<int> ExtensionIDS;
674  GetExtensionIDS(extensions, ExtensionIDS);
675 
676  switch(which) {
677  case FILEGROUP_MODEL: {
678  shared_ptr<FileDefinitionType> result =
679  _SearchForFileInVec(ModelFiles, ExtensionIDS, name, IsModelIndexed, &ModelIndexes);
680  if(result.get() != NULL) {
681  // found //
682  return result.get()->RelativePath;
683  }
684  } break;
685  case FILEGROUP_TEXTURE: {
686  shared_ptr<FileDefinitionType> result = _SearchForFileInVec(
687  TextureFiles, ExtensionIDS, name, IsTextureIndexed, &TextureIndexes);
688 
689  if(result.get() != NULL) {
690  // found //
691  return result.get()->RelativePath;
692  }
693  } break;
694  case FILEGROUP_SOUND: {
695  shared_ptr<FileDefinitionType> result =
696  _SearchForFileInVec(SoundFiles, ExtensionIDS, name, IsSoundIndexed, &SoundIndexes);
697  if(result.get() != NULL) {
698  // found //
699  return result.get()->RelativePath;
700  }
701  } break;
702  case FILEGROUP_SCRIPT: {
703  shared_ptr<FileDefinitionType> result = _SearchForFileInVec(
704  ScriptFiles, ExtensionIDS, name, IsScriptIndexed, &ScriptIndexes);
705  if(result.get() != NULL) {
706  // found //
707  return result.get()->RelativePath;
708  }
709  } break;
710  case FILEGROUP_OTHER: {
711  shared_ptr<FileDefinitionType> result =
712  _SearchForFileInVec(AllFiles, ExtensionIDS, name, IsAllIndexed, &AllIndexes);
713  if(result.get() != NULL) {
714  // found //
715  return result.get()->RelativePath;
716  }
717  } break;
718  }
719 
720 
721  // still not found, if searchall specified search all files vector //
722  if(searchall) {
723  shared_ptr<FileDefinitionType> result =
724  _SearchForFileInVec(AllFiles, ExtensionIDS, name, IsAllIndexed, &AllIndexes);
725  if(result.get() != NULL) {
726  // found //
727  return result.get()->RelativePath;
728  }
729  }
730  // not found return empty and if debug build warn //
731 
732  ErrorReporter->Error("FileSystem: File not found: " + name + "." + extensions);
733 
734  return "";
735 }
736 
737 DLLEXPORT vector<shared_ptr<FileDefinitionType>> Leviathan::FileSystem::FindAllMatchingFiles(
738  FILEGROUP which, const string& regexname, const string& extensions,
739  bool searchall /*= true*/)
740 {
741  // generate info about the search file //
742  vector<int> ExtensionIDS;
743  GetExtensionIDS(extensions, ExtensionIDS);
744 
745  // create regex //
746  regex usedregex(regexname, regex_constants::ECMAScript | regex_constants::icase);
747 
748  vector<shared_ptr<FileDefinitionType>> foundfiles;
749 
750  if(searchall) {
751 
752  _SearchForFilesInVec(AllFiles, foundfiles, ExtensionIDS, usedregex);
753 
754  } else {
755  // specific vector //
756  vector<shared_ptr<FileDefinitionType>>* targetvector = NULL;
757 
758  switch(which) {
759  case FILEGROUP_MODEL: {
760  targetvector = &ModelFiles;
761  } break;
762  case FILEGROUP_TEXTURE: {
763  targetvector = &TextureFiles;
764  } break;
765  case FILEGROUP_SOUND: {
766  targetvector = &SoundFiles;
767  } break;
768  case FILEGROUP_SCRIPT: {
769  targetvector = &ScriptFiles;
770  } break;
771  case FILEGROUP_OTHER: {
772  targetvector = &AllFiles;
773  } break;
774  }
775 
776  _SearchForFilesInVec(*targetvector, foundfiles, ExtensionIDS, usedregex);
777  }
778 
779  // return what we found //
780  return foundfiles;
781 }
782 
783 
784 // ------------------------------------ //
785 vector<shared_ptr<FileDefinitionType>>& Leviathan::FileSystem::GetModelFiles()
786 {
787  return ModelFiles;
788 }
789 
790 vector<shared_ptr<FileDefinitionType>>& Leviathan::FileSystem::GetSoundFiles()
791 {
792  return SoundFiles;
793 }
794 
795 vector<shared_ptr<FileDefinitionType>>& Leviathan::FileSystem::GetAllFiles()
796 {
797  return AllFiles;
798 }
799 
800 vector<shared_ptr<FileDefinitionType>>& Leviathan::FileSystem::GetScriptFiles()
801 {
802  return ScriptFiles;
803 }
804 // ------------------------------------ //
805 shared_ptr<FileDefinitionType> Leviathan::FileSystem::_SearchForFileInVec(
806  vector<shared_ptr<FileDefinitionType>>& vec, vector<int>& extensions, const string& name,
807  bool UseIndexVector, vector<CharWithIndex*>* Index)
808 {
809  size_t StartSpot = 0;
810 
811  // use index to get start spot for faster searching //
812  if(UseIndexVector) {
813  char startchar = name[0];
814  bool Found = false;
815 
816  // find matching char //
817  for(unsigned int i = 0; i < Index->size(); i++) {
818  if(Index->at(i)->Char == startchar) {
819  Found = true;
820  StartSpot = Index->at(i)->Index;
821  break;
822  }
823  }
824  // if character that starts the word wasn't found it can't be there, exit function //
825  if(!Found)
826  return NULL;
827  }
828 
829  for(size_t i = StartSpot; i < vec.size(); i++) {
830  // if no extension specified skip checking them //
831  if(extensions.size() > 0) {
832  // check does extension(s) match //
833  if(!DoesExtensionMatch(vec[i].get(), extensions))
834  continue;
835  }
836  // extensions match check name //
837  if((vec[i]->Name != name))
838  continue;
839 
840  // match //
841  return vec[i];
842  }
843  // nothing //
844  return NULL;
845 }
846 
847 void Leviathan::FileSystem::_SearchForFilesInVec(vector<shared_ptr<FileDefinitionType>>& vec,
848  vector<shared_ptr<FileDefinitionType>>& results, vector<int>& extensions,
849  const regex& regex)
850 {
851  for(size_t i = 0; i < vec.size(); i++) {
852  // if no extension specified skip checking them //
853  if(extensions.size() > 0) {
854  // check does extension(s) match //
855  if(!DoesExtensionMatch(vec[i].get(), extensions)) {
856  continue;
857  }
858  }
859  // extensions match check name //
860  if(!regex_match(vec[i]->Name, regex)) {
861  continue;
862  }
863 
864  // match //
865  results.push_back(vec[i]);
866  }
867 }
868 
869 void Leviathan::FileSystem::_CreateIndexesIfMissing(
870  vector<shared_ptr<FileDefinitionType>>& vec, vector<CharWithIndex*>& resultvec,
871  bool& indexed, const bool& force /*= false*/)
872 {
873  // we'll need to delete old ones if index creation is forced //
874  if(force) {
875  indexed = false;
876  SAFE_DELETE_VECTOR(resultvec);
877  }
878  // if they are valid we can just return //
879  if(indexed)
880  return;
881 
882  // now that the file vector is sorted we can loop through it and every time first character
883  // changes add it to index
884  char curchar = '!';
885 
886  for(size_t i = 0; i < vec.size(); i++) {
887  if(vec[i]->Name[0] != curchar) {
888  // beginning character changed, push to indexes //
889  curchar = vec[i]->Name[0];
890  resultvec.push_back(new CharWithIndex(curchar, i));
891  }
892  }
893 
894  // done //
895  indexed = true;
896 }
897 // ------------------ FileDefinitionType ------------------ //
899  RelativePath(path)
900 {
901  // get extension //
902  string tempexpt = StringOperations::GetExtension<std::string>(path);
903 
904  // register extension and store id //
905  ExtensionID = instance->RegisterExtension(tempexpt);
906 
907  // save name //
908  Name = StringOperations::RemoveExtension<std::string>(path, true);
909 }
910 
912 {
913  return this->Name < other.Name;
914 }
915 
917 
919 {
920  // Add the extension text to the end of the name //
921  return Name + "." + FileSystem::Get()->GetExtensionName(ExtensionID);
922 }
923 // ------------------ FileDefSorter ------------------ //
924 bool Leviathan::FileDefSorter::operator()(const std::shared_ptr<FileDefinitionType>& first,
925  const std::shared_ptr<FileDefinitionType>& second)
926 {
927  return (*first.get()) < *(second).get();
928 }
929 // ------------------ CharWithIndex ------------------ //
931 {
932  Char = L' ';
933  Index = -1;
934 }
935 
936 CharWithIndex::CharWithIndex(char character, size_t index) : Char(character), Index(index) {}
937 // ------------------ FileTypeHolder ------------------ //
938 FileTypeHolder::FileTypeHolder(int id, const std::string& name) : ID(id), Name(name) {}
static DLLEXPORT std::string GetScriptsFolder()
Definition: FileSystem.cpp:210
DLLEXPORT void SortFileVectors()
Definition: FileSystem.cpp:569
static DLLEXPORT std::string GetModelsFolder()
Definition: FileSystem.cpp:204
static DLLEXPORT std::string GetDataFolder()
Definition: FileSystem.cpp:198
static DLLEXPORT void SetModelsFolder(const std::string &folder)
Definition: FileSystem.cpp:280
FileDefinitionType(FileSystem *instance, const std::string &path)
Definition: FileSystem.cpp:898
static DLLEXPORT bool ProcessDataDump(const std::string &data, std::vector< std::shared_ptr< NamedVariableList >> &vec, LErrorReporter *errorreport, std::map< std::string, std::shared_ptr< VariableBlock >> *predefined=nullptr)
Definition: NamedVars.cpp:612
DLLEXPORT std::vector< std::shared_ptr< FileDefinitionType > > FindAllMatchingFiles(FILEGROUP which, const std::string &regexname, const std::string &extensions, bool searchall=true)
Returns all matching files.
Definition: FileSystem.cpp:737
static DLLEXPORT void SetDataFolder(const std::string &folder)
Definition: FileSystem.cpp:274
DLLEXPORT std::vector< std::shared_ptr< FileDefinitionType > > & GetModelFiles()
Definition: FileSystem.cpp:785
DLLEXPORT bool ReSearchFiles()
Destroys the current index and recreates it.
Definition: FileSystem.cpp:162
static DLLEXPORT bool AppendToFile(const std::string &data, const std::string &filepath)
Definition: FileSystem.cpp:489
static DLLEXPORT std::string Utf16ToUtf8(const std::wstring &utf16str)
Encodes an UTF8 string from a wide string (wstring/utf16)
Definition: Convert.cpp:108
Class for indexing and searching game data directory.
Definition: FileSystem.h:65
static DLLEXPORT bool GetFilesInDirectory(std::vector< std::string > &files, const std::string &dirpath, const std::string &pattern="*.*", bool recursive=true)
Definition: FileSystem.cpp:384
static DLLEXPORT std::string GetShaderFolder()
Definition: FileSystem.cpp:216
FileTypeHolder(int id, const std::string &name)
Definition: FileSystem.cpp:938
DLLEXPORT void GetExtensionIDS(const std::string &extensions, std::vector< int > &ids)
Returns list of matching ids to the extensions.
Definition: FileSystem.cpp:633
static DLLEXPORT bool DoesExtensionMatch(FileDefinitionType *file, const std::vector< int > &Ids)
Definition: FileSystem.cpp:240
#define SAFE_DELETE_VECTOR(x)
Definition: Define.h:171
DLLEXPORT bool operator()(const std::shared_ptr< FileDefinitionType > &first, const std::shared_ptr< FileDefinitionType > &second)
Definition: FileSystem.cpp:924
DLLEXPORT void CreateIndexesForVecs(bool forcerecreation=false)
Definition: FileSystem.cpp:603
static DLLEXPORT int64_t GetTimeMicro64()
static DLLEXPORT FileSystem * Get()
Definition: FileSystem.cpp:74
static DLLEXPORT void SetScriptsFolder(const std::string &folder)
Definition: FileSystem.cpp:286
static DLLEXPORT void SetTextureFolder(const std::string &folder)
Definition: FileSystem.cpp:298
static DLLEXPORT void SetShaderFolder(const std::string &folder)
Definition: FileSystem.cpp:292
static DLLEXPORT std::string GetFontFolder()
Definition: FileSystem.cpp:228
DLLEXPORT ~FileSystem()
Definition: FileSystem.cpp:41
DLLEXPORT std::vector< std::shared_ptr< FileDefinitionType > > & GetAllFiles()
Definition: FileSystem.cpp:795
DLLEXPORT bool Init(LErrorReporter *errorreport)
Runs the indexing and sorting.
Definition: FileSystem.cpp:91
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:98
std::string GetNameWithExtension() const
Definition: FileSystem.cpp:918
DLLEXPORT std::vector< std::shared_ptr< FileDefinitionType > > & GetScriptFiles()
Definition: FileSystem.cpp:800
static std::string ToString(const T &val)
Definition: Convert.h:72
DLLEXPORT FileSystem()
Definition: FileSystem.cpp:29
static DLLEXPORT bool FileExists(const std::string &name)
Definition: FileSystem.cpp:451
DLLEXPORT std::string SearchForFile(FILEGROUP which, const std::string &name, const std::string &extensions, bool searchall=true)
Searches for a file.
Definition: FileSystem.cpp:666
static bool CompareInsensitive(const StringTypeN &data, const StringTypeN &second)
static DLLEXPORT std::string GetSoundFolder()
Definition: FileSystem.cpp:234
DLLEXPORT std::vector< std::shared_ptr< FileDefinitionType > > & GetSoundFiles()
Definition: FileSystem.cpp:790
virtual void Error(const std::string &Text)=0
Helper class for indexing.
Definition: FileSystem.h:24
static DLLEXPORT bool ReadFileEntirely(const std::string &file, std::string &resultreceiver)
Definition: FileSystem.cpp:538
static DLLEXPORT bool LoadDataDump(const std::string &file, std::vector< std::shared_ptr< NamedVariableList >> &vec, LErrorReporter *errorreport)
Definition: FileSystem.cpp:304
static DLLEXPORT std::string GetTextureFolder()
Definition: FileSystem.cpp:222
#define DLLEXPORT
Definition: Include.h:84
static bool CutString(const StringTypeN &strtocut, const StringTypeN &separator, std::vector< StringTypeN > &vec)
The access mask controls which registered functions and classes a script sees.
Definition: GameModule.h:12
static DLLEXPORT size_t GetFileLength(const std::string &name)
Definition: FileSystem.cpp:431
DLLEXPORT int RegisterExtension(const std::string &extension)
Reserves a number for an extension string.
Definition: FileSystem.cpp:618
static DLLEXPORT bool WriteToFile(const std::string &data, const std::string &filename)
Definition: FileSystem.cpp:456
bool operator<(const FileDefinitionType &other) const
Definition: FileSystem.cpp:911
DLLEXPORT const std::string & GetExtensionName(int id) const
Retrieves the name of the extension from the id.
Definition: FileSystem.cpp:649