| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- //============================================================================================
- // Spirenkov Maxim, 2004, 2008
- //============================================================================================
- // CoreStorageFolder
- //============================================================================================
- #include "CoreStorageFolder.h"
- #include "CoreStorage.h"
- #include "Core.h"
- #include "..\..\common_h\data_swizzle.h"
- //============================================================================================
- //Streams
- //============================================================================================
- //WriteStream
- //--------------------------------------------------------------------------------------------
- CoreStorageFolder::WriteStream::WriteStream(array<byte> & _data) : data(_data)
- {
- offset = -1;
- }
- void CoreStorageFolder::WriteStream::WriteByte(const byte & b)
- {
- data.Add(b);
- }
- void CoreStorageFolder::WriteStream::WriteDWord(const dword & dw)
- {
- long index = data;
- data.AddElements(sizeof(dword));
- core_unaligned dword & v = (core_unaligned dword &)data[index];
- v = SwizzleDWord(dw);
- }
- void CoreStorageFolder::WriteStream::WriteFloat(const float & fl)
- {
- long index = data;
- data.AddElements(sizeof(float));
- core_unaligned float & v = (core_unaligned float &)data[index];
- v = SwizzleFloat(fl);
- }
- void CoreStorageFolder::WriteStream::WriteString(const char * str)
- {
- if(!str) str = "";
- for(long s = 0; str[s]; s++); s++;
- long index = data;
- data.AddElements(s);
- memcpy(&data[index], str, s);
- }
- void CoreStorageFolder::WriteStream::WriteTable(const void * buffer, dword size)
- {
- if(size > 0)
- {
- long index = data;
- data.AddElements(size);
- memcpy(&data[index], buffer, size);
- }
- }
- void CoreStorageFolder::WriteStream::PinSizePosition()
- {
- offset = data;
- data.AddElements(sizeof(dword));
- }
- void CoreStorageFolder::WriteStream::SaveSize()
- {
- Assert(offset > 0);
- long size = data - offset;
- Assert(size > 0);
- core_unaligned dword & v = (core_unaligned dword &)data[offset];
- v = SwizzleDWord((dword)size);
- }
- //--------------------------------------------------------------------------------------------
- //ReadStream
- //--------------------------------------------------------------------------------------------
- CoreStorageFolder::ReadStream::ReadStream(dword & _pointer, const void * _data, dword _size) : pointer(_pointer)
- {
- data = (const byte *)_data;
- size = _size;
- offset = -1;
- offsetSize = -1;
- }
- bool CoreStorageFolder::ReadStream::ReadByte(byte & b)
- {
- if(pointer + sizeof(byte) > size)
- {
- return false;
- }
- b = data[pointer];
- pointer += sizeof(byte);
- return true;
- }
- bool CoreStorageFolder::ReadStream::ReadDWord(dword & dw)
- {
- if(pointer + sizeof(dword) > size)
- {
- return false;
- }
- dw = SwizzleDWord((core_unaligned dword &)data[pointer]);
- pointer += sizeof(dword);
- return true;
- }
- bool CoreStorageFolder::ReadStream::ReadFloat(float & fl)
- {
- if(pointer + sizeof(float) > size)
- {
- return false;
- }
- fl = SwizzleFloat((core_unaligned float &)data[pointer]);
- pointer += sizeof(float);
- return true;
- }
- bool CoreStorageFolder::ReadStream::ReadString(string & str)
- {
- for(str.Empty(); pointer < size; pointer++)
- {
- char c = data[pointer];
- if(!c)
- {
- pointer++;
- return true;
- }
- str += c;
- }
- str.Empty();
- return false;
- }
- bool CoreStorageFolder::ReadStream::ReadTable(void * buffer, dword size)
- {
- if(pointer + size > this->size)
- {
- return false;
- }
- if(size > 0)
- {
- memcpy(buffer, &data[pointer], size);
- }
- pointer += size;
- return true;
- }
- bool CoreStorageFolder::ReadStream::PinSizePosition()
- {
- offset = pointer;
- return ReadDWord(offsetSize);
- }
- bool CoreStorageFolder::ReadStream::CheckSize()
- {
- long s = pointer - offset;
- if(s < 0)
- {
- return false;
- }
- if(s != offsetSize)
- {
- return false;
- }
- return true;
- }
- //============================================================================================
- //CoreStorageFolder
- //============================================================================================
- CoreStorageFolder::CoreStorageFolder(CoreStorageFolder * p, long nId) : items(_FL_),
- strings(_FL_)
- {
- parent = p;
- nameId = nId;
- }
- CoreStorageFolder::~CoreStorageFolder()
- {
- for(long i = 0; i < items; i++)
- {
- if(items[i].type == ICoreStorageItem::t_folder)
- {
- delete items[i].vFolder;
- }
- }
- items.Empty();
- }
- //Получить по пути итем, если объекты не созданы, попытаться создать
- //Если встречается на месте нужного итем другого типа то возвращает индекс этого итем и папку null
- CoreStorageFolder * CoreStorageFolder::FindItem(const array<long> & p, ICoreStorageItem::Type type, bool isCreatePath, long & index)
- {
- CoreStorageFolder * folder = this;
- for(long i = 0; i < p; i++)
- {
- //Ищем поле с заданным идентификатором
- long id = p[i];
- Item * its = folder->items.GetBuffer();
- long count = folder->items.Size();
- index = -1;
- for(long n = 0; n < count; n++)
- {
- if(its[n].nameId == id)
- {
- index = n;
- break;
- }
- }
- if(index >= 0)
- {
- //Элемент с таким идентификатором найден, проверяем тип
- Item & item = folder->items[index];
- if(i >= p - 1)
- {
- //Последний элемент
- if(type != ICoreStorageItem::t_error)
- {
- //Требуеться проверить тип переменной
- if(item.type != type)
- {
- return null;
- }
- }
- return folder;
- }
- //Не последний элемент должен быть папкой
- if(item.type != ICoreStorageItem::t_folder)
- {
- return null;
- }
- folder = item.vFolder;
- Assert(folder);
- }else{
- //Нету такого поля если в режиме создания то создаём папку
- if(!isCreatePath)
- {
- return null;
- }
- index = folder->items.Add();
- Item & item = folder->items[index];
- item.nameId = id;
- if(i >= p - 1)
- {
- //Последний элемент
- item.type = type;
- switch(type)
- {
- case ICoreStorageItem::t_string:
- item.vString = folder->strings.Add();
- break;
- case ICoreStorageItem::t_long:
- item.vLong = 0;
- break;
- case ICoreStorageItem::t_float:
- item.vFloat = 0.0f;
- break;
- case ICoreStorageItem::t_folder:
- item.vFolder = NEW CoreStorageFolder(folder, id);
- break;
- default:
- Assert(false);
- }
- return folder;
- }
- //Папка
- item.type = ICoreStorageItem::t_folder;
- folder = item.vFolder = NEW CoreStorageFolder(folder, id);
- }
- }
- //Указана текущая папка
- index = -1;
- if(type != ICoreStorageItem::t_error)
- {
- if(type != ICoreStorageItem::t_folder)
- {
- return null;
- }
- }
- return this;
- }
- //Заполнить полный путь до папки
- void CoreStorageFolder::BuildFullPath(array<long> & p, long size)
- {
- if(parent)
- {
- parent->BuildFullPath(p, size + 1);
- p.Add(nameId);
- }else{
- p.Empty();
- p.Reserve(size);
- }
- }
- //Вывести содержимое в строку, (перевод строки \n)
- void CoreStorageFolder::Print(long tab, string & buffer, long index)
- {
- if(index < 0)
- {
- buffer.Reserve(items.Size()*(tab + 1024));
- for(long i = 0; i < items; i++)
- {
- PrintItemToBuffer(tab, buffer, items[i]);
- }
- }else{
- buffer.Reserve(tab + 1024);
- PrintItemToBuffer(tab, buffer, items[index]);
- }
- }
- //Сохранить группу
- void CoreStorageFolder::Save(long index, WriteStream & stream)
- {
- if(index < 0)
- {
- //Надо сохранить всю папку
- stream.WriteDWord(items.Size());
- for(long i = 0; i < items; i++)
- {
- SaveItem(items[i], stream);
- }
- }else{
- //Надо сохранить отдельный элемент
- stream.WriteDWord(1);
- SaveItem(items[index], stream);
- }
- }
- //Прочитать группу
- bool CoreStorageFolder::Load(ReadStream & stream)
- {
- CoreStorage & storage = ((Core *)api)->GetCoreStorage();
- //Читаем количество полей
- dword count = 0;
- if(!stream.ReadDWord(count))
- {
- return false;
- }
- items.Reserve(items.Size() + count);
- //Читаем поля
- string name;
- for(dword i = 0; i < count; i++)
- {
- byte type;
- if(!stream.ReadByte(type))
- {
- return false;
- }
- if(!stream.ReadString(name))
- {
- return false;
- }
- Item item;
- item.nameId = storage.SaveName(name.c_str());
- //Проверяем такой среди добавленых
- for(long j = 0; j < items; j++)
- {
- Item & it = items[j];
- if(it.nameId == item.nameId)
- {
- //Опа, есть такое
- if(it.type != type)
- {
- //Жёпа, нельзя перезаписать значение
- return false;
- }
- break;
- }
- }
- switch(type)
- {
- case ICoreStorageItem::t_string:
- if(j >= items)
- {
- item.type = ICoreStorageItem::t_string;
- item.vString = strings.Add();
- if(!stream.ReadString(strings[item.vString]))
- {
- strings.DelIndex(item.vString);
- return false;
- }
- items.Add(item);
- }else{
- if(!stream.ReadString(strings[items[j].vString]))
- {
- return false;
- }
- }
- break;
- case ICoreStorageItem::t_long:
- if(j >= items)
- {
- item.type = ICoreStorageItem::t_long;
- if(!stream.ReadDWord((dword &)item.vLong))
- {
- return false;
- }
- items.Add(item);
- }else{
- if(!stream.ReadDWord((dword &)items[j].vLong))
- {
- return false;
- }
- }
- break;
- case ICoreStorageItem::t_float:
- if(j >= items)
- {
- item.type = ICoreStorageItem::t_float;
- if(!stream.ReadFloat(item.vFloat))
- {
- return false;
- }
- items.Add(item);
- }else{
- if(!stream.ReadFloat(items[j].vFloat))
- {
- return false;
- }
- }
- break;
- case ICoreStorageItem::t_folder:
- if(j >= items)
- {
- item.type = ICoreStorageItem::t_folder;
- item.vFolder = NEW CoreStorageFolder(this, item.nameId);
- if(!item.vFolder->Load(stream))
- {
- delete item.vFolder;
- return false;
- }
- items.Add(item);
- }else{
- if(!items[j].vFolder->Load(stream))
- {
- return false;
- }
- }
- break;
- default:
- return false;
- }
- }
- return true;
- }
- //Удалить все дочернии поля
- void CoreStorageFolder::Delete(long index)
- {
- if(index >= 0)
- {
- if(items[index].type == ICoreStorageItem::t_folder)
- {
- delete items[index].vFolder;
- }
- items.DelIndex(index);
- }else{
- for(long i = 0; i < items; i++)
- {
- if(items[i].type == ICoreStorageItem::t_folder)
- {
- delete items[i].vFolder;
- }
- }
- items.Empty();
- }
- }
- //Сохранить в поток поле
- void CoreStorageFolder::SaveItem(Item & item, WriteStream & stream)
- {
- //Тип
- stream.WriteByte(item.type);
- //Имя
- CoreStorage & storage = ((Core *)api)->GetCoreStorage();
- const char * name = storage.GetName(item.nameId);
- stream.WriteString(name);
- //Данные
- switch(item.type)
- {
- case ICoreStorageItem::t_string:
- stream.WriteString(strings[item.vString].c_str());
- break;
- case ICoreStorageItem::t_long:
- stream.WriteDWord((dword)item.vLong);
- break;
- case ICoreStorageItem::t_float:
- stream.WriteFloat(item.vFloat);
- break;
- case ICoreStorageItem::t_folder:
- item.vFolder->Save(-1, stream);
- break;
- default:
- Assert(false);
- }
- }
- //Вывести элемент в буфер
- void CoreStorageFolder::PrintItemToBuffer(long tab, string & buffer, Item & item)
- {
- char tmp[1024];
- for(long i = 0; i < tab; i++)
- {
- buffer += ' ';
- }
- CoreStorage & storage = ((Core *)api)->GetCoreStorage();
- const char * name = storage.GetName(item.nameId);
- switch(item.type)
- {
- case ICoreStorageItem::t_string:
- crt_snprintf(tmp, sizeof(tmp) - 1, "string %s = %s\n", name, strings[item.vString].c_str());
- buffer += tmp;
- break;
- case ICoreStorageItem::t_long:
- crt_snprintf(tmp, sizeof(tmp) - 1, "long %s = %i\n", name, item.vLong);
- buffer += tmp;
- break;
- case ICoreStorageItem::t_float:
- crt_snprintf(tmp, sizeof(tmp) - 1, "float %s = %f\n", name, item.vFloat);
- buffer += tmp;
- break;
- case ICoreStorageItem::t_folder:
- crt_snprintf(tmp, sizeof(tmp) - 1, "[%s]\n", name);
- buffer += tmp;
- item.vFolder->Print(tab + 4, buffer, -1);
- break;
- }
- }
|