tagblock.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header: /VSS_Sync/wwlib/tagblock.h 6 10/17/00 4:48p Vss_sync $ */
  19. /***********************************************************************************************
  20. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : WWLib *
  24. * *
  25. * $Archive:: /VSS_Sync/wwlib/tagblock.h $*
  26. * *
  27. * $Author:: Vss_sync $*
  28. * *
  29. * $Modtime:: 10/16/00 11:42a $*
  30. * *
  31. * $Revision:: 6 $*
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  36. #if defined(_MSC_VER)
  37. #pragma once
  38. #endif
  39. #ifndef TAGBLOCK_H
  40. #define TAGBLOCK_H
  41. #include "slist.h"
  42. #include "crc.h"
  43. #include "rawfile.h"
  44. #include <string.h>
  45. class TagBlockHandle;
  46. class TagBlockIndex;
  47. //////////////////////////////////////////////////////////////////////////////////////////////////
  48. //////////////////////////////////// Start of TagBlockHandle///////////////////////////////////////
  49. // TagBlockFile: Enables a file to have named (tagged) variable size blocks. User can
  50. // then open a block for reading. User may also create new blocks at the end of the
  51. // file. There may only be one block open for writting, unlimited blocks can be open for
  52. // reading. It can be thought of as a .MIX file that can have files added to it at any time.
  53. // One problem is it is a Write Once/Read Many solution.
  54. //
  55. // Usage: All user access to a TagBlockFile is done through TagBlockHandle.
  56. // A TagBlockHandle is created by TagBlockFile::Create_Tag() or Open_Tag(). It is destroyed
  57. // by either TagBlockFile::Close_Tag() or you can just destroy the handle with delete().
  58. //
  59. //
  60. class TagBlockFile : protected RawFileClass
  61. {
  62. public:
  63. //////////////////////////////////////////////////////////////////////////////////////////
  64. /////////////////////////////// Public Member Functions ///////////////////////////////////
  65. ///////////////////////////////////////////////////////////////////////////////////////////
  66. // Open up the tag file. It may or may not exist.
  67. TagBlockFile(const char *fname);
  68. virtual ~TagBlockFile();
  69. // DANGEROUS!! Resets entire file and makes small
  70. virtual void Reset_File();
  71. // Creation of a Handle so block can be crated/writen/read.
  72. // Use delete to destroy handle or use Close_Tag().
  73. // Open_Tag() returns NULL if tag not found.
  74. // Create_Tag() returns NULL if tag already exists.
  75. TagBlockHandle *Open_Tag(const char *tagname);
  76. TagBlockHandle *Create_Tag(const char *tagname);
  77. void Close_Tag(TagBlockHandle *handle);
  78. int Does_Tag_Exist(const char *tagname) {
  79. return(Find_Block(tagname) != NULL);
  80. }
  81. virtual unsigned long Get_Date_Time(void) {
  82. return(FileTime);
  83. }
  84. // Methods to figure an offset of the tag name and the data
  85. // given the offset of the start of the block (BlockHeader)..
  86. static int Calc_Tag_Offset(int blockoffset) {
  87. return(blockoffset + sizeof(BlockHeader));
  88. }
  89. static int Calc_Data_Offset(int blockoffset, const char *tagname) {
  90. return(Calc_Tag_Offset(blockoffset) + strlen(tagname) + 1);
  91. }
  92. protected:
  93. ///////////////////////////////////////////////////////////////////////////////////////////
  94. /////////////////////////////// Supporting Structures /////////////////////////////////////
  95. ///////////////////////////////////////////////////////////////////////////////////////////
  96. enum {
  97. // Put in date when format is changed.
  98. FILE_VERSION = 20000626,
  99. MAX_TAG_NAME_SIZE = 1024,
  100. };
  101. // This is the header that is in both the IndexFile and the DataFile.
  102. // They should be match except for the difference in the Version number as defined by enum.
  103. struct FileHeader
  104. {
  105. FileHeader() {memset(this, 0, sizeof(*this));}
  106. // Version number to make sure that it we are compatable and also to
  107. // verify that this is the file we think it is.
  108. unsigned Version;
  109. // Number of blocks in file.
  110. int NumBlocks;
  111. // This is how much data is actually valid in the file. There may be
  112. // extra room at end of file if file size is preset or the file is corrupt.
  113. int FileSize;
  114. };
  115. // Each block in the file has a header before it.
  116. struct BlockHeader
  117. {
  118. BlockHeader() {memset(this, 0, sizeof(*this));}
  119. BlockHeader(int index, int tagsize, int datasize):Index(index),TagSize(tagsize),DataSize(datasize) {}
  120. BlockHeader(BlockHeader& bh) {memcpy(this, &bh, sizeof(BlockHeader));}
  121. // Used to verify file integrity.
  122. int Index;
  123. // Size of tagname (including NULL) that follows this block.
  124. int TagSize;
  125. // Size of block not including header.
  126. int DataSize;
  127. // A variable length name (NULL terminated) follows this structure.
  128. // The name is then followed by the Data.
  129. // The entire length of the block is sizeof(BlockHeader) + TagSize + DataSize.
  130. };
  131. protected:
  132. ///////////////////////////////////////////////////////////////////////////////////////////
  133. /////////////////////////////// Member Data Fields ////////////////////////////////////////
  134. ///////////////////////////////////////////////////////////////////////////////////////////
  135. // This is the data at the start of the file.
  136. FileHeader Header;
  137. // Only one handle has permission to write to the end of the file if any.
  138. // This is a pointer to that handle.
  139. TagBlockHandle *CreateHandle;
  140. // To help those stupid programmers from leaving open handles when
  141. // this file is closed down.
  142. int NumOpenHandles;
  143. // Last time file was written to before we opened it.
  144. unsigned long FileTime;
  145. // Keep list of all blocks in file. This list is sorted by CRC value.
  146. // TagBlockIndex is defined in TagBlock.cpp.
  147. SList<TagBlockIndex> IndexList;
  148. protected:
  149. ///////////////////////////////////////////////////////////////////////////////////////////
  150. /////////////////////////////// Protected Member Functions ////////////////////////////////
  151. ///////////////////////////////////////////////////////////////////////////////////////////
  152. // Search for block given tag.
  153. TagBlockIndex *Find_Block(const char *tagname);
  154. // Create an index that can be used for seaching.
  155. TagBlockIndex *Create_Index(const char *tagname, int blockoffset);
  156. // Is this the handle that has creation priveledges?
  157. int Handle_Can_Write(TagBlockHandle *handle) {
  158. return(CreateHandle == handle);
  159. }
  160. // Called only by ~TagBlockHandle!
  161. void Destroy_Handle(TagBlockHandle *handle);
  162. // Stop write access - flushes data out but keeps handle available for reading.
  163. int End_Write_Access(TagBlockHandle *handle);
  164. // Save the header when it has been updated.
  165. void Save_Header() {
  166. Seek(0, SEEK_SET);
  167. Write(&Header, sizeof(Header));
  168. }
  169. void Empty_Index_List();
  170. friend class TagBlockHandle;
  171. };
  172. ///////////////////////////////////////// End of TagBlockFile /////////////////////////////////////
  173. ///////////////////////////////////////////////////////////////////////////////////////////////////
  174. ////////////////////////////////////// Start of TagBlockHandle/////////////////////////////////////
  175. // All external access to the TagBlockFile is done through handles.
  176. class TagBlockHandle
  177. {
  178. public:
  179. // Access functions.
  180. int Write(const void *buf, int nbytes);
  181. int Read(void *buf, int nbytes);
  182. int Seek(int pos, int dir = SEEK_CUR);
  183. // Stop write access - flushes data out but keeps handle available for reading.
  184. int End_Write_Access() {
  185. return (File->End_Write_Access(this));
  186. }
  187. int Tell() {
  188. return(Position);
  189. }
  190. int Get_Data_Size() {
  191. return(BlockHeader->DataSize);
  192. }
  193. // User must call TagBlockFile::New_Handle() to create a TagBlockHandle object.
  194. // User may call this delete to destry handle or
  195. // he may call TagBlockFile::Close_Tag().
  196. ~TagBlockHandle();
  197. private:
  198. // Pointer to parent file object.
  199. TagBlockFile *File;
  200. // Pointer to index for aditional information.
  201. TagBlockIndex *Index;
  202. // Keep header infomation in memory so that it can be updated.
  203. TagBlockFile::BlockHeader *BlockHeader;
  204. // Current postion we are in the file.
  205. int Position;
  206. private:
  207. // User must call TagBlockFile::New_Handle() to create a TagBlockHandle object.
  208. // The constructor is private so only TagBlockFile can create the handle.
  209. // This is so that a handle will not be created if the TagBlock
  210. // does not exist on a CREAD or if there was already a WRITE access granted.
  211. // User needs to call detete to destroy the handle.
  212. TagBlockHandle(TagBlockFile *tagfile, TagBlockIndex *tagindex, TagBlockFile::BlockHeader *blockheader);
  213. friend class TagBlockFile;
  214. // Used to prevent TagBlockFile::Destroy_Handle() from being called
  215. // except by this destructor.
  216. static int _InDestructor;
  217. int Called_By_Destructor() {
  218. return(_InDestructor);
  219. }
  220. };
  221. ////////////////////////////////////// End of TagBlockHandle///////////////////////////////////////
  222. ///////////////////////////////////////////////////////////////////////////////////////////////////
  223. #endif //TAGBLOCK_H