CResourceLoader.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. /*
  2. * CResourceLoader.h, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #pragma once
  11. #include "CInputStream.h"
  12. class CResourceLoader;
  13. class ResourceLocator;
  14. class ISimpleResourceLoader;
  15. class JsonNode;
  16. /**
  17. * Specifies the resource type.
  18. *
  19. * Supported file extensions:
  20. *
  21. * Text: .txt .json
  22. * Animation: .def
  23. * Mask: .msk .msg
  24. * Campaign: .h3c
  25. * Map: .h3m
  26. * Font: .fnt
  27. * Image: .bmp, .jpg, .pcx, .png, .tga
  28. * Sound: .wav .82m
  29. * Video: .smk, .bik .mjpg .mpg
  30. * Music: .mp3, .ogg
  31. * Archive: .lod, .snd, .vid .pac
  32. * Palette: .pal
  33. * Savegame: .v*gm1
  34. */
  35. namespace EResType
  36. {
  37. enum Type
  38. {
  39. TEXT,
  40. ANIMATION,
  41. MASK,
  42. CAMPAIGN,
  43. MAP,
  44. BMP_FONT,
  45. TTF_FONT,
  46. IMAGE,
  47. VIDEO,
  48. SOUND,
  49. MUSIC,
  50. ARCHIVE_VID,
  51. ARCHIVE_SND,
  52. ARCHIVE_LOD,
  53. PALETTE,
  54. CLIENT_SAVEGAME,
  55. SERVER_SAVEGAME,
  56. DIRECTORY,
  57. ERM,
  58. ERT,
  59. ERS,
  60. OTHER
  61. };
  62. }
  63. /**
  64. * A struct which identifies a resource clearly.
  65. */
  66. class DLL_LINKAGE ResourceID
  67. {
  68. public:
  69. /**
  70. * Default c-tor.
  71. */
  72. ResourceID();
  73. /**
  74. * Move Ctor.
  75. */
  76. ResourceID(ResourceID && other)
  77. : name(std::move(other.name)), type(other.getType())
  78. {
  79. }
  80. /**
  81. * Copy Ctor. Required by clang (or this is standard?) if move constructor is present
  82. */
  83. ResourceID(const ResourceID & other)
  84. : name(other.getName()), type(other.getType())
  85. {
  86. }
  87. /**
  88. * Ctor. Can be used to create indentifier for resource loading using one parameter
  89. *
  90. * @param name The resource name including extension.
  91. */
  92. explicit ResourceID(std::string fullName);
  93. /**
  94. * Ctor.
  95. *
  96. * @param name The resource name.
  97. * @param type The resource type. A constant from the enumeration EResType.
  98. */
  99. ResourceID(std::string name, EResType::Type type);
  100. /**
  101. * Compares this object with a another resource identifier.
  102. *
  103. * @param other The other resource identifier.
  104. * @return Returns true if both are equally, false if not.
  105. */
  106. inline bool operator==(ResourceID const & other) const
  107. {
  108. return name == other.name && type == other.type;
  109. }
  110. /*
  111. * Move-assignment operator.
  112. */
  113. inline ResourceID& operator=(ResourceID && other)
  114. {
  115. name = std::move(other.name);
  116. type = other.getType();
  117. return *this;
  118. }
  119. std::string getName() const;
  120. EResType::Type getType() const;
  121. void setName(std::string name);
  122. void setType(EResType::Type type);
  123. protected:
  124. /**
  125. * Ctor for usage strictly in resourceLoader for some speedup
  126. *
  127. * @param prefix Prefix of ths filename, already in upper case
  128. * @param name The resource name, upper case
  129. * @param type The resource type. A constant from the enumeration EResType.
  130. */
  131. ResourceID(const std::string & prefix, const std::string & name, EResType::Type type);
  132. friend class CResourceLoader;
  133. private:
  134. /** Specifies the resource name. No extension so .pcx and .png can override each other, always in upper case. **/
  135. std::string name;
  136. /**
  137. * Specifies the resource type. EResType::OTHER if not initialized.
  138. * Required to prevent conflicts if files with different types (e.g. text and image) have the same name.
  139. */
  140. EResType::Type type;
  141. };
  142. /**
  143. * Generates a hash value for the resource identifier object.
  144. *
  145. * @param resourceIdent The object from which a hash value should be generated.
  146. * @return the generated hash value
  147. */
  148. inline size_t hash_value(const ResourceID & resourceIdent)
  149. {
  150. boost::hash<int> intHasher;
  151. boost::hash<std::string> stringHasher;
  152. return stringHasher(resourceIdent.getName()) ^ intHasher(static_cast<int>(resourceIdent.getType()));
  153. }
  154. /**
  155. * This class manages the loading of resources whether standard
  156. * or derived from several container formats and the file system.
  157. */
  158. class DLL_LINKAGE CResourceLoader
  159. {
  160. typedef boost::unordered_map<ResourceID, std::vector<ResourceLocator> > ResourcesMap;
  161. public:
  162. /// class for iterating over all available files/Identifiers
  163. /// can be created via CResourceLoader::getIterator
  164. template <typename Comparator, typename Iter>
  165. class Iterator
  166. {
  167. public:
  168. /// find next available item.
  169. Iterator& operator++()
  170. {
  171. assert(begin != end);
  172. begin++;
  173. findNext();
  174. return *this;
  175. }
  176. bool hasNext()
  177. {
  178. return begin != end;
  179. }
  180. /// get identifier of current item
  181. const ResourceID & operator* () const
  182. {
  183. assert(begin != end);
  184. return begin->first;
  185. }
  186. /// get identifier of current item
  187. const ResourceID * operator -> () const
  188. {
  189. assert(begin != end);
  190. return &begin->first;
  191. }
  192. protected:
  193. Iterator(Iter begin, Iter end, Comparator comparator):
  194. begin(begin),
  195. end(end),
  196. comparator(comparator)
  197. {
  198. //find first applicable item
  199. findNext();
  200. }
  201. friend class CResourceLoader;
  202. private:
  203. Iter begin;
  204. Iter end;
  205. Comparator comparator;
  206. void findNext()
  207. {
  208. while (begin != end && !comparator(begin->first))
  209. begin++;
  210. }
  211. };
  212. CResourceLoader();
  213. /**
  214. * Loads the resource specified by the resource identifier.
  215. *
  216. * @param resourceIdent This parameter identifies the resource to load.
  217. * @return a pointer to the input stream, not null
  218. *
  219. * @throws std::runtime_error if the resource doesn't exists
  220. */
  221. std::unique_ptr<CInputStream> load(const ResourceID & resourceIdent) const;
  222. /// temporary member to ease transition to new filesystem classes
  223. std::pair<std::unique_ptr<ui8[]>, ui64> loadData(const ResourceID & resourceIdent) const;
  224. /**
  225. * Get resource locator for this identifier
  226. *
  227. * @param resourceIdent This parameter identifies the resource to load.
  228. * @return resource locator for this resource or empty one if resource was not found
  229. */
  230. ResourceLocator getResource(const ResourceID & resourceIdent) const;
  231. /// returns ALL overriden resources with same name, including last one acessible via getResource
  232. const std::vector<ResourceLocator> & getResourcesWithName(const ResourceID & resourceIdent) const;
  233. /// returns real name of file in filesystem. Not usable for archives
  234. std::string getResourceName(const ResourceID & resourceIdent) const;
  235. /**
  236. * Get iterator for looping all files matching filter
  237. * Notes:
  238. * - iterating over all files may be slow. Use with caution
  239. * - all filenames are in upper case
  240. *
  241. * @param filter functor with signature bool(ResourceIdentifier) used to check if this file is required
  242. * @return resource locator for this resource or empty one if resource was not found
  243. */
  244. template<typename Comparator>
  245. Iterator<Comparator, ResourcesMap::const_iterator> getIterator(Comparator filter) const
  246. {
  247. return Iterator<Comparator, ResourcesMap::const_iterator>(resources.begin(), resources.end(), filter);
  248. }
  249. /**
  250. * Tests whether the specified resource exists.
  251. *
  252. * @param resourceIdent the resource which should be checked
  253. * @return true if the resource exists, false if not
  254. */
  255. bool existsResource(const ResourceID & resourceIdent) const;
  256. /**
  257. * Creates new resource (if not exists) with specified URI.
  258. * Type will be determined from extension
  259. * File case will be same as in URI
  260. *
  261. * @param URI file to create
  262. * @return true on success, false if resource exists or on error
  263. */
  264. bool createResource(std::string URI);
  265. /**
  266. * Adds a simple resource loader to the loaders list and its entries to the resources list.
  267. *
  268. * The loader object will be destructed when this resource loader is destructed.
  269. * Don't delete it manually.
  270. * Same loader can be added multiple times (with different mount point)
  271. *
  272. * @param mountPoint prefix that will be added to all files in this loader
  273. * @param loader The simple resource loader object to add
  274. */
  275. void addLoader(std::string mountPoint, shared_ptr<ISimpleResourceLoader> loader, bool writeable);
  276. private:
  277. /**
  278. * Contains lists of same resources which can be accessed uniquely by an
  279. * resource identifier.
  280. */
  281. ResourcesMap resources;
  282. struct LoaderEntry
  283. {
  284. std::string prefix;
  285. shared_ptr<ISimpleResourceLoader> loader;
  286. bool writeable;
  287. };
  288. /** A list of resource loader objects */
  289. std::vector<LoaderEntry > loaders;
  290. };
  291. /**
  292. * This class has static methods for a global resource loader access.
  293. *
  294. * Class is not thread-safe. Make sure nobody is calling getInstance while somebody else is calling initialize.
  295. */
  296. class DLL_LINKAGE CResourceHandler
  297. {
  298. public:
  299. /**
  300. * Gets an instance of resource loader.
  301. *
  302. * Make sure that you've set an instance before using it. It'll throw an exception if no instance was set.
  303. *
  304. * @return Returns an instance of resource loader.
  305. */
  306. static CResourceLoader * get();
  307. /**
  308. * Creates instance of resource loader.
  309. * Will not fill filesystem with data
  310. *
  311. */
  312. static void initialize();
  313. /**
  314. * Semi-debug method to track all possible cases of memory leaks
  315. * Used before exiting application
  316. *
  317. */
  318. static void clear();
  319. /**
  320. * Will load all filesystem data from Json data at this path (config/filesystem.json)
  321. * @param prefix - prefix for all paths in filesystem config
  322. */
  323. static void loadFileSystem(const std::string &prefix, const std::string & fsConfigURI);
  324. static void loadFileSystem(const std::string &prefix, const JsonNode & fsConfig);
  325. static void loadDirectory(const std::string &prefix, const std::string & mountPoint, const JsonNode & config);
  326. static void loadArchive(const std::string &prefix, const std::string & mountPoint, const JsonNode & config, EResType::Type archiveType);
  327. static void loadJsonMap(const std::string &prefix, const std::string & mountPoint, const JsonNode & config);
  328. /**
  329. * Checks all subfolders of MODS directory for presence of mods
  330. * If this directory has mod.json file it will be added to resources
  331. */
  332. static std::vector<std::string> getAvailableMods();
  333. static void setActiveMods(std::vector<std::string> enabledMods); //WARNING: not reentrable. Do not call it twice!!!
  334. private:
  335. /** Instance of resource loader */
  336. static CResourceLoader * resourceLoader;
  337. static CResourceLoader * initialLoader;
  338. };
  339. /**
  340. * A struct which describes the exact position of a resource.
  341. */
  342. class DLL_LINKAGE ResourceLocator
  343. {
  344. public:
  345. /**
  346. * Ctor.
  347. *
  348. * @param archive A pointer to the resource archive object.
  349. * @param resourceName Unique resource name in the space of the given resource archive.
  350. */
  351. ResourceLocator(ISimpleResourceLoader * loader, const std::string & resourceName);
  352. /**
  353. * Gets a pointer to the resource loader object.
  354. *
  355. * @return a pointer to the resource loader object
  356. */
  357. ISimpleResourceLoader * getLoader() const;
  358. /**
  359. * Gets the resource name.
  360. *
  361. * @return the resource name.
  362. */
  363. std::string getResourceName() const;
  364. private:
  365. /**
  366. * A pointer to the loader which knows where and how to construct a stream object
  367. * which does the loading process actually.
  368. */
  369. ISimpleResourceLoader * loader;
  370. /** A unique name of the resource in space of the loader. */
  371. std::string resourceName;
  372. };
  373. /**
  374. * A helper class which provides a functionality to convert extension strings to EResTypes.
  375. */
  376. class DLL_LINKAGE EResTypeHelper
  377. {
  378. public:
  379. /**
  380. * Converts a extension string to a EResType enum object.
  381. *
  382. * @param extension The extension string e.g. .BMP, .PNG
  383. * @return Returns a EResType enum object
  384. */
  385. static EResType::Type getTypeFromExtension(std::string extension);
  386. /**
  387. * Gets the EResType as a string representation.
  388. *
  389. * @param type the EResType
  390. * @return the type as a string representation
  391. */
  392. static std::string getEResTypeAsString(EResType::Type type);
  393. };