CResourceLoader.h 10 KB

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