BitFlagsIO.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. ** Command & Conquer Generals Zero Hour(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. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: BitFlagsIO.h /////////////////////////////////////////////////////////////////////////////
  24. // Author: Steven Johnson, March 2002
  25. // Desc:
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #pragma once
  28. #ifndef __BitFlagsIO_H_
  29. #define __BitFlagsIO_H_
  30. #include "Common/BitFlags.h"
  31. #include "Common/INI.h"
  32. #include "Common/Xfer.h"
  33. //-------------------------------------------------------------------------------------------------
  34. /*
  35. template <size_t NUMBITS>
  36. void BitFlags<NUMBITS>::buildDescription( AsciiString* str ) const
  37. {
  38. if ( str == NULL )
  39. return;//sanity
  40. for( Int i = 0; i < size(); ++i )
  41. {
  42. const char* bitName = getBitNameIfSet(i);
  43. if (bitName != NULL)
  44. {
  45. str->concat( bitName );
  46. str->concat( ",\n");
  47. }
  48. }
  49. }
  50. */
  51. //-------------------------------------------------------------------------------------------------
  52. template <size_t NUMBITS>
  53. void BitFlags<NUMBITS>::parse(INI* ini, AsciiString* str)
  54. {
  55. // m_bits.reset();
  56. if (str)
  57. str->clear();
  58. Bool foundNormal = false;
  59. Bool foundAddOrSub = false;
  60. // loop through all tokens
  61. for (const char *token = ini->getNextTokenOrNull(); token != NULL; token = ini->getNextTokenOrNull())
  62. {
  63. if (str)
  64. {
  65. if (str->isNotEmpty())
  66. str->concat(" ");
  67. str->concat(token);
  68. }
  69. if (stricmp(token, "NONE") == 0)
  70. {
  71. if (foundNormal || foundAddOrSub)
  72. {
  73. DEBUG_CRASH(("you may not mix normal and +- ops in bitstring lists"));
  74. throw INI_INVALID_NAME_LIST;
  75. }
  76. clear();
  77. break;
  78. }
  79. if (token[0] == '+')
  80. {
  81. if (foundNormal)
  82. {
  83. DEBUG_CRASH(("you may not mix normal and +- ops in bitstring lists"));
  84. throw INI_INVALID_NAME_LIST;
  85. }
  86. Int bitIndex = INI::scanIndexList(token+1, s_bitNameList); // this throws if the token is not found
  87. set(bitIndex, 1);
  88. foundAddOrSub = true;
  89. }
  90. else if (token[0] == '-')
  91. {
  92. if (foundNormal)
  93. {
  94. DEBUG_CRASH(("you may not mix normal and +- ops in bitstring lists"));
  95. throw INI_INVALID_NAME_LIST;
  96. }
  97. Int bitIndex = INI::scanIndexList(token+1, s_bitNameList); // this throws if the token is not found
  98. set(bitIndex, 0);
  99. foundAddOrSub = true;
  100. }
  101. else
  102. {
  103. if (foundAddOrSub)
  104. {
  105. DEBUG_CRASH(("you may not mix normal and +- ops in bitstring lists"));
  106. throw INI_INVALID_NAME_LIST;
  107. }
  108. if (!foundNormal)
  109. clear();
  110. Int bitIndex = INI::scanIndexList(token, s_bitNameList); // this throws if the token is not found
  111. set(bitIndex, 1);
  112. foundNormal = true;
  113. }
  114. }
  115. }
  116. //-------------------------------------------------------------------------------------------------
  117. //-------------------------------------------------------------------------------------------------
  118. template <size_t NUMBITS>
  119. /*static*/ void BitFlags<NUMBITS>::parseFromINI(INI* ini, void* /*instance*/, void *store, const void* /*userData*/)
  120. {
  121. ((BitFlags*)store)->parse(ini, NULL);
  122. }
  123. //-------------------------------------------------------------------------------------------------
  124. //-------------------------------------------------------------------------------------------------
  125. template <size_t NUMBITS>
  126. /*static*/ void BitFlags<NUMBITS>::parseSingleBitFromINI(INI* ini, void* /*instance*/, void *store, const void* /*userData*/)
  127. {
  128. const char *token = ini->getNextToken();
  129. Int bitIndex = INI::scanIndexList(token, s_bitNameList); // this throws if the token is not found
  130. Int *storeAsInt = (Int*)store;
  131. *storeAsInt = bitIndex;
  132. }
  133. //-------------------------------------------------------------------------------------------------
  134. /** Xfer method
  135. * Version Info:
  136. * 1: Initial version */
  137. //-------------------------------------------------------------------------------------------------
  138. template <size_t NUMBITS>
  139. void BitFlags<NUMBITS>::xfer(Xfer* xfer)
  140. {
  141. // this deserves a version number
  142. XferVersion currentVersion = 1;
  143. XferVersion version = currentVersion;
  144. xfer->xferVersion( &version, currentVersion );
  145. if( xfer->getXferMode() == XFER_SAVE )
  146. {
  147. // save how many entries are to follow
  148. Int c = count();
  149. xfer->xferInt( &c );
  150. // save each of the string data
  151. for( Int i = 0; i < size(); ++i )
  152. {
  153. const char* bitName = getBitNameIfSet(i);
  154. // ignore if this kindof is not set in our mask data
  155. if (bitName == NULL)
  156. continue;
  157. // this bit is set, write the string value
  158. AsciiString bitNameA = bitName;
  159. xfer->xferAsciiString( &bitNameA );
  160. } // end for i
  161. } // end if, save
  162. else if( xfer->getXferMode() == XFER_LOAD )
  163. {
  164. // clear the kind of mask data
  165. clear();
  166. // read how many entries follow
  167. Int c;
  168. xfer->xferInt( &c );
  169. // read each of the string entries
  170. AsciiString string;
  171. for( Int i = 0; i < c; ++i )
  172. {
  173. // read ascii string
  174. xfer->xferAsciiString( &string );
  175. // set in our mask type data
  176. Bool valid = setBitByName( string.str() );
  177. if (!valid)
  178. {
  179. DEBUG_CRASH(("invalid bit name %s",string.str()));
  180. throw XFER_READ_ERROR;
  181. }
  182. } // end for, i
  183. } // end else if, load
  184. else if( xfer->getXferMode() == XFER_CRC )
  185. {
  186. // just call the xfer implementation on the data values
  187. xfer->xferUser( this, sizeof( this ) );
  188. } // end else if, crc
  189. else
  190. {
  191. DEBUG_CRASH(( "BitFlagsXfer - Unknown xfer mode '%d'\n", xfer->getXferMode() ));
  192. throw XFER_MODE_UNKNOWN;
  193. } // end else
  194. } // end xfer
  195. #endif