BitFlags.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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: BitFlags.h /////////////////////////////////////////////////////////////////////////
  24. // Author: Steven Johnson, March 2002
  25. // Desc:
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #pragma once
  28. #ifndef __BitFlags_H_
  29. #define __BitFlags_H_
  30. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  31. #include "Common/STLTypedefs.h"
  32. class INI;
  33. class Xfer;
  34. class AsciiString;
  35. //-------------------------------------------------------------------------------------------------
  36. /*
  37. BitFlags is a wrapper class that exists primarily because of a flaw in std::bitset<>.
  38. Although quite useful, it has horribly non-useful constructor, which (1) don't let
  39. us initialize stuff in useful ways, and (2) provide a default constructor that implicitly
  40. converts ints into bitsets in a "wrong" way (ie, it treats the int as a mask, not an index).
  41. So we wrap to correct this, but leave the bitset "exposed" so that we can use all the non-ctor
  42. functions on it directly (since it doesn't overload operator= to do the "wrong" thing, strangley enough)
  43. */
  44. template <size_t NUMBITS>
  45. class BitFlags
  46. {
  47. private:
  48. std::bitset<NUMBITS> m_bits;
  49. static const char* s_bitNameList[];
  50. public:
  51. /*
  52. just a little syntactic sugar so that there is no "foo = 0" compatible constructor
  53. */
  54. enum BogusInitType
  55. {
  56. kInit = 0
  57. };
  58. inline BitFlags()
  59. {
  60. }
  61. inline BitFlags(BogusInitType k, Int idx1)
  62. {
  63. m_bits.set(idx1);
  64. }
  65. inline BitFlags(BogusInitType k, Int idx1, Int idx2)
  66. {
  67. m_bits.set(idx1);
  68. m_bits.set(idx2);
  69. }
  70. inline BitFlags(BogusInitType k, Int idx1, Int idx2, Int idx3)
  71. {
  72. m_bits.set(idx1);
  73. m_bits.set(idx2);
  74. m_bits.set(idx3);
  75. }
  76. inline BitFlags(BogusInitType k, Int idx1, Int idx2, Int idx3, Int idx4)
  77. {
  78. m_bits.set(idx1);
  79. m_bits.set(idx2);
  80. m_bits.set(idx3);
  81. m_bits.set(idx4);
  82. }
  83. inline BitFlags(BogusInitType k, Int idx1, Int idx2, Int idx3, Int idx4, Int idx5)
  84. {
  85. m_bits.set(idx1);
  86. m_bits.set(idx2);
  87. m_bits.set(idx3);
  88. m_bits.set(idx4);
  89. m_bits.set(idx5);
  90. }
  91. inline BitFlags(BogusInitType k,
  92. Int idx1,
  93. Int idx2,
  94. Int idx3,
  95. Int idx4,
  96. Int idx5,
  97. Int idx6,
  98. Int idx7,
  99. Int idx8,
  100. Int idx9,
  101. Int idx10,
  102. Int idx11,
  103. Int idx12
  104. )
  105. {
  106. m_bits.set(idx1);
  107. m_bits.set(idx2);
  108. m_bits.set(idx3);
  109. m_bits.set(idx4);
  110. m_bits.set(idx5);
  111. m_bits.set(idx6);
  112. m_bits.set(idx7);
  113. m_bits.set(idx8);
  114. m_bits.set(idx9);
  115. m_bits.set(idx10);
  116. m_bits.set(idx11);
  117. m_bits.set(idx12);
  118. }
  119. inline Bool operator==(const BitFlags& that) const
  120. {
  121. return this->m_bits == that.m_bits;
  122. }
  123. inline Bool operator!=(const BitFlags& that) const
  124. {
  125. return this->m_bits != that.m_bits;
  126. }
  127. inline void set(Int i, Int val = 1)
  128. {
  129. m_bits.set(i, val);
  130. }
  131. inline Bool test(Int i) const
  132. {
  133. return m_bits.test(i);
  134. }
  135. //Tests for any bits that are set in both.
  136. inline Bool testForAny( const BitFlags& that ) const
  137. {
  138. BitFlags tmp = *this;
  139. tmp.m_bits &= that.m_bits;
  140. return tmp.m_bits.any();
  141. }
  142. //All argument bits must be set in our bits too in order to return TRUE
  143. inline Bool testForAll( const BitFlags& that ) const
  144. {
  145. DEBUG_ASSERTCRASH( that.any(), ("BitFlags::testForAll is always true if you ask about zero flags. Did you mean that?") );
  146. BitFlags tmp = *this;
  147. tmp.m_bits.flip();
  148. tmp.m_bits &= that.m_bits;
  149. return !tmp.m_bits.any();
  150. }
  151. //None of the argument bits must be set in our bits in order to return TRUE
  152. inline Bool testForNone( const BitFlags& that ) const
  153. {
  154. BitFlags tmp = *this;
  155. tmp.m_bits &= that.m_bits;
  156. return !tmp.m_bits.any();
  157. }
  158. inline Int size() const
  159. {
  160. return m_bits.size();
  161. }
  162. inline Int count() const
  163. {
  164. return m_bits.count();
  165. }
  166. inline Bool any() const
  167. {
  168. return m_bits.any();
  169. }
  170. inline void flip()
  171. {
  172. m_bits.flip();
  173. }
  174. inline void clear()
  175. {
  176. m_bits.reset();
  177. }
  178. inline Int countIntersection(const BitFlags& that) const
  179. {
  180. BitFlags tmp = *this;
  181. tmp.m_bits &= that.m_bits;
  182. return tmp.m_bits.count();
  183. }
  184. inline Int countInverseIntersection(const BitFlags& that) const
  185. {
  186. BitFlags tmp = *this;
  187. tmp.m_bits.flip();
  188. tmp.m_bits &= that.m_bits;
  189. return tmp.m_bits.count();
  190. }
  191. inline Bool anyIntersectionWith(const BitFlags& that) const
  192. {
  193. /// @todo srj -- improve me.
  194. BitFlags tmp = that;
  195. tmp.m_bits &= m_bits;
  196. return tmp.m_bits.any();
  197. }
  198. inline void clear(const BitFlags& clr)
  199. {
  200. m_bits &= ~clr.m_bits;
  201. }
  202. inline void set(const BitFlags& set)
  203. {
  204. m_bits |= set.m_bits;
  205. }
  206. inline void clearAndSet(const BitFlags& clr, const BitFlags& set)
  207. {
  208. m_bits &= ~clr.m_bits;
  209. m_bits |= set.m_bits;
  210. }
  211. inline Bool testSetAndClear(const BitFlags& mustBeSet, const BitFlags& mustBeClear) const
  212. {
  213. /// @todo srj -- improve me.
  214. BitFlags tmp = *this;
  215. tmp.m_bits &= mustBeClear.m_bits;
  216. if (tmp.m_bits.any())
  217. return false;
  218. tmp = *this;
  219. tmp.m_bits.flip();
  220. tmp.m_bits &= mustBeSet.m_bits;
  221. if (tmp.m_bits.any())
  222. return false;
  223. return true;
  224. }
  225. static const char** getBitNames()
  226. {
  227. return s_bitNameList;
  228. }
  229. static const char* getNameFromSingleBit(Int i)
  230. {
  231. return (i >= 0 && i < NUMBITS) ? s_bitNameList[i] : NULL;
  232. }
  233. static Int getSingleBitFromName(const char* token)
  234. {
  235. Int i = 0;
  236. for(const char** name = s_bitNameList; *name; ++name, ++i )
  237. {
  238. if( stricmp( *name, token ) == 0 )
  239. {
  240. return i;
  241. }
  242. }
  243. return -1;
  244. }
  245. const char* getBitNameIfSet(Int i) const
  246. {
  247. return test(i) ? s_bitNameList[i] : NULL;
  248. }
  249. Bool setBitByName(const char* token)
  250. {
  251. Int i = getSingleBitFromName(token);
  252. if (i >= 0)
  253. {
  254. set(i);
  255. return true;
  256. }
  257. else
  258. {
  259. return false;
  260. }
  261. }
  262. void parse(INI* ini, AsciiString* str);
  263. void parseSingleBit(INI* ini, AsciiString* str);
  264. void xfer(Xfer* xfer);
  265. static void parseFromINI(INI* ini, void* /*instance*/, void *store, const void* /*userData*/); ///< Returns a BitFlag
  266. static void parseSingleBitFromINI(INI* ini, void* /*instance*/, void *store, const void* /*userData*/); ///< Returns an int, the Index of the one bit
  267. void buildDescription( AsciiString* str ) const
  268. {
  269. if ( str == NULL )
  270. return;//sanity
  271. for( Int i = 0; i < size(); ++i )
  272. {
  273. const char* bitName = getBitNameIfSet(i);
  274. if (bitName != NULL)
  275. {
  276. str->concat( bitName );
  277. str->concat( ",\n");
  278. }
  279. }
  280. }
  281. };
  282. #endif // __BitFlags_H_