1 #ifndef __RESOURCES_H__ 2 #define __RESOURCES_H__ 3 4 /** \file resources.h 5 * Classes for resources loading and unloading. 6 */ 7 8 #include <string> 9 #include <fstream> 10 #include <list> 11 #include <map> 12 #include <vector> 13 14 #include "visitor.h" 15 #include "buffer.h" 16 17 typedef std::list<std::wstring> StringList; 18 19 20 class ResourceFile; 21 22 23 /// Abstract interface for streamed resource access 24 class ResourceStream 25 { 26 public: ~ResourceStream()27 virtual ~ResourceStream() { }; 28 29 /// Get size of resource 30 virtual size_t getSize() = 0; 31 32 /// Seek into resource. 33 /// \param offset offset from resource start 34 virtual void seek(long offset) = 0; 35 36 /// Read data from resource into buffer. 37 /// \param buffer buffer of size bytes. 38 /// \param size number of bytes to read. 39 virtual void read(char *buffer, size_t size) = 0; 40 41 /// Get current position 42 virtual long getPos() = 0; 43 44 /// Return true if end of resource reached isEof()45 virtual bool isEof() { return (size_t)getPos() >= getSize(); }; 46 47 /// Get count of bytes left getAvailable()48 virtual long getAvailable() { return (long)getSize() - getPos(); }; 49 }; 50 51 52 /*** 53 * Low level resource file interface. 54 * Never use it, use ResourcesCollection instead. 55 ***/ 56 class ResourceFile 57 { 58 private: 59 std::ifstream stream; /// resource file input stream 60 int priority; /// priority of resource file 61 std::wstring name; /// resource file name 62 Buffer *buffer; 63 bool ownBuffer; 64 65 public: 66 /// Resource file directory entry 67 typedef struct { 68 std::wstring name; /// resource name 69 long offset; /// offset from start of resource file 70 long packedSize; /// compressed size 71 long unpackedSize; /// uncompressed size 72 std::wstring group; /// group name 73 int level; /// pack level 74 } DirectoryEntry; 75 /// List of directory entries. 76 typedef std::list<DirectoryEntry> Directory; 77 78 public: 79 /// Create resource file. Throws exception if file can't be opened. 80 /// \param fileName the name of resource file. 81 /// \param buffer buffer for temporary data. 82 /// Can be shared with other resource files. 83 ResourceFile(const std::wstring &fileName, Buffer *buffer=NULL); 84 virtual ~ResourceFile(); 85 86 public: 87 /// Load directory listing. 88 /// \param directory list where resource entries will be placed. 89 void getDirectory(Directory &directory); 90 91 /// Load data in preallocated buffer buf of size unpackedSize. 92 /// \param buf buffer of unpackedSize bytes where unpacked data will 93 /// be placed 94 /// \param offset offset from start of resource file to packed data 95 /// \param packedSize size of packed resource 96 /// \param unpackedSize size of unpacked resource 97 void load(char *buf, long offset, long packedSize, 98 long unpackedSize, int level); 99 100 /// Allocate buffer and load data. Memory returned by this 101 /// method must be freed by free() function call. 102 /// \param offset offset from start of resource file to packed data 103 /// \param packedSize size of packed resource 104 /// \param unpackedSize size of unpacked resource 105 void* load(long offset, long packedSize, long unpackedSize, 106 int level); 107 108 /// Get priority of this resource file. getPriority()109 int getPriority() const { return priority; }; 110 111 /// Get the name of resource file. getFileName()112 const std::wstring& getFileName() const { return name; }; 113 114 /// Get file stream. getStream()115 std::ifstream& getStream() { return stream; }; 116 117 private: 118 /// Unpack memory buffer 119 /// \param in buffer of inSize bytes filled with packed data 120 /// \param inSize size of packed data 121 /// \param out buffer of outSize bytes where unpacked data will 122 /// be placed 123 /// \param outSize size of unpacked data 124 void unpack(char *in, int inSize, char *out, int outSize); 125 }; 126 127 128 /// Simple resource file wrapper. 129 /// Used at boot time when ResourcesCollection 130 /// is not available yet. 131 class SimpleResourceFile: public ResourceFile 132 { 133 private: 134 typedef std::map<std::wstring, DirectoryEntry> DirectoryMap; 135 DirectoryMap directory; /// Directory map. 136 137 public: 138 /// Open resource file. Throws exception if file can't be opened. 139 /// \param fileName the name of resource file. 140 /// \param buffer buffer for temporary data. 141 /// Can be shared with other resource files. 142 SimpleResourceFile(const std::wstring &fileName, Buffer *buffer=NULL); 143 144 public: 145 /// Load data. Memory returned by this method should be freed 146 /// by free() function call. 147 /// \param name name of resource 148 /// \param size returns size of resource 149 virtual void* load(const std::wstring &name, int &size); 150 151 /// Load data into the buffer. 152 /// \param name name of resource 153 /// \param buffer buffer for resource data 154 virtual void load(const std::wstring &name, Buffer &buffer); 155 }; 156 157 158 /// Internationalized resource entity. 159 class ResVariant 160 { 161 private: 162 int i18nScore; 163 ResourceFile *file; 164 long offset; 165 long unpackedSize; 166 long packedSize; 167 int refCnt; 168 void *data; 169 int level; 170 171 public: 172 /// Create resource variation. 173 /// \param file reesource file 174 /// \param score locale compability score 175 /// \param entry entry in global resources directory 176 ResVariant(ResourceFile *file, int score, 177 const ResourceFile::DirectoryEntry &entry); 178 179 ~ResVariant(); 180 181 public: 182 /// Return locale compability score. getI18nScore()183 int getI18nScore() const { return i18nScore; }; 184 185 /// Get pointer to unpacked resource data. 186 /// Must be freed after use this delRef() 187 void* getRef(); 188 189 /// Get pointer to unpacked resource data and return resource size. 190 /// Must be freed after use this delRef(). 191 /// \param size returned size of resource data. 192 void* getRef(size_t &size); 193 194 /// Delete referene to data. 195 /// \param data pointer to unpacked data. 196 void delRef(void *data); 197 198 /// Return reference counter. getRefCount()199 int getRefCount() const { return refCnt; }; 200 201 /// Is data managed by this object 202 /// \param data pointer to dataa isDataOwned(void * data)203 bool isDataOwned(void *data) const { return refCnt && data == this->data; }; 204 205 /// return data. 206 /// destroy it after use with free() 207 void* getDynData(); 208 209 /// returns size of data getSize()210 long getSize() const { return unpackedSize; }; 211 212 /// Return data in buffer 213 /// \param buffer buffer to store data. 214 void getData(Buffer &buffer); 215 216 /// Create ResourceStream for resource. 217 /// This may be usefull for large streams unpacked data, 218 /// for example video and sound. 219 /// Delete stream after use. 220 ResourceStream* createStream(); 221 }; 222 223 224 /// Internationalized resources. 225 /// Collection of localized data (ResVariant) with single name. 226 class Resource 227 { 228 private: 229 typedef std::vector<ResVariant*> Variants; 230 Variants variants; 231 std::wstring name; 232 233 public: 234 /// Create resource and add first entry 235 /// \param file resource file 236 /// \param i18nScore locale compability score 237 /// \param entry resource entry in global directory 238 /// \param name name of resource 239 Resource(ResourceFile *file, int i18nScore, 240 const ResourceFile::DirectoryEntry &entry, 241 const std::wstring &name); 242 243 ~Resource(); 244 245 public: 246 /// Add resource variant. 247 /// \param file resource file 248 /// \param i18nScore locale compability score 249 /// \param entry resource entry in global directory 250 void addVariant(ResourceFile *file, int i18nScore, 251 const ResourceFile::DirectoryEntry &entry); 252 253 /// Get number of variants. getVariantsCount()254 int getVariantsCount() const { return variants.size(); }; 255 256 /// Geturns variant object. 257 /// \param variant variant number. 258 ResVariant* getVariant(int variant=0) { return variants[variant]; }; 259 260 /// Load data from variant. 261 /// Data must be freed with delRef(). 262 /// \param variant variant number. 263 void* getRef(int variant=0); 264 265 /// Load data from variant. 266 /// data must be freed with delRef() 267 /// \param size size of data. 268 /// \param variant variant number. 269 void* getRef(int *size, int variant=0); 270 271 /// Unload data 272 /// param data pointer to data. 273 void delRef(void *data); 274 275 /// Get size of data. 276 /// \param variant variant number. 277 long getSize(int variant=0) { return variants[variant]->getSize(); }; 278 279 /// Get name of this resource. getName()280 const std::wstring& getName() const { return name; }; 281 282 /// Load data into buffer. 283 /// \param buffer buffer for data. 284 /// \param variant variant number. 285 void getData(Buffer &buffer, int variant=0); 286 287 /// Create ResourceStream for resource. 288 /// This may be usefull for large streams unpacked data, 289 /// for example video and sound. 290 /// Delete stream after use. 291 /// \param variant variant number. 292 ResourceStream* createStream(int variant=0); 293 }; 294 295 296 /// Internationalized resource files collection. 297 /// When ResourceCollection created all resources checked against 298 /// current locale. Resources not belonged to current locale are 299 /// ignored, resources that can be used in current locale sorted 300 /// by locale relevance score. 301 /// All resources names interpeted as name[_language][_COUNTRY].extension 302 /// where name is name of resource, language is optional two letters 303 /// ISO language code, country is two letters ISO country code 304 /// and extension is file extension. 305 /// After processing resource name will be truncated to name.extension. 306 /// By default resource with highest locale relevance score will 307 /// be loaded. Howether, it is possible to enumerate all variants 308 /// by using Resource class interface. 309 /// Resource files loaded in order specified by their priority. 310 /// Resources from file loaded later can replace resources 311 /// loaded before it. 312 class ResourcesCollection 313 { 314 private: 315 /// Map resource names to resources. 316 typedef std::map<std::wstring, Resource*> ResourcesMap; 317 318 /// List of resources. 319 typedef std::list<Resource*> ResourcesList; 320 321 /// Map group names to resources list. 322 typedef std::map<std::wstring, ResourcesList> ResourcesListMap; 323 324 /// List of resource files. 325 typedef std::vector<ResourceFile*> ResourceFiles; 326 327 ResourcesMap resources; /// Map of all available resources. 328 ResourcesListMap groups; /// Map of all available groups. 329 ResourceFiles files; /// List of resource files. 330 Buffer buffer; /// Temporary buffer for resource files. 331 332 public: 333 /// Load resource files, make grouping and i18n optimizations. 334 ResourcesCollection(StringList &directories); 335 ~ResourcesCollection(); 336 337 public: 338 /// Returns resource entry. 339 /// If resource not found Exception will be thrown. 340 Resource* getResource(const std::wstring &name); 341 342 /// Load resource. 343 /// Loaded data must be freed with delRef method. 344 void* getRef(const std::wstring &name, int &size); 345 346 /// Load resource. 347 /// Loaded data must be freed with delRef method. 348 void* getRef(const std::wstring &name); 349 350 /// Delete reference to resource. 351 void delRef(void *data); 352 353 /// Visit all group members. 354 void forEachInGroup(const std::wstring &groupName, 355 Visitor<Resource*> &visitor); 356 357 /// Create ResourceStream for resource. 358 /// This may be usefull for large streams unpacked data, 359 /// for example video and sound. 360 /// Delete stream after use. 361 /// \param name name of resource. 362 ResourceStream* createStream(const std::wstring &name); 363 364 /// Load data into buffer. 365 /// Usually you don't need this, use getRef instead. 366 /// \param name name of resource. 367 /// \param buffer buffer for data. 368 void loadData(const std::wstring &name, Buffer &buffer); 369 370 private: 371 /// Open resource files. 372 void loadResourceFiles(StringList &directories); 373 374 /// Make grouping and locale processing. 375 void processFiles(); 376 }; 377 378 379 /// Helper class for simple resource loading and unloading 380 class ResDataHolder 381 { 382 private: 383 void *data; 384 size_t size; 385 386 public: 387 /// Create holder without data 388 ResDataHolder(); 389 390 /// Create holder and load data 391 ResDataHolder(const std::wstring &name); 392 393 ~ResDataHolder(); 394 395 public: 396 /// Load resource data 397 void load(const std::wstring &name); 398 399 /// Returns pointer to resource data getData()400 void* getData() const { return data; }; 401 402 /// Returns size of data getSize()403 size_t getSize() const { return size; }; 404 }; 405 406 407 /// Global collection of resources. 408 /// Careated at first step at boot time stage2 409 extern ResourcesCollection *resources; 410 411 412 #endif 413 414