NamedData.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. // Description : Collection of Named data blocks.
  9. #include "EditorDefs.h"
  10. #include "NamedData.h"
  11. // Editor
  12. #include "Util/CryMemFile.h" // for CryMemFile
  13. #include "Util/PakFile.h" // for CPakFile
  14. //////////////////////////////////////////////////////////////////////////
  15. CNamedData::CNamedData()
  16. {
  17. }
  18. //////////////////////////////////////////////////////////////////////////
  19. CNamedData::~CNamedData()
  20. {
  21. Clear();
  22. }
  23. //////////////////////////////////////////////////////////////////////////
  24. void CNamedData::AddDataBlock(const QString& blockName, void* pData, int nSize, bool bCompress)
  25. {
  26. assert(pData);
  27. assert(nSize > 0);
  28. DataBlock* pBlock = stl::find_in_map(m_blocks, blockName, (DataBlock*)nullptr);
  29. if (pBlock)
  30. {
  31. delete pBlock;
  32. }
  33. pBlock = new DataBlock();
  34. pBlock->bFastCompression = !bCompress;
  35. bCompress = false;
  36. if (bCompress)
  37. {
  38. pBlock->bCompressed = true;
  39. CMemoryBlock temp;
  40. temp.Attach(pData, nSize);
  41. temp.Compress(pBlock->compressedData);
  42. }
  43. else
  44. {
  45. pBlock->bCompressed = false;
  46. pBlock->data.Allocate(nSize);
  47. pBlock->data.Copy(pData, nSize);
  48. }
  49. m_blocks[blockName] = pBlock;
  50. }
  51. void CNamedData::AddDataBlock(const QString& blockName, CMemoryBlock& mem)
  52. {
  53. DataBlock* pBlock = stl::find_in_map(m_blocks, blockName, (DataBlock*)nullptr);
  54. if (pBlock)
  55. {
  56. delete pBlock;
  57. }
  58. pBlock = new DataBlock();
  59. pBlock->bFastCompression = false;
  60. if (mem.GetUncompressedSize() != 0)
  61. {
  62. // This is compressed block.
  63. pBlock->bCompressed = true;
  64. pBlock->compressedData = mem;
  65. }
  66. else
  67. {
  68. pBlock->bCompressed = false;
  69. pBlock->data = mem;
  70. }
  71. m_blocks[blockName] = pBlock;
  72. }
  73. //////////////////////////////////////////////////////////////////////////
  74. void CNamedData::Clear()
  75. {
  76. for (TBlocks::iterator it = m_blocks.begin(); it != m_blocks.end(); ++it)
  77. {
  78. delete it->second;
  79. }
  80. m_blocks.clear();
  81. }
  82. //////////////////////////////////////////////////////////////////////////
  83. bool CNamedData::GetDataBlock(const QString& blockName, void*& pData, int& nSize)
  84. {
  85. pData = nullptr;
  86. nSize = 0;
  87. bool bUncompressed = false;
  88. CMemoryBlock* mem = GetDataBlock(blockName, bUncompressed);
  89. if (mem)
  90. {
  91. pData = mem->GetBuffer();
  92. nSize = mem->GetSize();
  93. return true;
  94. }
  95. return false;
  96. }
  97. //////////////////////////////////////////////////////////////////////////
  98. CMemoryBlock* CNamedData::GetDataBlock(const QString& blockName, bool& bCompressed)
  99. {
  100. DataBlock* pBlock = stl::find_in_map(m_blocks, blockName, (DataBlock*)nullptr);
  101. if (!pBlock)
  102. {
  103. return nullptr;
  104. }
  105. if (bCompressed)
  106. {
  107. // Return compressed data.
  108. if (!pBlock->compressedData.IsEmpty())
  109. {
  110. return &pBlock->compressedData;
  111. }
  112. }
  113. else
  114. {
  115. // Return normal data.
  116. if (!pBlock->data.IsEmpty())
  117. {
  118. return &pBlock->data;
  119. }
  120. else
  121. {
  122. // Uncompress compressed block.
  123. if (!pBlock->compressedData.IsEmpty())
  124. {
  125. pBlock->compressedData.Uncompress(pBlock->data);
  126. return &pBlock->data;
  127. }
  128. }
  129. }
  130. return nullptr;
  131. }
  132. //////////////////////////////////////////////////////////////////////////
  133. bool CNamedData::Serialize(CArchive& ar)
  134. {
  135. if (ar.IsStoring())
  136. {
  137. int iSize = static_cast<int>(m_blocks.size());
  138. ar << iSize;
  139. for (TBlocks::iterator it = m_blocks.begin(); it != m_blocks.end(); it++)
  140. {
  141. QString key = it->first;
  142. DataBlock* pBlock = it->second;
  143. unsigned int nOriginalSize;
  144. unsigned int nSizeFlags;
  145. unsigned int flags = 0;
  146. if (pBlock->bCompressed)
  147. {
  148. nOriginalSize = pBlock->compressedData.GetUncompressedSize();
  149. // Compressed data.
  150. unsigned int destSize = static_cast<unsigned int>(pBlock->compressedData.GetSize());
  151. void* dest = pBlock->compressedData.GetBuffer();
  152. nSizeFlags = destSize | (1u << 31);
  153. ar << key;
  154. ar << nSizeFlags; // Current size of data + 1 bit for compressed flag.
  155. ar << nOriginalSize; // Size of uncompressed data.
  156. ar << flags; // Some additional flags.
  157. ar.Write(dest, destSize);
  158. }
  159. else
  160. {
  161. nOriginalSize = pBlock->data.GetSize();
  162. void* dest = pBlock->data.GetBuffer();
  163. nSizeFlags = nOriginalSize;
  164. ar << key;
  165. ar << nSizeFlags;
  166. ar << nOriginalSize; // Size of uncompressed data.
  167. ar << flags; // Some additional flags.
  168. ar.Write(dest, nOriginalSize);
  169. }
  170. }
  171. }
  172. else
  173. {
  174. Clear();
  175. int iSize;
  176. ar >> iSize;
  177. for (int i = 0; i < iSize && ar.status() == QDataStream::Ok; i++)
  178. {
  179. QString key;
  180. unsigned int nSizeFlags = 0;
  181. unsigned int nSize = 0;
  182. unsigned int nOriginalSize = 0;
  183. unsigned int flags = 0;
  184. bool bCompressed = false;
  185. DataBlock* pBlock = new DataBlock();
  186. ar >> key;
  187. ar >> nSizeFlags;
  188. ar >> nOriginalSize;
  189. ar >> flags;
  190. nSize = nSizeFlags & (~(1 << 31));
  191. bCompressed = (nSizeFlags & (1 << 31)) != 0;
  192. if (nSize)
  193. {
  194. if (bCompressed)
  195. {
  196. pBlock->compressedData.Allocate(nSize, nOriginalSize);
  197. void* pSrcData = pBlock->compressedData.GetBuffer();
  198. // Read compressed data.
  199. ar.Read(pSrcData, nSize);
  200. }
  201. else
  202. {
  203. pBlock->data.Allocate(nSize);
  204. void* pSrcData = pBlock->data.GetBuffer();
  205. // Read uncompressed data.
  206. ar.Read(pSrcData, nSize);
  207. }
  208. }
  209. m_blocks[key] = pBlock;
  210. }
  211. }
  212. return ar.status() == QDataStream::Ok;
  213. }
  214. //////////////////////////////////////////////////////////////////////////
  215. void CNamedData::Save(CPakFile& pakFile)
  216. {
  217. for (TBlocks::iterator it = m_blocks.begin(); it != m_blocks.end(); it++)
  218. {
  219. QString key = it->first;
  220. DataBlock* pBlock = it->second;
  221. if (!pBlock->bCompressed)
  222. {
  223. QString filename = key + ".editor_data";
  224. pakFile.UpdateFile(filename.toUtf8().data(), pBlock->data, true, pBlock->bFastCompression ? AZ::IO::INestedArchive::LEVEL_FASTEST : AZ::IO::INestedArchive::LEVEL_BETTER);
  225. }
  226. else
  227. {
  228. int nOriginalSize = pBlock->compressedData.GetUncompressedSize();
  229. CCryMemFile memFile;
  230. // Write uncompressed data size.
  231. memFile.Write(&nOriginalSize, sizeof(nOriginalSize));
  232. // Write compressed data.
  233. memFile.Write(pBlock->compressedData.GetBuffer(), pBlock->compressedData.GetSize());
  234. pakFile.UpdateFile((key + ".editor_datac").toUtf8().data(), memFile, false);
  235. }
  236. }
  237. }
  238. //////////////////////////////////////////////////////////////////////////
  239. bool CNamedData::Load(const QString& levelPath, [[maybe_unused]] CPakFile& pakFile)
  240. {
  241. int i;
  242. IFileUtil::FileArray files;
  243. CFileUtil::ScanDirectory(levelPath, "*.editor_data", files, false);
  244. for (i = 0; i < files.size(); i++)
  245. {
  246. QString filename = files[i].filename;
  247. CCryFile cfile;
  248. if (cfile.Open(Path::Make(levelPath, filename).toUtf8().data(), "rb"))
  249. {
  250. int fileSize = static_cast<int>(cfile.GetLength());
  251. if (fileSize > 0)
  252. {
  253. QString key = Path::GetFileName(filename);
  254. // Read data block.
  255. DataBlock* pBlock = new DataBlock();
  256. pBlock->data.Allocate(fileSize);
  257. cfile.ReadRaw(pBlock->data.GetBuffer(), fileSize);
  258. m_blocks[key] = pBlock;
  259. }
  260. }
  261. }
  262. files.clear();
  263. // Scan compressed data.
  264. CFileUtil::ScanDirectory(levelPath, "*.editor_datac", files, false);
  265. for (i = 0; i < files.size(); i++)
  266. {
  267. QString filename = files[i].filename;
  268. CCryFile cfile;
  269. if (cfile.Open(Path::Make(levelPath, filename).toUtf8().data(), "rb"))
  270. {
  271. int fileSize = static_cast<uint32>(cfile.GetLength());
  272. if (fileSize > 0)
  273. {
  274. // Read uncompressed data size.
  275. int nOriginalSize = 0;
  276. cfile.ReadType(&nOriginalSize);
  277. // Read uncompressed data.
  278. int nDataSize = fileSize - sizeof(nOriginalSize);
  279. QString key = Path::GetFileName(filename);
  280. // Read data block.
  281. DataBlock* pBlock = new DataBlock();
  282. pBlock->compressedData.Allocate(nDataSize, nOriginalSize);
  283. cfile.ReadRaw(pBlock->compressedData.GetBuffer(), nDataSize);
  284. m_blocks[key] = pBlock;
  285. }
  286. }
  287. }
  288. return true;
  289. }
  290. void CNamedData::SaveToFiles(const QString& rootPath)
  291. {
  292. for (TBlocks::iterator it = m_blocks.begin(); it != m_blocks.end(); it++)
  293. {
  294. QString key = it->first;
  295. DataBlock* pBlock = it->second;
  296. QString filename = rootPath + key;
  297. if (pBlock->bCompressed)
  298. {
  299. filename += ".editor_datac";
  300. CCryFile file(filename.toUtf8().data(), "wb");
  301. int nOriginalSize = pBlock->compressedData.GetUncompressedSize();
  302. file.Write(&nOriginalSize, sizeof(nOriginalSize));
  303. file.Write(pBlock->compressedData.GetBuffer(), pBlock->compressedData.GetSize());
  304. }
  305. else
  306. {
  307. filename += ".editor_data";
  308. CCryFile file(filename.toUtf8().data(), "wb");
  309. file.Write(pBlock->data.GetBuffer(), pBlock->data.GetSize());
  310. }
  311. }
  312. }
  313. void CNamedData::LoadFromFiles(const QString& rootPath)
  314. {
  315. // TODO: Unify code paths in a nicer way!
  316. CPakFile dummyPak;
  317. Load(rootPath, dummyPak);
  318. }
  319. CNamedData::DataBlock::DataBlock()
  320. {
  321. }