414 lines
14 KiB
C++
414 lines
14 KiB
C++
#ifndef __RESOURCES_H__
|
|
#define __RESOURCES_H__
|
|
|
|
/** \file resources.h
|
|
* Classes for resources loading and unloading.
|
|
*/
|
|
|
|
#include <string>
|
|
#include <fstream>
|
|
#include <list>
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
#include "visitor.h"
|
|
#include "buffer.h"
|
|
|
|
typedef std::list<std::wstring> StringList;
|
|
|
|
|
|
class ResourceFile;
|
|
|
|
|
|
/// Abstract interface for streamed resource access
|
|
class ResourceStream
|
|
{
|
|
public:
|
|
virtual ~ResourceStream() { };
|
|
|
|
/// Get size of resource
|
|
virtual size_t getSize() = 0;
|
|
|
|
/// Seek into resource.
|
|
/// \param offset offset from resource start
|
|
virtual void seek(long offset) = 0;
|
|
|
|
/// Read data from resource into buffer.
|
|
/// \param buffer buffer of size bytes.
|
|
/// \param size number of bytes to read.
|
|
virtual void read(char *buffer, size_t size) = 0;
|
|
|
|
/// Get current position
|
|
virtual long getPos() = 0;
|
|
|
|
/// Return true if end of resource reached
|
|
virtual bool isEof() { return (size_t)getPos() >= getSize(); };
|
|
|
|
/// Get count of bytes left
|
|
virtual long getAvailable() { return (long)getSize() - getPos(); };
|
|
};
|
|
|
|
|
|
/***
|
|
* Low level resource file interface.
|
|
* Never use it, use ResourcesCollection instead.
|
|
***/
|
|
class ResourceFile
|
|
{
|
|
private:
|
|
std::ifstream stream; /// resource file input stream
|
|
int priority; /// priority of resource file
|
|
std::wstring name; /// resource file name
|
|
Buffer *buffer;
|
|
bool ownBuffer;
|
|
|
|
public:
|
|
/// Resource file directory entry
|
|
typedef struct {
|
|
std::wstring name; /// resource name
|
|
long offset; /// offset from start of resource file
|
|
long packedSize; /// compressed size
|
|
long unpackedSize; /// uncompressed size
|
|
std::wstring group; /// group name
|
|
int level; /// pack level
|
|
} DirectoryEntry;
|
|
/// List of directory entries.
|
|
typedef std::list<DirectoryEntry> Directory;
|
|
|
|
public:
|
|
/// Create resource file. Throws exception if file can't be opened.
|
|
/// \param fileName the name of resource file.
|
|
/// \param buffer buffer for temporary data.
|
|
/// Can be shared with other resource files.
|
|
ResourceFile(const std::wstring &fileName, Buffer *buffer=NULL);
|
|
virtual ~ResourceFile();
|
|
|
|
public:
|
|
/// Load directory listing.
|
|
/// \param directory list where resource entries will be placed.
|
|
void getDirectory(Directory &directory);
|
|
|
|
/// Load data in preallocated buffer buf of size unpackedSize.
|
|
/// \param buf buffer of unpackedSize bytes where unpacked data will
|
|
/// be placed
|
|
/// \param offset offset from start of resource file to packed data
|
|
/// \param packedSize size of packed resource
|
|
/// \param unpackedSize size of unpacked resource
|
|
void load(char *buf, long offset, long packedSize,
|
|
long unpackedSize, int level);
|
|
|
|
/// Allocate buffer and load data. Memory returned by this
|
|
/// method must be freed by free() function call.
|
|
/// \param offset offset from start of resource file to packed data
|
|
/// \param packedSize size of packed resource
|
|
/// \param unpackedSize size of unpacked resource
|
|
void* load(long offset, long packedSize, long unpackedSize,
|
|
int level);
|
|
|
|
/// Get priority of this resource file.
|
|
int getPriority() const { return priority; };
|
|
|
|
/// Get the name of resource file.
|
|
const std::wstring& getFileName() const { return name; };
|
|
|
|
/// Get file stream.
|
|
std::ifstream& getStream() { return stream; };
|
|
|
|
private:
|
|
/// Unpack memory buffer
|
|
/// \param in buffer of inSize bytes filled with packed data
|
|
/// \param inSize size of packed data
|
|
/// \param out buffer of outSize bytes where unpacked data will
|
|
/// be placed
|
|
/// \param outSize size of unpacked data
|
|
void unpack(char *in, int inSize, char *out, int outSize);
|
|
};
|
|
|
|
|
|
/// Simple resource file wrapper.
|
|
/// Used at boot time when ResourcesCollection
|
|
/// is not available yet.
|
|
class SimpleResourceFile: public ResourceFile
|
|
{
|
|
private:
|
|
typedef std::map<std::wstring, DirectoryEntry> DirectoryMap;
|
|
DirectoryMap directory; /// Directory map.
|
|
|
|
public:
|
|
/// Open resource file. Throws exception if file can't be opened.
|
|
/// \param fileName the name of resource file.
|
|
/// \param buffer buffer for temporary data.
|
|
/// Can be shared with other resource files.
|
|
SimpleResourceFile(const std::wstring &fileName, Buffer *buffer=NULL);
|
|
|
|
public:
|
|
/// Load data. Memory returned by this method should be freed
|
|
/// by free() function call.
|
|
/// \param name name of resource
|
|
/// \param size returns size of resource
|
|
virtual void* load(const std::wstring &name, int &size);
|
|
|
|
/// Load data into the buffer.
|
|
/// \param name name of resource
|
|
/// \param buffer buffer for resource data
|
|
virtual void load(const std::wstring &name, Buffer &buffer);
|
|
};
|
|
|
|
|
|
/// Internationalized resource entity.
|
|
class ResVariant
|
|
{
|
|
private:
|
|
int i18nScore;
|
|
ResourceFile *file;
|
|
long offset;
|
|
long unpackedSize;
|
|
long packedSize;
|
|
int refCnt;
|
|
void *data;
|
|
int level;
|
|
|
|
public:
|
|
/// Create resource variation.
|
|
/// \param file reesource file
|
|
/// \param score locale compability score
|
|
/// \param entry entry in global resources directory
|
|
ResVariant(ResourceFile *file, int score,
|
|
const ResourceFile::DirectoryEntry &entry);
|
|
|
|
~ResVariant();
|
|
|
|
public:
|
|
/// Return locale compability score.
|
|
int getI18nScore() const { return i18nScore; };
|
|
|
|
/// Get pointer to unpacked resource data.
|
|
/// Must be freed after use this delRef()
|
|
void* getRef();
|
|
|
|
/// Get pointer to unpacked resource data and return resource size.
|
|
/// Must be freed after use this delRef().
|
|
/// \param size returned size of resource data.
|
|
void* getRef(size_t &size);
|
|
|
|
/// Delete referene to data.
|
|
/// \param data pointer to unpacked data.
|
|
void delRef(void *data);
|
|
|
|
/// Return reference counter.
|
|
int getRefCount() const { return refCnt; };
|
|
|
|
/// Is data managed by this object
|
|
/// \param data pointer to dataa
|
|
bool isDataOwned(void *data) const { return refCnt && data == this->data; };
|
|
|
|
/// return data.
|
|
/// destroy it after use with free()
|
|
void* getDynData();
|
|
|
|
/// returns size of data
|
|
long getSize() const { return unpackedSize; };
|
|
|
|
/// Return data in buffer
|
|
/// \param buffer buffer to store data.
|
|
void getData(Buffer &buffer);
|
|
|
|
/// Create ResourceStream for resource.
|
|
/// This may be usefull for large streams unpacked data,
|
|
/// for example video and sound.
|
|
/// Delete stream after use.
|
|
ResourceStream* createStream();
|
|
};
|
|
|
|
|
|
/// Internationalized resources.
|
|
/// Collection of localized data (ResVariant) with single name.
|
|
class Resource
|
|
{
|
|
private:
|
|
typedef std::vector<ResVariant*> Variants;
|
|
Variants variants;
|
|
std::wstring name;
|
|
|
|
public:
|
|
/// Create resource and add first entry
|
|
/// \param file resource file
|
|
/// \param i18nScore locale compability score
|
|
/// \param entry resource entry in global directory
|
|
/// \param name name of resource
|
|
Resource(ResourceFile *file, int i18nScore,
|
|
const ResourceFile::DirectoryEntry &entry,
|
|
const std::wstring &name);
|
|
|
|
~Resource();
|
|
|
|
public:
|
|
/// Add resource variant.
|
|
/// \param file resource file
|
|
/// \param i18nScore locale compability score
|
|
/// \param entry resource entry in global directory
|
|
void addVariant(ResourceFile *file, int i18nScore,
|
|
const ResourceFile::DirectoryEntry &entry);
|
|
|
|
/// Get number of variants.
|
|
int getVariantsCount() const { return variants.size(); };
|
|
|
|
/// Geturns variant object.
|
|
/// \param variant variant number.
|
|
ResVariant* getVariant(int variant=0) { return variants[variant]; };
|
|
|
|
/// Load data from variant.
|
|
/// Data must be freed with delRef().
|
|
/// \param variant variant number.
|
|
void* getRef(int variant=0);
|
|
|
|
/// Load data from variant.
|
|
/// data must be freed with delRef()
|
|
/// \param size size of data.
|
|
/// \param variant variant number.
|
|
void* getRef(int *size, int variant=0);
|
|
|
|
/// Unload data
|
|
/// param data pointer to data.
|
|
void delRef(void *data);
|
|
|
|
/// Get size of data.
|
|
/// \param variant variant number.
|
|
long getSize(int variant=0) { return variants[variant]->getSize(); };
|
|
|
|
/// Get name of this resource.
|
|
const std::wstring& getName() const { return name; };
|
|
|
|
/// Load data into buffer.
|
|
/// \param buffer buffer for data.
|
|
/// \param variant variant number.
|
|
void getData(Buffer &buffer, int variant=0);
|
|
|
|
/// Create ResourceStream for resource.
|
|
/// This may be usefull for large streams unpacked data,
|
|
/// for example video and sound.
|
|
/// Delete stream after use.
|
|
/// \param variant variant number.
|
|
ResourceStream* createStream(int variant=0);
|
|
};
|
|
|
|
|
|
/// Internationalized resource files collection.
|
|
/// When ResourceCollection created all resources checked against
|
|
/// current locale. Resources not belonged to current locale are
|
|
/// ignored, resources that can be used in current locale sorted
|
|
/// by locale relevance score.
|
|
/// All resources names interpeted as name[_language][_COUNTRY].extension
|
|
/// where name is name of resource, language is optional two letters
|
|
/// ISO language code, country is two letters ISO country code
|
|
/// and extension is file extension.
|
|
/// After processing resource name will be truncated to name.extension.
|
|
/// By default resource with highest locale relevance score will
|
|
/// be loaded. Howether, it is possible to enumerate all variants
|
|
/// by using Resource class interface.
|
|
/// Resource files loaded in order specified by their priority.
|
|
/// Resources from file loaded later can replace resources
|
|
/// loaded before it.
|
|
class ResourcesCollection
|
|
{
|
|
private:
|
|
/// Map resource names to resources.
|
|
typedef std::map<std::wstring, Resource*> ResourcesMap;
|
|
|
|
/// List of resources.
|
|
typedef std::list<Resource*> ResourcesList;
|
|
|
|
/// Map group names to resources list.
|
|
typedef std::map<std::wstring, ResourcesList> ResourcesListMap;
|
|
|
|
/// List of resource files.
|
|
typedef std::vector<ResourceFile*> ResourceFiles;
|
|
|
|
ResourcesMap resources; /// Map of all available resources.
|
|
ResourcesListMap groups; /// Map of all available groups.
|
|
ResourceFiles files; /// List of resource files.
|
|
Buffer buffer; /// Temporary buffer for resource files.
|
|
|
|
public:
|
|
/// Load resource files, make grouping and i18n optimizations.
|
|
ResourcesCollection(StringList &directories);
|
|
~ResourcesCollection();
|
|
|
|
public:
|
|
/// Returns resource entry.
|
|
/// If resource not found Exception will be thrown.
|
|
Resource* getResource(const std::wstring &name);
|
|
|
|
/// Load resource.
|
|
/// Loaded data must be freed with delRef method.
|
|
void* getRef(const std::wstring &name, int &size);
|
|
|
|
/// Load resource.
|
|
/// Loaded data must be freed with delRef method.
|
|
void* getRef(const std::wstring &name);
|
|
|
|
/// Delete reference to resource.
|
|
void delRef(void *data);
|
|
|
|
/// Visit all group members.
|
|
void forEachInGroup(const std::wstring &groupName,
|
|
Visitor<Resource*> &visitor);
|
|
|
|
/// Create ResourceStream for resource.
|
|
/// This may be usefull for large streams unpacked data,
|
|
/// for example video and sound.
|
|
/// Delete stream after use.
|
|
/// \param name name of resource.
|
|
ResourceStream* createStream(const std::wstring &name);
|
|
|
|
/// Load data into buffer.
|
|
/// Usually you don't need this, use getRef instead.
|
|
/// \param name name of resource.
|
|
/// \param buffer buffer for data.
|
|
void loadData(const std::wstring &name, Buffer &buffer);
|
|
|
|
private:
|
|
/// Open resource files.
|
|
void loadResourceFiles(StringList &directories);
|
|
|
|
/// Make grouping and locale processing.
|
|
void processFiles();
|
|
};
|
|
|
|
|
|
/// Helper class for simple resource loading and unloading
|
|
class ResDataHolder
|
|
{
|
|
private:
|
|
void *data;
|
|
size_t size;
|
|
|
|
public:
|
|
/// Create holder without data
|
|
ResDataHolder();
|
|
|
|
/// Create holder and load data
|
|
ResDataHolder(const std::wstring &name);
|
|
|
|
~ResDataHolder();
|
|
|
|
public:
|
|
/// Load resource data
|
|
void load(const std::wstring &name);
|
|
|
|
/// Returns pointer to resource data
|
|
void* getData() const { return data; };
|
|
|
|
/// Returns size of data
|
|
size_t getSize() const { return size; };
|
|
};
|
|
|
|
|
|
/// Global collection of resources.
|
|
/// Careated at first step at boot time stage2
|
|
extern ResourcesCollection *resources;
|
|
|
|
|
|
#endif
|
|
|