ResourceFilesystem.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Resource/Common.h>
  7. #include <AnKi/Util/String.h>
  8. #include <AnKi/Util/StringList.h>
  9. #include <AnKi/Util/File.h>
  10. #include <AnKi/Util/Ptr.h>
  11. #include <AnKi/Util/CVarSet.h>
  12. namespace anki {
  13. ANKI_CVAR(StringCVar, Rsrc, DataPaths, ".",
  14. "The engine loads assets only in from these paths. Separate them with : (it's smart enough to identify drive letters in Windows). After a "
  15. "path you can add an optional | and what follows it is a number of words to include or exclude paths. eg. "
  16. "my_path|include_this,include_that,!exclude_this")
  17. // Resource filesystem file. An interface that abstracts the resource file.
  18. class ResourceFile
  19. {
  20. public:
  21. ResourceFile() = default;
  22. ResourceFile(const ResourceFile&) = delete; // Non-copyable
  23. virtual ~ResourceFile()
  24. {
  25. }
  26. ResourceFile& operator=(const ResourceFile&) = delete; // Non-copyable
  27. // Read data from the file
  28. virtual Error read(void* buff, PtrSize size) = 0;
  29. // Read all the contents of a text file. If the file is not rewined it will probably fail
  30. virtual Error readAllText(ResourceString& out) = 0;
  31. // Read 32bit unsigned integer. Set the endianness if the file's endianness is different from the machine's
  32. virtual Error readU32(U32& u) = 0;
  33. // Read 32bit float. Set the endianness if the file's endianness is different from the machine's
  34. virtual Error readF32(F32& f) = 0;
  35. // Set the position indicator to a new position
  36. // offset: Number of bytes to offset from origin
  37. // origin: Position used as reference for the offset
  38. virtual Error seek(PtrSize offset, FileSeekOrigin origin) = 0;
  39. // Get the size of the file.
  40. virtual PtrSize getSize() const = 0;
  41. void retain() const
  42. {
  43. m_refcount.fetchAdd(1);
  44. }
  45. I32 release() const
  46. {
  47. return m_refcount.fetchSub(1);
  48. }
  49. private:
  50. mutable Atomic<I32> m_refcount = {0};
  51. };
  52. // Resource file smart pointer.
  53. class ResourceFileDeleter
  54. {
  55. public:
  56. void operator()(ResourceFile* x)
  57. {
  58. deleteInstance(ResourceMemoryPool::getSingleton(), x);
  59. }
  60. };
  61. using ResourceFilePtr = IntrusivePtr<ResourceFile, ResourceFileDeleter>;
  62. // Resource filesystem.
  63. class ResourceFilesystem : public MakeSingleton<ResourceFilesystem>
  64. {
  65. public:
  66. ResourceFilesystem() = default;
  67. ResourceFilesystem(const ResourceFilesystem&) = delete; // Non-copyable
  68. ~ResourceFilesystem();
  69. ResourceFilesystem& operator=(const ResourceFilesystem&) = delete; // Non-copyable
  70. Error init();
  71. // Search the path list to find the file. Then open the file for reading.
  72. // Thread-safe.
  73. Error openFile(ResourceFilename filename, ResourceFilePtr& file) const;
  74. // Return some sort of time a file was last updated. This time is opaque and it's increasing with every update. Only works for filesystem files
  75. U64 getFileUpdateTime(ResourceFilename filename) const;
  76. // Take the filename (which is relative) and return the full path of the file. Only works for filesystem files
  77. ResourceString getFileFullPath(ResourceFilename filename) const;
  78. // Iterate all the filenames from all paths provided.
  79. template<typename TFunc>
  80. void iterateAllFilenames(TFunc func) const
  81. {
  82. for(const Path& path : m_paths)
  83. {
  84. for(const FileInfo& file : path.m_files)
  85. {
  86. if(func(file.m_filename.toCString()) == FunctorContinue::kStop)
  87. {
  88. break;
  89. }
  90. }
  91. }
  92. }
  93. // Iterate paths in the DataPaths CVar
  94. template<typename TFunc>
  95. void iterateAllResourceBasePaths(TFunc func) const
  96. {
  97. for(const Path& path : m_paths)
  98. {
  99. const FunctorContinue cont = func(path.m_path);
  100. if(cont == FunctorContinue::kStop)
  101. {
  102. break;
  103. }
  104. }
  105. }
  106. #if !ANKI_TESTS
  107. private:
  108. #endif
  109. class FileInfo
  110. {
  111. public:
  112. ResourceString m_filename;
  113. U64 m_filenameHash = 0;
  114. };
  115. class Path
  116. {
  117. public:
  118. ResourceDynamicArray<FileInfo> m_files; // Files inside the directory.
  119. ResourceString m_path; // A directory or an archive.
  120. Bool m_isArchive = false;
  121. Bool m_isSpecial = false;
  122. Path() = default;
  123. Path(const Path&) = delete; // Non-copyable
  124. Path(Path&& b)
  125. {
  126. *this = std::move(b);
  127. }
  128. Path& operator=(const Path&) = delete; // Non-copyable
  129. Path& operator=(Path&& b)
  130. {
  131. m_files = std::move(b.m_files);
  132. m_path = std::move(b.m_path);
  133. m_isArchive = b.m_isArchive;
  134. m_isSpecial = b.m_isSpecial;
  135. return *this;
  136. }
  137. };
  138. ResourceList<Path> m_paths;
  139. ResourceString m_cacheDir;
  140. // Add a filesystem path or an archive. The path is read-only.
  141. Error addNewPath(CString path, const ResourceStringList& includeStrings, const ResourceStringList& excludedStrings);
  142. Error openFileInternal(const ResourceFilename& filename, ResourceFile*& rfile) const;
  143. };
  144. } // end namespace anki