BitFlagsIO.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. ** Command & Conquer Generals(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. /** Xfer method
  125. * Version Info:
  126. * 1: Initial version */
  127. //-------------------------------------------------------------------------------------------------
  128. template <size_t NUMBITS>
  129. void BitFlags<NUMBITS>::xfer(Xfer* xfer)
  130. {
  131. // this deserves a version number
  132. XferVersion currentVersion = 1;
  133. XferVersion version = currentVersion;
  134. xfer->xferVersion( &version, currentVersion );
  135. if( xfer->getXferMode() == XFER_SAVE )
  136. {
  137. // save how many entries are to follow
  138. Int c = count();
  139. xfer->xferInt( &c );
  140. // save each of the string data
  141. for( Int i = 0; i < size(); ++i )
  142. {
  143. const char* bitName = getBitNameIfSet(i);
  144. // ignore if this kindof is not set in our mask data
  145. if (bitName == NULL)
  146. continue;
  147. // this bit is set, write the string value
  148. AsciiString bitNameA = bitName;
  149. xfer->xferAsciiString( &bitNameA );
  150. } // end for i
  151. } // end if, save
  152. else if( xfer->getXferMode() == XFER_LOAD )
  153. {
  154. // clear the kind of mask data
  155. clear();
  156. // read how many entries follow
  157. Int c;
  158. xfer->xferInt( &c );
  159. // read each of the string entries
  160. AsciiString string;
  161. for( Int i = 0; i < c; ++i )
  162. {
  163. // read ascii string
  164. xfer->xferAsciiString( &string );
  165. // set in our mask type data
  166. Bool valid = setBitByName( string.str() );
  167. if (!valid)
  168. {
  169. DEBUG_CRASH(("invalid bit name %s",string.str()));
  170. throw XFER_READ_ERROR;
  171. }
  172. } // end for, i
  173. } // end else if, load
  174. else if( xfer->getXferMode() == XFER_CRC )
  175. {
  176. // just call the xfer implementation on the data values
  177. xfer->xferUser( this, sizeof( this ) );
  178. } // end else if, crc
  179. else
  180. {
  181. DEBUG_CRASH(( "BitFlagsXfer - Unknown xfer mode '%d'\n", xfer->getXferMode() ));
  182. throw XFER_MODE_UNKNOWN;
  183. } // end else
  184. } // end xfer
  185. #endif