CoreStorageFolder.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. //============================================================================================
  2. // Spirenkov Maxim, 2004, 2008
  3. //============================================================================================
  4. // CoreStorageFolder
  5. //============================================================================================
  6. #include "CoreStorageFolder.h"
  7. #include "CoreStorage.h"
  8. #include "Core.h"
  9. #include "..\..\common_h\data_swizzle.h"
  10. //============================================================================================
  11. //Streams
  12. //============================================================================================
  13. //WriteStream
  14. //--------------------------------------------------------------------------------------------
  15. CoreStorageFolder::WriteStream::WriteStream(array<byte> & _data) : data(_data)
  16. {
  17. offset = -1;
  18. }
  19. void CoreStorageFolder::WriteStream::WriteByte(const byte & b)
  20. {
  21. data.Add(b);
  22. }
  23. void CoreStorageFolder::WriteStream::WriteDWord(const dword & dw)
  24. {
  25. long index = data;
  26. data.AddElements(sizeof(dword));
  27. core_unaligned dword & v = (core_unaligned dword &)data[index];
  28. v = SwizzleDWord(dw);
  29. }
  30. void CoreStorageFolder::WriteStream::WriteFloat(const float & fl)
  31. {
  32. long index = data;
  33. data.AddElements(sizeof(float));
  34. core_unaligned float & v = (core_unaligned float &)data[index];
  35. v = SwizzleFloat(fl);
  36. }
  37. void CoreStorageFolder::WriteStream::WriteString(const char * str)
  38. {
  39. if(!str) str = "";
  40. for(long s = 0; str[s]; s++); s++;
  41. long index = data;
  42. data.AddElements(s);
  43. memcpy(&data[index], str, s);
  44. }
  45. void CoreStorageFolder::WriteStream::WriteTable(const void * buffer, dword size)
  46. {
  47. if(size > 0)
  48. {
  49. long index = data;
  50. data.AddElements(size);
  51. memcpy(&data[index], buffer, size);
  52. }
  53. }
  54. void CoreStorageFolder::WriteStream::PinSizePosition()
  55. {
  56. offset = data;
  57. data.AddElements(sizeof(dword));
  58. }
  59. void CoreStorageFolder::WriteStream::SaveSize()
  60. {
  61. Assert(offset > 0);
  62. long size = data - offset;
  63. Assert(size > 0);
  64. core_unaligned dword & v = (core_unaligned dword &)data[offset];
  65. v = SwizzleDWord((dword)size);
  66. }
  67. //--------------------------------------------------------------------------------------------
  68. //ReadStream
  69. //--------------------------------------------------------------------------------------------
  70. CoreStorageFolder::ReadStream::ReadStream(dword & _pointer, const void * _data, dword _size) : pointer(_pointer)
  71. {
  72. data = (const byte *)_data;
  73. size = _size;
  74. offset = -1;
  75. offsetSize = -1;
  76. }
  77. bool CoreStorageFolder::ReadStream::ReadByte(byte & b)
  78. {
  79. if(pointer + sizeof(byte) > size)
  80. {
  81. return false;
  82. }
  83. b = data[pointer];
  84. pointer += sizeof(byte);
  85. return true;
  86. }
  87. bool CoreStorageFolder::ReadStream::ReadDWord(dword & dw)
  88. {
  89. if(pointer + sizeof(dword) > size)
  90. {
  91. return false;
  92. }
  93. dw = SwizzleDWord((core_unaligned dword &)data[pointer]);
  94. pointer += sizeof(dword);
  95. return true;
  96. }
  97. bool CoreStorageFolder::ReadStream::ReadFloat(float & fl)
  98. {
  99. if(pointer + sizeof(float) > size)
  100. {
  101. return false;
  102. }
  103. fl = SwizzleFloat((core_unaligned float &)data[pointer]);
  104. pointer += sizeof(float);
  105. return true;
  106. }
  107. bool CoreStorageFolder::ReadStream::ReadString(string & str)
  108. {
  109. for(str.Empty(); pointer < size; pointer++)
  110. {
  111. char c = data[pointer];
  112. if(!c)
  113. {
  114. pointer++;
  115. return true;
  116. }
  117. str += c;
  118. }
  119. str.Empty();
  120. return false;
  121. }
  122. bool CoreStorageFolder::ReadStream::ReadTable(void * buffer, dword size)
  123. {
  124. if(pointer + size > this->size)
  125. {
  126. return false;
  127. }
  128. if(size > 0)
  129. {
  130. memcpy(buffer, &data[pointer], size);
  131. }
  132. pointer += size;
  133. return true;
  134. }
  135. bool CoreStorageFolder::ReadStream::PinSizePosition()
  136. {
  137. offset = pointer;
  138. return ReadDWord(offsetSize);
  139. }
  140. bool CoreStorageFolder::ReadStream::CheckSize()
  141. {
  142. long s = pointer - offset;
  143. if(s < 0)
  144. {
  145. return false;
  146. }
  147. if(s != offsetSize)
  148. {
  149. return false;
  150. }
  151. return true;
  152. }
  153. //============================================================================================
  154. //CoreStorageFolder
  155. //============================================================================================
  156. CoreStorageFolder::CoreStorageFolder(CoreStorageFolder * p, long nId) : items(_FL_),
  157. strings(_FL_)
  158. {
  159. parent = p;
  160. nameId = nId;
  161. }
  162. CoreStorageFolder::~CoreStorageFolder()
  163. {
  164. for(long i = 0; i < items; i++)
  165. {
  166. if(items[i].type == ICoreStorageItem::t_folder)
  167. {
  168. delete items[i].vFolder;
  169. }
  170. }
  171. items.Empty();
  172. }
  173. //Получить по пути итем, если объекты не созданы, попытаться создать
  174. //Если встречается на месте нужного итем другого типа то возвращает индекс этого итем и папку null
  175. CoreStorageFolder * CoreStorageFolder::FindItem(const array<long> & p, ICoreStorageItem::Type type, bool isCreatePath, long & index)
  176. {
  177. CoreStorageFolder * folder = this;
  178. for(long i = 0; i < p; i++)
  179. {
  180. //Ищем поле с заданным идентификатором
  181. long id = p[i];
  182. Item * its = folder->items.GetBuffer();
  183. long count = folder->items.Size();
  184. index = -1;
  185. for(long n = 0; n < count; n++)
  186. {
  187. if(its[n].nameId == id)
  188. {
  189. index = n;
  190. break;
  191. }
  192. }
  193. if(index >= 0)
  194. {
  195. //Элемент с таким идентификатором найден, проверяем тип
  196. Item & item = folder->items[index];
  197. if(i >= p - 1)
  198. {
  199. //Последний элемент
  200. if(type != ICoreStorageItem::t_error)
  201. {
  202. //Требуеться проверить тип переменной
  203. if(item.type != type)
  204. {
  205. return null;
  206. }
  207. }
  208. return folder;
  209. }
  210. //Не последний элемент должен быть папкой
  211. if(item.type != ICoreStorageItem::t_folder)
  212. {
  213. return null;
  214. }
  215. folder = item.vFolder;
  216. Assert(folder);
  217. }else{
  218. //Нету такого поля если в режиме создания то создаём папку
  219. if(!isCreatePath)
  220. {
  221. return null;
  222. }
  223. index = folder->items.Add();
  224. Item & item = folder->items[index];
  225. item.nameId = id;
  226. if(i >= p - 1)
  227. {
  228. //Последний элемент
  229. item.type = type;
  230. switch(type)
  231. {
  232. case ICoreStorageItem::t_string:
  233. item.vString = folder->strings.Add();
  234. break;
  235. case ICoreStorageItem::t_long:
  236. item.vLong = 0;
  237. break;
  238. case ICoreStorageItem::t_float:
  239. item.vFloat = 0.0f;
  240. break;
  241. case ICoreStorageItem::t_folder:
  242. item.vFolder = NEW CoreStorageFolder(folder, id);
  243. break;
  244. default:
  245. Assert(false);
  246. }
  247. return folder;
  248. }
  249. //Папка
  250. item.type = ICoreStorageItem::t_folder;
  251. folder = item.vFolder = NEW CoreStorageFolder(folder, id);
  252. }
  253. }
  254. //Указана текущая папка
  255. index = -1;
  256. if(type != ICoreStorageItem::t_error)
  257. {
  258. if(type != ICoreStorageItem::t_folder)
  259. {
  260. return null;
  261. }
  262. }
  263. return this;
  264. }
  265. //Заполнить полный путь до папки
  266. void CoreStorageFolder::BuildFullPath(array<long> & p, long size)
  267. {
  268. if(parent)
  269. {
  270. parent->BuildFullPath(p, size + 1);
  271. p.Add(nameId);
  272. }else{
  273. p.Empty();
  274. p.Reserve(size);
  275. }
  276. }
  277. //Вывести содержимое в строку, (перевод строки \n)
  278. void CoreStorageFolder::Print(long tab, string & buffer, long index)
  279. {
  280. if(index < 0)
  281. {
  282. buffer.Reserve(items.Size()*(tab + 1024));
  283. for(long i = 0; i < items; i++)
  284. {
  285. PrintItemToBuffer(tab, buffer, items[i]);
  286. }
  287. }else{
  288. buffer.Reserve(tab + 1024);
  289. PrintItemToBuffer(tab, buffer, items[index]);
  290. }
  291. }
  292. //Сохранить группу
  293. void CoreStorageFolder::Save(long index, WriteStream & stream)
  294. {
  295. if(index < 0)
  296. {
  297. //Надо сохранить всю папку
  298. stream.WriteDWord(items.Size());
  299. for(long i = 0; i < items; i++)
  300. {
  301. SaveItem(items[i], stream);
  302. }
  303. }else{
  304. //Надо сохранить отдельный элемент
  305. stream.WriteDWord(1);
  306. SaveItem(items[index], stream);
  307. }
  308. }
  309. //Прочитать группу
  310. bool CoreStorageFolder::Load(ReadStream & stream)
  311. {
  312. CoreStorage & storage = ((Core *)api)->GetCoreStorage();
  313. //Читаем количество полей
  314. dword count = 0;
  315. if(!stream.ReadDWord(count))
  316. {
  317. return false;
  318. }
  319. items.Reserve(items.Size() + count);
  320. //Читаем поля
  321. string name;
  322. for(dword i = 0; i < count; i++)
  323. {
  324. byte type;
  325. if(!stream.ReadByte(type))
  326. {
  327. return false;
  328. }
  329. if(!stream.ReadString(name))
  330. {
  331. return false;
  332. }
  333. Item item;
  334. item.nameId = storage.SaveName(name.c_str());
  335. //Проверяем такой среди добавленых
  336. for(long j = 0; j < items; j++)
  337. {
  338. Item & it = items[j];
  339. if(it.nameId == item.nameId)
  340. {
  341. //Опа, есть такое
  342. if(it.type != type)
  343. {
  344. //Жёпа, нельзя перезаписать значение
  345. return false;
  346. }
  347. break;
  348. }
  349. }
  350. switch(type)
  351. {
  352. case ICoreStorageItem::t_string:
  353. if(j >= items)
  354. {
  355. item.type = ICoreStorageItem::t_string;
  356. item.vString = strings.Add();
  357. if(!stream.ReadString(strings[item.vString]))
  358. {
  359. strings.DelIndex(item.vString);
  360. return false;
  361. }
  362. items.Add(item);
  363. }else{
  364. if(!stream.ReadString(strings[items[j].vString]))
  365. {
  366. return false;
  367. }
  368. }
  369. break;
  370. case ICoreStorageItem::t_long:
  371. if(j >= items)
  372. {
  373. item.type = ICoreStorageItem::t_long;
  374. if(!stream.ReadDWord((dword &)item.vLong))
  375. {
  376. return false;
  377. }
  378. items.Add(item);
  379. }else{
  380. if(!stream.ReadDWord((dword &)items[j].vLong))
  381. {
  382. return false;
  383. }
  384. }
  385. break;
  386. case ICoreStorageItem::t_float:
  387. if(j >= items)
  388. {
  389. item.type = ICoreStorageItem::t_float;
  390. if(!stream.ReadFloat(item.vFloat))
  391. {
  392. return false;
  393. }
  394. items.Add(item);
  395. }else{
  396. if(!stream.ReadFloat(items[j].vFloat))
  397. {
  398. return false;
  399. }
  400. }
  401. break;
  402. case ICoreStorageItem::t_folder:
  403. if(j >= items)
  404. {
  405. item.type = ICoreStorageItem::t_folder;
  406. item.vFolder = NEW CoreStorageFolder(this, item.nameId);
  407. if(!item.vFolder->Load(stream))
  408. {
  409. delete item.vFolder;
  410. return false;
  411. }
  412. items.Add(item);
  413. }else{
  414. if(!items[j].vFolder->Load(stream))
  415. {
  416. return false;
  417. }
  418. }
  419. break;
  420. default:
  421. return false;
  422. }
  423. }
  424. return true;
  425. }
  426. //Удалить все дочернии поля
  427. void CoreStorageFolder::Delete(long index)
  428. {
  429. if(index >= 0)
  430. {
  431. if(items[index].type == ICoreStorageItem::t_folder)
  432. {
  433. delete items[index].vFolder;
  434. }
  435. items.DelIndex(index);
  436. }else{
  437. for(long i = 0; i < items; i++)
  438. {
  439. if(items[i].type == ICoreStorageItem::t_folder)
  440. {
  441. delete items[i].vFolder;
  442. }
  443. }
  444. items.Empty();
  445. }
  446. }
  447. //Сохранить в поток поле
  448. void CoreStorageFolder::SaveItem(Item & item, WriteStream & stream)
  449. {
  450. //Тип
  451. stream.WriteByte(item.type);
  452. //Имя
  453. CoreStorage & storage = ((Core *)api)->GetCoreStorage();
  454. const char * name = storage.GetName(item.nameId);
  455. stream.WriteString(name);
  456. //Данные
  457. switch(item.type)
  458. {
  459. case ICoreStorageItem::t_string:
  460. stream.WriteString(strings[item.vString].c_str());
  461. break;
  462. case ICoreStorageItem::t_long:
  463. stream.WriteDWord((dword)item.vLong);
  464. break;
  465. case ICoreStorageItem::t_float:
  466. stream.WriteFloat(item.vFloat);
  467. break;
  468. case ICoreStorageItem::t_folder:
  469. item.vFolder->Save(-1, stream);
  470. break;
  471. default:
  472. Assert(false);
  473. }
  474. }
  475. //Вывести элемент в буфер
  476. void CoreStorageFolder::PrintItemToBuffer(long tab, string & buffer, Item & item)
  477. {
  478. char tmp[1024];
  479. for(long i = 0; i < tab; i++)
  480. {
  481. buffer += ' ';
  482. }
  483. CoreStorage & storage = ((Core *)api)->GetCoreStorage();
  484. const char * name = storage.GetName(item.nameId);
  485. switch(item.type)
  486. {
  487. case ICoreStorageItem::t_string:
  488. crt_snprintf(tmp, sizeof(tmp) - 1, "string %s = %s\n", name, strings[item.vString].c_str());
  489. buffer += tmp;
  490. break;
  491. case ICoreStorageItem::t_long:
  492. crt_snprintf(tmp, sizeof(tmp) - 1, "long %s = %i\n", name, item.vLong);
  493. buffer += tmp;
  494. break;
  495. case ICoreStorageItem::t_float:
  496. crt_snprintf(tmp, sizeof(tmp) - 1, "float %s = %f\n", name, item.vFloat);
  497. buffer += tmp;
  498. break;
  499. case ICoreStorageItem::t_folder:
  500. crt_snprintf(tmp, sizeof(tmp) - 1, "[%s]\n", name);
  501. buffer += tmp;
  502. item.vFolder->Print(tab + 4, buffer, -1);
  503. break;
  504. }
  505. }