Стандартным способом для достижения этого [12, 14] является вынесение изменяющейся функциональности в отдельные объекты. В нашем случае возникает два типа таких объектов - объекты, обеспечивающие доступ к данным, и объекты, обеспечивающие декодирование данных из различных форматов.
Класс ResourceSource служит абстракцией доступа к файлу с данными. На его основе могут быть построены классы, позволяющие загружать фай-
Основные классы для рендерера. Работа с ресурсами
лы как из обычной файловой системы, так и из составных файлов различных форматов (например, ркЗ).
Ниже приводится описание этого класса.
OI Л'
class ResourceSource : public Object {
publi С :
ResourceSource ( const char * theName ) : Object ( theName ) {}
virtual Data * getFile ( const Strings name ) {
return NULL;
}
static MetaClass classlnstance;
} ;
Метод getFile возвращает указатель на объект класса Data, содержащий загруженный образ файла или NULL, если файл найти не удалось.
Использование класса Data для доступа к данным объясняется соображениями удобства и инкапсуляции. Этот класс содержит ряд операций, которые будут использоваться при декодировании ресурсов.
Ниже приводится его описание
class Data : public Object {
private:
unsigned char * bits;
int length;
int pos; public:
Data () : Object ( "" )
{
bits = NULL;
length = 0;
pos = 0;
metaClass = &classlnstance;
}
Data ( const char * theName, void * ptr, int len ) : Object ( theName )
{
bits = (unsigned char *) ptr;
length = len;
pos = 0;
metaClass = &classlnstance;
}
virtual bool isOk () const {
return bits != NULL;
}
bool isEmpty () const {
return pos >= length;
}
int getLength () const {
return length;
}
int getByte () {
if ( pos < length )
return bits [pos++];
else
return -1;
}
short getShort () {
if ( pos + 1 >= length ) return -1;
short v = *(short *) (bits + pos);
pos += 2;
return v;
}
unsigned short getUnsignedShort () {