Dict.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  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: Dict.h
  24. //-----------------------------------------------------------------------------
  25. //
  26. // Westwood Studios Pacific.
  27. //
  28. // Confidential Information
  29. // Copyright (C) 2001 - All Rights Reserved
  30. //
  31. //-----------------------------------------------------------------------------
  32. //
  33. // Project: RTS3
  34. //
  35. // File name: Dict.h
  36. //
  37. // Created: Steven Johnson, November 2001
  38. //
  39. // Desc: General-purpose dictionary class
  40. //
  41. //-----------------------------------------------------------------------------
  42. ///////////////////////////////////////////////////////////////////////////////
  43. #pragma once
  44. #ifndef Dict_H
  45. #define Dict_H
  46. #include "Common/Errors.h"
  47. #include "Common/NameKeyGenerator.h"
  48. // -----------------------------------------------------
  49. /**
  50. Dict provides a general utility class for maintaining
  51. a sorted key-value pair list. Keys are currently required
  52. to be of type NameKeyType, and data may be Bool, int, real,
  53. or string.
  54. Current implementation keeps the pairs sorted by key, and
  55. does a binary search for lookups; this might change in the future,
  56. depending on usage and performance (e.g., to a hashtable). So
  57. don't rely on the quirks of this implementation.
  58. */
  59. class Dict
  60. {
  61. public:
  62. enum
  63. {
  64. MAX_LEN = 32767 ///< max total len of any Dict, in Pairs
  65. };
  66. enum DataType
  67. {
  68. DICT_NONE = -1, // this is returned by getType and getNthType to indicate "invalid key/index"
  69. DICT_BOOL = 0, // note, we rely on the fact that this constant is zero in the code. so don't change it.
  70. DICT_INT,
  71. DICT_REAL,
  72. DICT_ASCIISTRING,
  73. DICT_UNICODESTRING
  74. };
  75. /**
  76. Default constructor -- construct a new, empty Dict.
  77. */
  78. Dict(Int numPairsToPreAllocate = 0);
  79. /**
  80. Copy constructor -- make this Dict identical to the
  81. other Dict. (This is actually quite efficient, because
  82. they will simply share the same data and increment the
  83. refcount.)
  84. */
  85. Dict(const Dict& src);
  86. /**
  87. Destructor. Not too exciting... clean up the works and such.
  88. */
  89. ~Dict();
  90. /**
  91. */
  92. Dict& operator=(const Dict& src);
  93. /**
  94. remove all pairs.
  95. */
  96. void clear();
  97. /**
  98. return the number of key-value pairs in the dict.
  99. */
  100. Int getPairCount() const;
  101. /**
  102. Return the key for the nth pair (0-based index).
  103. return NAMEKEY_INVALID if n is out of range.
  104. */
  105. NameKeyType getNthKey(Int n) const;
  106. /**
  107. Return the datatype for the pair with the given key.
  108. return DICT_NONE if no pair with the key exists.
  109. */
  110. DataType getType(NameKeyType key) const;
  111. /**
  112. Return there is a pair with the given key and datatype, return true.
  113. */
  114. inline Bool known(NameKeyType key, DataType d) const
  115. {
  116. return getType(key) == d;
  117. }
  118. /**
  119. Return the datatype for the nth pair (0-based index).
  120. return DICT_NONE if n is out of range.
  121. */
  122. DataType getNthType(Int n) const;
  123. /**
  124. return the value for the pair with the given key.
  125. if there is no pair with the given key, or the value is
  126. not of the correct type, 0 is returned.
  127. */
  128. Bool getBool(NameKeyType key, Bool* exists = NULL) const;
  129. /**
  130. return the value for the pair with the given key.
  131. if there is no pair with the given key, or the value is
  132. not of the correct type, 0 is returned.
  133. */
  134. Int getInt(NameKeyType key, Bool* exists = NULL) const;
  135. /**
  136. return the value for the pair with the given key.
  137. if there is no pair with the given key, or the value is
  138. not of the correct type, 0 is returned.
  139. */
  140. Real getReal(NameKeyType key, Bool* exists = NULL) const;
  141. /**
  142. return the value for the pair with the given key.
  143. if there is no pair with the given key, or the value is
  144. not of the correct type, "" is returned.
  145. */
  146. AsciiString getAsciiString(NameKeyType key, Bool* exists = NULL) const;
  147. /**
  148. return the value for the pair with the given key.
  149. if there is no pair with the given key, or the value is
  150. not of the correct type, "" is returned.
  151. */
  152. UnicodeString getUnicodeString(NameKeyType key, Bool* exists = NULL) const;
  153. /**
  154. return the value for the pair with the given index.
  155. if the index is out of range, or the value is
  156. not of the correct type, 0 is returned.
  157. */
  158. Bool getNthBool(Int n) const;
  159. /**
  160. return the value for the pair with the given index.
  161. if the index is out of range, or the value is
  162. not of the correct type, 0 is returned.
  163. */
  164. Int getNthInt(Int n) const;
  165. /**
  166. return the value for the pair with the given index.
  167. if the index is out of range, or the value is
  168. not of the correct type, 0 is returned.
  169. */
  170. Real getNthReal(Int n) const;
  171. /**
  172. return the value for the pair with the given index.
  173. if the index is out of range, or the value is
  174. not of the correct type, "" is returned.
  175. */
  176. AsciiString getNthAsciiString(Int n) const;
  177. /**
  178. return the value for the pair with the given index.
  179. if the index is out of range, or the value is
  180. not of the correct type, "" is returned.
  181. */
  182. UnicodeString getNthUnicodeString(Int n) const;
  183. /**
  184. set the value for the pair with the given key.
  185. if no such pair exists, it is created.
  186. if such a pair exists, it is replaced.
  187. note that when replacing a pair, the new and old
  188. data types need not match.
  189. */
  190. void setBool(NameKeyType key, Bool value);
  191. /**
  192. set the value for the pair with the given key.
  193. if no such pair exists, it is created.
  194. if such a pair exists, it is replaced.
  195. note that when replacing a pair, the new and old
  196. data types need not match.
  197. */
  198. void setInt(NameKeyType key, Int value);
  199. /**
  200. set the value for the pair with the given key.
  201. if no such pair exists, it is created.
  202. if such a pair exists, it is replaced.
  203. note that when replacing a pair, the new and old
  204. data types need not match.
  205. */
  206. void setReal(NameKeyType key, Real value);
  207. /**
  208. set the value for the pair with the given key.
  209. if no such pair exists, it is created.
  210. if such a pair exists, it is replaced.
  211. note that when replacing a pair, the new and old
  212. data types need not match.
  213. */
  214. void setAsciiString(NameKeyType key, const AsciiString& value);
  215. /**
  216. set the value for the pair with the given key.
  217. if no such pair exists, it is created.
  218. if such a pair exists, it is replaced.
  219. note that when replacing a pair, the new and old
  220. data types need not match.
  221. */
  222. void setUnicodeString(NameKeyType key, const UnicodeString& value);
  223. /**
  224. remove the pair with the given key. if such a pair existed, return true.
  225. if no such pair existed, return false.
  226. */
  227. Bool remove(NameKeyType key);
  228. /**
  229. copy the pair with the given key from 'that', replacing any such pair in 'this'.
  230. if no such pair exists in 'that', any pair with that key will be removed from 'this'.
  231. */
  232. void copyPairFrom(const Dict& that, NameKeyType key);
  233. private:
  234. struct DictPair;
  235. struct DictPairData;
  236. DictPairData* m_data; // pointer to ref counted Pair data
  237. void sortPairs();
  238. Dict::DictPair *setPrep(NameKeyType key, Dict::DataType type);
  239. DictPair* findPairByKey(NameKeyType key) const;
  240. void releaseData();
  241. DictPair *ensureUnique(int numPairsNeeded, Bool preserveData, DictPair *pairToTranslate);
  242. enum DictPairKeyType
  243. {
  244. DICTPAIRKEY_ILLEGAL = 0
  245. };
  246. // danger... this is Plain Old Data and allocated in a skanky way;
  247. // and thus the ctor/dtor for DictPair will never be called. so don't
  248. // bother writing one.
  249. struct DictPair
  250. {
  251. private:
  252. DictPairKeyType m_key;
  253. void* m_value;
  254. inline static DictPairKeyType createKey(NameKeyType keyVal, DataType nt)
  255. {
  256. return (DictPairKeyType)((((UnsignedInt)(keyVal)) << 8) | ((UnsignedInt)nt));
  257. }
  258. inline static DataType getTypeFromKey(DictPairKeyType nk)
  259. {
  260. return (DataType)(((UnsignedInt)nk) & 0xff);
  261. }
  262. inline static NameKeyType getNameFromKey(DictPairKeyType nk)
  263. {
  264. return (NameKeyType)(((UnsignedInt)nk) >> 8);
  265. }
  266. public:
  267. void clear();
  268. void copyFrom(DictPair* that);
  269. void setNameAndType(NameKeyType key, DataType type);
  270. inline DataType getType() const { return getTypeFromKey(m_key); }
  271. inline NameKeyType getName() const { return getNameFromKey(m_key); }
  272. inline Bool* asBool() { return (Bool*)&m_value; }
  273. inline Int* asInt() { return (Int*)&m_value; }
  274. inline Real* asReal() { return (Real*)&m_value; }
  275. inline AsciiString* asAsciiString() { return (AsciiString*)&m_value; }
  276. inline UnicodeString* asUnicodeString() { return (UnicodeString*)&m_value; }
  277. };
  278. struct DictPairData
  279. {
  280. unsigned short m_refCount; // reference count
  281. unsigned short m_numPairsAllocated; // length of data allocated
  282. unsigned short m_numPairsUsed; // length of data allocated
  283. //DictPair m_pairs[];
  284. inline DictPair* peek() { return (DictPair*)(this+1); }
  285. };
  286. #ifdef _DEBUG
  287. void validate() const;
  288. #else
  289. inline void validate() const { }
  290. #endif
  291. };
  292. // -----------------------------------------------------
  293. inline Dict::Dict(const Dict& src) : m_data(src.m_data)
  294. {
  295. if (m_data)
  296. ++m_data->m_refCount;
  297. }
  298. // -----------------------------------------------------
  299. inline Dict::~Dict()
  300. {
  301. releaseData();
  302. }
  303. // -----------------------------------------------------
  304. inline Int Dict::getPairCount() const
  305. {
  306. return m_data ? m_data->m_numPairsUsed : 0;
  307. }
  308. // -----------------------------------------------------
  309. inline NameKeyType Dict::getNthKey(Int n) const
  310. {
  311. if (!m_data || n < 0 || n >= m_data->m_numPairsUsed)
  312. return NAMEKEY_INVALID;
  313. return m_data->peek()[n].getName();
  314. }
  315. // -----------------------------------------------------
  316. inline Dict::DataType Dict::getNthType(Int n) const
  317. {
  318. if (!m_data || n < 0 || n >= m_data->m_numPairsUsed)
  319. return DICT_NONE;
  320. return m_data->peek()[n].getType();
  321. }
  322. #endif // Dict_H