BVB Source Codes

CRYENGINE Show ChunkFileWriters.cpp Source code

Return Download CRYENGINE: download ChunkFileWriters.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  File name: ChunkFileWriters.cpp
  5. //  Created:   2013/10/21 by Sergey Sokov
  6. //
  7. ////////////////////////////////////////////////////////////////////////////
  8.  
  9. #include "StdAfx.h"
  10. #include "ChunkFileWriters.h"
  11.  
  12. static inline size_t ComputeSizeOfAlignment(size_t pos, size_t alignment)
  13. {
  14.         if (alignment <= 1 || (alignment & (alignment - 1)))
  15.         {
  16.                 return 0;
  17.         }
  18.         const size_t mask = alignment - 1;
  19.         return (alignment - (pos & mask)) & mask;
  20. }
  21.  
  22. namespace ChunkFile
  23. {
  24.  
  25. //////////////////////////////////////////////////////////////////////////
  26.  
  27. bool IWriter::WriteZeros(size_t size)
  28. {
  29.         if (size <= 0)
  30.         {
  31.                 return true;
  32.         }
  33.  
  34.         char bf[1024];
  35.         memset(bf, 0, (sizeof(bf) < size ? sizeof(bf) : size));
  36.  
  37.         while (size > 0)
  38.         {
  39.                 const uint32 sz = (sizeof(bf) < size ? sizeof(bf) : size);
  40.                 size -= sz;
  41.                 if (!Write(bf, sz))
  42.                 {
  43.                         return false;
  44.                 }
  45.         }
  46.  
  47.         return true;
  48. }
  49.  
  50. //////////////////////////////////////////////////////////////////////////
  51.  
  52. OsFileWriter::OsFileWriter()
  53.         : m_f(0)
  54. {
  55. }
  56.  
  57. OsFileWriter::~OsFileWriter()
  58. {
  59.         Erase();
  60. }
  61.  
  62. bool OsFileWriter::Create(const char* filename)
  63. {
  64.         Erase();
  65.  
  66.         if (filename == 0 || filename[0] == 0)
  67.         {
  68.                 // RCLogError("Filename is empty");
  69.                 return false;
  70.         }
  71.  
  72.         m_filename = filename;
  73.  
  74.         m_f = fopen(filename, "wb");
  75.         if (!m_f)
  76.         {
  77.                 // RCLogError("Failed to create file %s.", m_filename.c_str());
  78.                 return false;
  79.         }
  80.  
  81.         m_offset = 0;
  82.  
  83.         return true;
  84. }
  85.  
  86. void OsFileWriter::Erase()
  87. {
  88.         if (m_f)
  89.         {
  90.                 Close();
  91.                 ::remove(m_filename.c_str());
  92.         }
  93. }
  94.  
  95. void OsFileWriter::Close()
  96. {
  97.         if (m_f)
  98.         {
  99.                 fclose(m_f);
  100.                 m_f = 0;
  101.         }
  102. }
  103.  
  104. int32 OsFileWriter::GetPos() const
  105. {
  106.         return m_offset;
  107. }
  108.  
  109. bool OsFileWriter::Write(const void* buffer, size_t size)
  110. {
  111.         if (!m_f)
  112.         {
  113.                 return false;
  114.         }
  115.  
  116.         if (size <= 0)
  117.         {
  118.                 return true;
  119.         }
  120.  
  121.         if (fwrite(buffer, size, 1, m_f) != 1)
  122.         {
  123.                 // RCLogError("Failed to write %u byte(s) to file %s.", (uint)size, m_filename.c_str());
  124.                 Erase();
  125.                 return false;
  126.         }
  127.  
  128.         m_offset += size;
  129.  
  130.         return true;
  131. }
  132.  
  133. //////////////////////////////////////////////////////////////////////////
  134. #if !defined(RESOURCE_COMPILER)
  135.  
  136. CryPakFileWriter::CryPakFileWriter()
  137.         : m_pPak(0)
  138.         , m_f(0)
  139. {
  140. }
  141.  
  142. CryPakFileWriter::~CryPakFileWriter()
  143. {
  144.         Erase();
  145. }
  146.  
  147. bool CryPakFileWriter::Create(ICryPak* pPak, const char* filename)
  148. {
  149.         Erase();
  150.  
  151.         if (pPak == 0 || filename == 0 || filename[0] == 0)
  152.         {
  153.                 return false;
  154.         }
  155.  
  156.         m_pPak = pPak;
  157.         m_filename = filename;
  158.  
  159.         m_f = m_pPak->FOpen(m_filename.c_str(), "w+b");
  160.  
  161.         if (!m_f)
  162.         {
  163.                 return false;
  164.         }
  165.  
  166.         m_offset = 0;
  167.  
  168.         return true;
  169. }
  170.  
  171. void CryPakFileWriter::Erase()
  172. {
  173.         if (m_f)
  174.         {
  175.                 Close();
  176.                 m_pPak->RemoveFile(m_filename.c_str());
  177.         }
  178. }
  179.  
  180. void CryPakFileWriter::Close()
  181. {
  182.         if (m_f)
  183.         {
  184.                 m_pPak->FClose(m_f);
  185.                 m_f = 0;
  186.         }
  187. }
  188.  
  189. int32 CryPakFileWriter::GetPos() const
  190. {
  191.         return m_offset;
  192. }
  193.  
  194. bool CryPakFileWriter::Write(const void* buffer, size_t size)
  195. {
  196.         if (!m_f)
  197.         {
  198.                 return false;
  199.         }
  200.  
  201.         if (size <= 0)
  202.         {
  203.                 return true;
  204.         }
  205.  
  206.         if (m_pPak->FWrite(buffer, 1, size, m_f) != size)
  207.         {
  208.                 Erase();
  209.                 return false;
  210.         }
  211.  
  212.         m_offset += size;
  213.  
  214.         return true;
  215. }
  216.  
  217. #endif
  218. //////////////////////////////////////////////////////////////////////////
  219.  
  220. MemoryWriter::MemoryWriter()
  221.         : m_ptr(0)
  222.         , m_size(0)
  223. {
  224. }
  225.  
  226. MemoryWriter::~MemoryWriter()
  227. {
  228. }
  229.  
  230. bool MemoryWriter::Start(void* ptr, int32 size)
  231. {
  232.         Erase();
  233.  
  234.         if (ptr == 0 || size <= 0)
  235.         {
  236.                 return false;
  237.         }
  238.  
  239.         m_ptr = (char*)ptr;
  240.         m_size = size;
  241.         m_offset = 0;
  242.  
  243.         return true;
  244. }
  245.  
  246. void MemoryWriter::Erase()
  247. {
  248.         m_ptr = 0;
  249.         m_size = 0;
  250. }
  251.  
  252. void MemoryWriter::Close()
  253. {
  254.         m_ptr = 0;
  255.         m_size = 0;
  256. }
  257.  
  258. int32 MemoryWriter::GetPos() const
  259. {
  260.         return m_offset;
  261. }
  262.  
  263. bool MemoryWriter::Write(const void* buffer, size_t size)
  264. {
  265.         if (!m_ptr)
  266.         {
  267.                 return false;
  268.         }
  269.  
  270.         if (size <= 0)
  271.         {
  272.                 return true;
  273.         }
  274.  
  275.         if ((size_t)m_offset + size > (size_t)m_size)
  276.         {
  277.                 Erase();
  278.                 return false;
  279.         }
  280.  
  281.         memcpy(&m_ptr[m_offset], buffer, size);
  282.         m_offset += size;
  283.  
  284.         return true;
  285. }
  286.  
  287. //////////////////////////////////////////////////////////////////////////
  288.  
  289. MemorylessChunkFileWriter::MemorylessChunkFileWriter(
  290.   EChunkFileFormat eFormat,
  291.   IWriter* pWriter)
  292.         : m_eChunkFileFormat(eFormat)
  293.         , m_pWriter(pWriter)
  294.         , m_alignment(4)
  295.         , m_chunkCount(0)
  296.         , m_eState(eState_Init)
  297. {
  298.         if (!m_pWriter)
  299.         {
  300.                 m_eState = eState_Fail;
  301.         }
  302. }
  303.  
  304. MemorylessChunkFileWriter::~MemorylessChunkFileWriter()
  305. {
  306.         if (m_eState != eState_Success)
  307.         {
  308.                 Fail();
  309.         }
  310. }
  311.  
  312. void MemorylessChunkFileWriter::SetAlignment(size_t alignment)
  313. {
  314.         m_alignment = (alignment < 1) ? 1 : alignment;
  315. }
  316.  
  317. bool MemorylessChunkFileWriter::StartPass()
  318. {
  319.         switch (m_eState)
  320.         {
  321.         case eState_Init:
  322.                 m_eState = eState_CountingChunks;
  323.                 m_chunkIndex = -1;
  324.                 break;
  325.         case eState_CountingChunks:
  326.                 WriteFileHeader(m_chunkIndex + 1, GetSizeOfHeader());
  327.                 m_eState = eState_WritingChunkTable;
  328.                 WriteChunkTableHeader(m_chunkIndex + 1);
  329.                 m_dataOffsetInFile = GetSizeOfHeader() + GetSizeOfChunkTable(m_chunkIndex + 1);
  330.                 m_chunkIndex = -1;
  331.                 break;
  332.         case eState_WritingChunkTable:
  333.                 if (m_chunkIndex >= 0)
  334.                 {
  335.                         WriteChunkEntry();
  336.                 }
  337.                 m_eState = eState_WritingData;
  338.                 m_dataOffsetInFile = GetSizeOfHeader() + GetSizeOfChunkTable(m_chunkIndex + 1);
  339.                 m_chunkIndex = -1;
  340.                 break;
  341.         case eState_WritingData:
  342.                 m_eState = eState_Success;
  343.                 m_pWriter->Close();
  344.                 return false;
  345.         case eState_Fail:
  346.                 return false;
  347.         default:
  348.                 assert(0);
  349.                 Fail();
  350.                 return false;
  351.         }
  352.         return true;
  353. }
  354.  
  355. void MemorylessChunkFileWriter::StartChunk(EEndianness eEndianness, uint32 type, uint32 version, uint32 id)
  356. {
  357.         if (type != 0)
  358.         {
  359.                 type = ConvertChunkTypeTo0x746(type);
  360.                 if (type == 0)
  361.                 {
  362.                         Fail();
  363.                         return;
  364.                 }
  365.         }
  366.  
  367.         if (version >= ChunkFile::ChunkTableEntry_0x746::kBigEndianVersionFlag)
  368.         {
  369.                 Fail();
  370.                 return;
  371.         }
  372.  
  373.         switch (m_eState)
  374.         {
  375.         case eState_CountingChunks:
  376.                 ++m_chunkIndex;
  377.                 break;
  378.         case eState_WritingChunkTable:
  379.                 if (m_chunkIndex >= 0)
  380.                 {
  381.                         WriteChunkEntry();
  382.                 }
  383.         /* fall through */
  384.         case eState_WritingData:
  385.                 {
  386.                         size_t size = ComputeSizeOfAlignment(m_dataOffsetInFile, m_alignment);
  387.  
  388.                         // Make sure that zero-length chunks have distinct positions in file
  389.                         if (size == 0 && m_chunkIndex > 0 && m_chunkSize == 0)
  390.                         {
  391.                                 size = m_alignment;
  392.                         }
  393.  
  394.                         m_dataOffsetInFile += size;
  395.                         m_chunkOffsetInFile = m_dataOffsetInFile;
  396.                         if (m_eState == eState_WritingData && !m_pWriter->WriteZeros(size))
  397.                         {
  398.                                 Fail();
  399.                                 return;
  400.                         }
  401.                 }
  402.  
  403.                 ++m_chunkIndex;
  404.                 m_chunkEndianness = eEndianness;
  405.                 m_chunkType = type;
  406.                 m_chunkVersion = version;
  407.                 m_chunkId = id;
  408.                 m_chunkSize = 0;
  409.  
  410.                 if (m_eChunkFileFormat == eChunkFileFormat_0x745 &&
  411.                     ChunkContainsHeader_0x744_0x745(m_chunkType, m_chunkVersion))
  412.                 {
  413.                         ChunkHeader_0x744_0x745 c;
  414.  
  415.                         c.type = ConvertChunkTypeTo0x745(m_chunkType);
  416.                         c.version = m_chunkVersion | (m_chunkEndianness == eEndianness_Big ? ChunkFile::ChunkHeader_0x744_0x745::kBigEndianVersionFlag : 0);
  417.                         c.id = m_chunkId;
  418.                         c.offsetInFile = m_chunkOffsetInFile;
  419.  
  420.                         if (SYSTEM_IS_BIG_ENDIAN)
  421.                         {
  422.                                 c.SwapEndianness();
  423.                         }
  424.  
  425.                         AddChunkData(&c, sizeof(c));
  426.                 }
  427.                 break;
  428.         default:
  429.                 Fail();
  430.                 break;
  431.         }
  432. }
  433.  
  434. void MemorylessChunkFileWriter::AddChunkData(void* ptr, size_t size)
  435. {
  436.         if (m_chunkIndex < 0)
  437.         {
  438.                 Fail();
  439.                 return;
  440.         }
  441.  
  442.         switch (m_eState)
  443.         {
  444.         case eState_CountingChunks:
  445.                 break;
  446.         case eState_WritingChunkTable:
  447.         case eState_WritingData:
  448.                 m_chunkSize += size;
  449.                 m_dataOffsetInFile += size;
  450.                 if (m_eState == eState_WritingData && !m_pWriter->Write(ptr, size))
  451.                 {
  452.                         Fail();
  453.                 }
  454.                 break;
  455.         default:
  456.                 Fail();
  457.                 break;
  458.         }
  459. }
  460.  
  461. void MemorylessChunkFileWriter::AddChunkDataZeros(size_t size)
  462. {
  463.         if (m_chunkIndex < 0)
  464.         {
  465.                 Fail();
  466.                 return;
  467.         }
  468.  
  469.         switch (m_eState)
  470.         {
  471.         case eState_CountingChunks:
  472.                 break;
  473.         case eState_WritingChunkTable:
  474.         case eState_WritingData:
  475.                 m_chunkSize += size;
  476.                 m_dataOffsetInFile += size;
  477.                 if (m_eState == eState_WritingData && !m_pWriter->WriteZeros(size))
  478.                 {
  479.                         Fail();
  480.                 }
  481.                 break;
  482.         default:
  483.                 Fail();
  484.                 break;
  485.         }
  486. }
  487.  
  488. void MemorylessChunkFileWriter::AddChunkDataAlignment(size_t alignment)
  489. {
  490.         const size_t size = ComputeSizeOfAlignment(m_chunkSize, alignment);
  491.         return AddChunkDataZeros(size);
  492. }
  493.  
  494. bool MemorylessChunkFileWriter::HasWrittenSuccessfully() const
  495. {
  496.         return m_eState == eState_Success;
  497. }
  498.  
  499. IWriter* MemorylessChunkFileWriter::GetWriter() const
  500. {
  501.         return m_pWriter;
  502. }
  503.  
  504. //////////////////////////////////////////////////////////////////////////
  505.  
  506. void MemorylessChunkFileWriter::Fail()
  507. {
  508.         m_eState = eState_Fail;
  509.         if (m_pWriter)
  510.         {
  511.                 m_pWriter->Erase();
  512.         }
  513. }
  514.  
  515. size_t MemorylessChunkFileWriter::GetSizeOfHeader() const
  516. {
  517.         return (m_eChunkFileFormat == eChunkFileFormat_0x745)
  518.                ? sizeof(FileHeader_0x744_0x745)
  519.                : sizeof(FileHeader_0x746);
  520. }
  521.  
  522. void MemorylessChunkFileWriter::WriteFileHeader(int32 chunkCount, uint32 chunkTableOffsetInFile)
  523. {
  524.         if (m_eChunkFileFormat == eChunkFileFormat_0x745)
  525.         {
  526.                 FileHeader_0x744_0x745 h;
  527.                 h.Set(chunkTableOffsetInFile);
  528.  
  529.                 if (SYSTEM_IS_BIG_ENDIAN)
  530.                 {
  531.                         h.SwapEndianness();
  532.                 }
  533.  
  534.                 if (!m_pWriter->Write(&h, sizeof(h)))
  535.                 {
  536.                         Fail();
  537.                 }
  538.         }
  539.         else
  540.         {
  541.                 FileHeader_0x746 h;
  542.                 h.Set(chunkCount, chunkTableOffsetInFile);
  543.  
  544.                 if (SYSTEM_IS_BIG_ENDIAN)
  545.                 {
  546.                         h.SwapEndianness();
  547.                 }
  548.  
  549.                 if (!m_pWriter->Write(&h, sizeof(h)))
  550.                 {
  551.                         Fail();
  552.                 }
  553.         }
  554. }
  555.  
  556. size_t MemorylessChunkFileWriter::GetSizeOfChunkTable(int32 chunkCount) const
  557. {
  558.         if (m_eChunkFileFormat == eChunkFileFormat_0x745)
  559.         {
  560.                 return sizeof(uint32) + chunkCount * sizeof(ChunkTableEntry_0x745);
  561.         }
  562.         else
  563.         {
  564.                 return chunkCount * sizeof(ChunkTableEntry_0x746);
  565.         }
  566. }
  567.  
  568. void MemorylessChunkFileWriter::WriteChunkTableHeader(int32 chunkCount)
  569. {
  570.         if (m_eChunkFileFormat == eChunkFileFormat_0x745)
  571.         {
  572.                 if (SYSTEM_IS_BIG_ENDIAN)
  573.                 {
  574.                         SwapEndianBase(&chunkCount, 1);
  575.                 }
  576.  
  577.                 if (!m_pWriter->Write(&chunkCount, sizeof(chunkCount)))
  578.                 {
  579.                         Fail();
  580.                 }
  581.         }
  582. }
  583.  
  584. void MemorylessChunkFileWriter::WriteChunkEntry()
  585. {
  586.         if (m_chunkIndex < 0)
  587.         {
  588.                 assert(0);
  589.                 Fail();
  590.                 return;
  591.         }
  592.  
  593.         if (m_eChunkFileFormat == eChunkFileFormat_0x745)
  594.         {
  595.                 ChunkTableEntry_0x745 c;
  596.  
  597.                 c.type = ConvertChunkTypeTo0x745(m_chunkType);
  598.                 c.version = m_chunkVersion | (m_chunkEndianness == eEndianness_Big ? ChunkFile::ChunkHeader_0x744_0x745::kBigEndianVersionFlag : 0);
  599.                 c.id = m_chunkId;
  600.                 c.size = m_chunkSize;
  601.                 c.offsetInFile = m_chunkOffsetInFile;
  602.  
  603.                 if (SYSTEM_IS_BIG_ENDIAN)
  604.                 {
  605.                         c.SwapEndianness();
  606.                 }
  607.  
  608.                 if (!m_pWriter->Write(&c, sizeof(c)))
  609.                 {
  610.                         Fail();
  611.                 }
  612.         }
  613.         else
  614.         {
  615.                 ChunkTableEntry_0x746 c;
  616.  
  617.                 c.type = m_chunkType;
  618.                 c.version = m_chunkVersion | (m_chunkEndianness == eEndianness_Big ? ChunkFile::ChunkTableEntry_0x746::kBigEndianVersionFlag : 0);
  619.                 c.id = m_chunkId;
  620.                 c.size = m_chunkSize;
  621.                 c.offsetInFile = m_chunkOffsetInFile;
  622.  
  623.                 if (SYSTEM_IS_BIG_ENDIAN)
  624.                 {
  625.                         c.SwapEndianness();
  626.                 }
  627.  
  628.                 if (!m_pWriter->Write(&c, sizeof(c)))
  629.                 {
  630.                         Fail();
  631.                 }
  632.         }
  633. }
  634.  
  635. //////////////////////////////////////////////////////////////////////////
  636.  
  637. }  // namespace ChunkFile
  638.  
downloadChunkFileWriters.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top