LookupTable.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. #ifndef __LookupTable_h__
  2. #define __LookupTable_h__
  3. /////////////////////////////////////////////////////////////////////////////
  4. // LookupTable.h | Declaration of a simple lookup table.
  5. #pragma warning(disable: 4786)
  6. /////////////////////////////////////////////////////////////////////////////
  7. /////////////////////////////////////////////////////////////////////////////
  8. // Declares a template structure that holds a pair of values of types
  9. // /key/ and /Value/. This is used by the TCLookupTable macros.
  10. //
  11. // Template Parameters:
  12. // Key - The type of the m_key public data member.
  13. // Value - The type of the m_value public data member;
  14. //
  15. // See Also: TCLookupTable Macros, TCLookupTable_DECLARE
  16. template <class Key, class Value, class KeyRef = Key const &>
  17. struct TCLookupTablePair
  18. {
  19. typedef Key KeyT; // {secret}
  20. typedef Value ValueT; // {secret}
  21. typedef KeyRef KeyRefT; // {secret}
  22. KeyT m_key; // {secret}
  23. ValueT m_value; // {secret}
  24. };
  25. /////////////////////////////////////////////////////////////////////////////
  26. // Iterates through the entries of the specified lookup table until either
  27. // the specified /key/ is found or the number of table entries specified by
  28. // /nSize/ have been searched.
  29. //
  30. // This is used by the TCLookupTable_FIND macro and probably has limited use
  31. // outside of that macro.
  32. //
  33. // Template Parameters:
  34. // Key - The type of the table's keys.
  35. // Value - The type of the table's associated values.
  36. // Parameters:
  37. // pTable - The address of the first entry in the table.
  38. // nSize - The number of table entries in the table.
  39. // key - The key to be located in the table.
  40. // value - A reference to where the located key's associated value will be
  41. // copied. If the key is not found, this parameter is not used.
  42. //
  43. // Return Value: true if the specified key was located in the specified
  44. // table, otherwise false;
  45. //
  46. // See Also: TCLookupTable Macros, TCLookupTable_FIND
  47. template <class Key, class Value, class KeyRef>
  48. bool TCLookupTable_Find(TCLookupTablePair<Key, Value, KeyRef>* ptable,
  49. UINT nSize, KeyRef key, Value& value)
  50. {
  51. for (UINT i = 0; i < nSize; i++)
  52. {
  53. if (key == ptable[i].m_key)
  54. {
  55. value = ptable[i].m_value;
  56. return true;
  57. }
  58. }
  59. return false;
  60. }
  61. #ifdef _DOCJET_ONLY
  62. ///////////////////////////////////////////////////////////////////////////
  63. // Macro Group: TCLookupTable Macros
  64. //
  65. // There is often the need during development to define lookup tables for a
  66. // variety of uses. Regardless of the use, this involves mapping a
  67. // /key/ to one or more /values/. For dynamic lookup tables, those that
  68. // will be built and modified during run-time, an obvious choice might be
  69. // the STL std::map class. However, many lookup tables are static in nature
  70. // and, as such, can be defined at compile time and do not change during
  71. // the course of the program. The TCLookupTable macros provide a reusable
  72. // mechanism to assist in the declaration and initialization of such static
  73. // lookup tables.
  74. //
  75. // Note: These macros are not designed to be used to declare static tables
  76. // in template classes. This is mostly due to limitations of the
  77. // C++ preprocessor which, for example, make it difficult (or impossible)
  78. // to specify a template class name with multiple template arguments as a
  79. // macro parameter; the comma's get in the way. However, for efficiency
  80. // reasons, using static tables in a template class is *not* recommended,
  81. // anyway.
  82. // It could be inefficient since multiple template instances would each
  83. // have their own copy of the static data. If you need a static table in a
  84. // template class, derive the template class from a non-template base class
  85. // that declares (and initializes) the table. Be sure to make the tables
  86. // *public* or *protected* in the non-template base class so that the
  87. // derived template class has access to them.
  88. //
  89. // To declare a static lookup table in your class, add the
  90. // TCLookupTable_DECLARE macro inside your class declaration:
  91. //
  92. // class CMyClass
  93. // {
  94. // // ...(Other members)...
  95. // …
  96. // // Data Members
  97. // protected:
  98. // TCLookupTable_DECLARE(fruits, int, LPCTSTR)
  99. // };
  100. //
  101. // The above example declares a static lookup table named "fruits" as a
  102. // protected data member of CMyClass. The table will map integers to
  103. // strings. For the sake of the example, forget that all localizable
  104. // strings should be put into String Table resources.
  105. //
  106. // A class can declare as many tables as needed. If the CMyClass also
  107. // needed a table of vegetables, it could simply specify the macro again,
  108. // with a different table name:
  109. //
  110. // class CMyClass
  111. // {
  112. // // ...(Other members)...
  113. // …
  114. // // Data Members
  115. // protected:
  116. // TCLookupTable_DECLARE(fruits, int, LPCTSTR)
  117. // TCLookupTable_DECLARE(vegetables, int, LPCTSTR)
  118. // };
  119. //
  120. // To initialize each table, use the TCLookupTable_ENTRY macros, enclosed
  121. // within the TCLookupTable_BEGIN and TCLookupTable_END macros. Keep in
  122. // mind that the table is a static data member of the class. So the best
  123. // place to initialize the static data members is in your class
  124. // implementation (CPP) file:
  125. //
  126. // // (In MyClass.cpp)
  127. // // Static Initialization
  128. // TCLookupTable_BEGIN(CMyClass, fruits)
  129. // TCLookupTable_ENTRY(10, TEXT("Apple"))
  130. // TCLookupTable_ENTRY(20, TEXT("Banana"))
  131. // TCLookupTable_ENTRY(30, TEXT("Orange"))
  132. // TCLookupTable_END()
  133. //
  134. // The above example only shows the TCLookupTable_ENTRY macro, but several
  135. // other macros are provided to assist in the declaration of other common
  136. // scenarios, such as when the associated value type is a structure.
  137. //
  138. // Now that your lookup table is initialized, the TCLookupTable_FIND macro
  139. // allows a key and its associated value to easily be found in the table:
  140. //
  141. // LPCTSTR CMyClass::FruitToString(int idFruit) const
  142. // {
  143. // // Lookup the specified fruit ID
  144. // LPCTSTR pszName;
  145. // bool bFound = TCLookupTable_FIND(fruit, idFruit, pszName);
  146. // return bFound ? pszName : NULL;
  147. // }
  148. //
  149. // While the above example demonstrates the most common use for a lookup
  150. // table, it is sometimes useful to manually iterate through the table
  151. // entries. To assist with this, the TCLookupTable_SIZE macro is provided.
  152. // As its name implies, it provides the number of entries in the table. The
  153. // table consists of a regular array of TCLookupTablePair structures. Since
  154. // this structure is a template, the TCLookupTable_DECLARE macro declares
  155. // a type definition consisting of the table name suffixed with _ValueType.
  156. // In the following example, the /entry/ variable is a reference of type
  157. // /fruit_ValueType/, which is the type definition declared by the
  158. // TCLookupTable_DECLARE macro:
  159. //
  160. // void CMyClass::DumpFruitTable() const
  161. // {
  162. // for (int i = 0; i < TCLookupTable_SIZE(fruit); ++i)
  163. // {
  164. // fruit_ValueType& entry = fruit[i];
  165. // _TRACE2("Fruit ID %d = %s\n", entry.m_key, entry.m_value);
  166. // }
  167. // }
  168. //
  169. // See Also: TCLookupTablePair, TCLookupTable_DECLARE,
  170. // TCLookupTable_DECLARE, TCLookupTable_BEGIN, TCLookupTable_END,
  171. // TCLookupTable_ENTRY Macros, TCLookupTable_SIZE, TCLookupTable_FIND,
  172. // TCLookupTable_Find
  173. #define TCLookupTable
  174. #endif // _DOCJET_ONLY
  175. /////////////////////////////////////////////////////////////////////////////
  176. // Declares a static lookup table as a static member variable. Also declares
  177. // a type definition for the entries of the table by suffixing the
  178. // /table/ parameter with _ValueType.
  179. //
  180. // Use this macro within a class declaration. More than one table can be
  181. // declared in a class by specifying a different /table/ name in each macro
  182. // statement.
  183. //
  184. // Parameters:
  185. // table - The table name, which doubles as the name of the static member
  186. // variable.
  187. // Key - The type of the table's keys.
  188. // Value - The type of the table's associated values.
  189. //
  190. // See Also: TCLookupTable Macros, TCLookupTable_BEGIN, TCLookupTablePair
  191. #define TCLookupTable_DECLARE(table, Key, Value) \
  192. typedef TCLookupTablePair<Key, Value> table##_ValueType; \
  193. static table##_ValueType table [];
  194. #define TCLookupTable_DECLARE_REF(table, Key, Value, KeyRef) \
  195. typedef TCLookupTablePair<Key, Value, KeyRef> table##_ValueType; \
  196. static table##_ValueType table [];
  197. /////////////////////////////////////////////////////////////////////////////
  198. // Begins the initialization scope of a static lookup table. This scope
  199. // should contain TCLookupTable_ENTRY macros and should end with the
  200. // TCLookupTable_END macro.
  201. //
  202. // Since this initializes a static member variable of the specified class, it
  203. // needs to be specified *outside* of the class declaration and positioned so
  204. // that it is included exactly *once* by the linker. The best place to
  205. // initialize the static data members is in the class implementation (CPP)
  206. // file.
  207. //
  208. // Parameters:
  209. // theClass - the name of the class which declares the static lookup table.
  210. // table - the name of the table in /theClass/.
  211. //
  212. // See Also: TCLookupTable Macros, TCLookupTable_ENTRY Macros,
  213. // TCLookupTable_END
  214. #define TCLookupTable_BEGIN(theClass, table) \
  215. theClass::table##_ValueType theClass::table [] = {
  216. /////////////////////////////////////////////////////////////////////////////
  217. // {alias: TCLookupTable_ENTRY2, TCLookupTable_ENTRY3, TCLookupTable_ENTRY4}
  218. // {alias: TCLookupTable_ENTRY_PREFIX, TCLookupTable_ENTRY_SUFFIX}
  219. // Initializes an entry in a static lookup table. These macros should only
  220. // be used within the initialization scope of a static lookup table. This
  221. // scope should begin with the TCLookupTable_BEGIN macro and should end with
  222. // the TCLookupTable_END macro.
  223. //
  224. // TCLookupTable_ENTRY is the simplest of these macros, taking just a key
  225. // and a value with which to initialize the table entry.
  226. //
  227. // TCLookupTable_ENTRY2 through TCLookupTable_ENTRY4 require the key and from
  228. // 2 to 4 value parameters, respectively. The multiple value parameters are
  229. // used to initialize the members of a structure when a structure is used as
  230. // the table's value type.
  231. //
  232. // TCLookupTable_ENTRY_PREFIX and TCLookupTable_ENTRY_SUFFIX are used when
  233. // the key and/or value are symbolic and the symbols contain some element of
  234. // identical text. For example, if a lookup table was being used to map error
  235. // code identifiers to string table identifiers, the following sets of
  236. // entries would be equivalent:
  237. //
  238. // This way is tedious and the repetition may introduce typing errors:
  239. //
  240. // TCLookupTable_ENTRY(E_FILENOTFOUND, IDS_E_FILENOTFOUND)
  241. // TCLookupTable_ENTRY(E_INPUTIS2UGLY, IDS_E_INPUTIS2UGLY)
  242. //
  243. // This way results in the exact same table initialization:
  244. //
  245. // TCLookupTable_ENTRY_PREFIX(E_FILENOTFOUND, IDS_)
  246. // TCLookupTable_ENTRY_PREFIX(E_INPUTIS2UGLY, IDS_)
  247. //
  248. // TODO: It may also be useful to provide a macro to "stringize" the key
  249. // symbol to derive the value:
  250. //
  251. // #define TCLookupTable_ENTRY_STRING(key) \
  252. // TCLookupTable_Entry(key, TEXT(#key))
  253. //
  254. // Parameters:
  255. // key - The value with which to initialize the table entry's key.
  256. // value - The value to which the table entry's key is associated.
  257. // value1_thru_value4 - The values with which to initialize the structure
  258. // associated with the table entry's key.
  259. // prefix - Used to create a value name based on the key parameter prefixed
  260. // with the specified parameter.
  261. // suffix - Used to create a value name based on the key parameter suffixed
  262. // with the specified parameter.
  263. //
  264. // Macro Group: TCLookupTable_ENTRY Macros
  265. //
  266. // Declaration:
  267. // #define TCLookupTable_ENTRY(key, value)
  268. // #define TCLookupTable_ENTRY2(key, value1, value2)
  269. // #define TCLookupTable_ENTRY3(key, value1, value2, value3)
  270. // #define TCLookupTable_ENTRY4(key, value1, value2, value3, value4)
  271. // #define TCLookupTable_ENTRY_PREFIX(key, prefix)
  272. // #define TCLookupTable_ENTRY_SUFFIX(key, suffix)
  273. //
  274. // See Also: TCLookupTable Macros, TCLookupTable_BEGIN, TCLookupTable_END
  275. #define TCLookupTable_ENTRY(key, value) \
  276. { key, value },
  277. /////////////////////////////////////////////////////////////////////////////
  278. // {partof:TCLookupTable_ENTRY}
  279. #define TCLookupTable_ENTRY2(key, value1, value2) \
  280. { key, {value1, value2} },
  281. /////////////////////////////////////////////////////////////////////////////
  282. // {partof:TCLookupTable_ENTRY}
  283. #define TCLookupTable_ENTRY3(key, value1, value2, value3) \
  284. { key, {value1, value2, value3} },
  285. /////////////////////////////////////////////////////////////////////////////
  286. // {partof:TCLookupTable_ENTRY}
  287. #define TCLookupTable_ENTRY4(key, value1, value2, value3, value4) \
  288. { key, {value1, value2, value3, value4} },
  289. /////////////////////////////////////////////////////////////////////////////
  290. // {partof:TCLookupTable_ENTRY}
  291. #define TCLookupTable_ENTRY_PREFIX(key, prefix) \
  292. TCLookupTable_ENTRY(key, prefix##key)
  293. /////////////////////////////////////////////////////////////////////////////
  294. // {partof:TCLookupTable_ENTRY}
  295. #define TCLookupTable_ENTRY_SUFFIX(key, suffix) \
  296. TCLookupTable_ENTRY(key, key##suffix)
  297. /////////////////////////////////////////////////////////////////////////////
  298. // Ends the initialization scope of a static lookup table. This scope should
  299. // begin with the TCLookupTable_BEGIN macro and should contain
  300. // TCLookupTable_ENTRY macros.
  301. //
  302. // See Also: TCLookupTable Macros, TCLookupTable_BEGIN, TCLookupTable_ENTRY
  303. // Macros
  304. #define TCLookupTable_END() };
  305. /////////////////////////////////////////////////////////////////////////////
  306. // Computes the number of entries in a static lookup table. Since the size of
  307. // the table is known at compile time, this macro will compile out to a
  308. // constant value.
  309. //
  310. // Parameters:
  311. // table - The name of the table.
  312. //
  313. // Return Value: The number of elements in the table.
  314. //
  315. // See Also: TCLookupTable Macros
  316. #define TCLookupTable_SIZE(table) (sizeof(table) / sizeof(table[0]))
  317. /////////////////////////////////////////////////////////////////////////////
  318. // Iterates through the entries of the specified lookup table until either
  319. // the specified /key/ is found or the end of the table is reached.
  320. //
  321. // Parameters:
  322. // table - The name of the table.
  323. // key - The key to be located in the table.
  324. // value - A reference to where the located key's associated value will be
  325. // copied. If the key is not found, this parameter is not used.
  326. //
  327. // Return Value: true if the specified key was located in the specified
  328. // table, otherwise false;
  329. //
  330. // See Also: TCLookupTable Macros, TCLookupTable_Find
  331. #define TCLookupTable_FIND(table, key, value) \
  332. TCLookupTable_Find<table##_ValueType::KeyT, \
  333. table##_ValueType::ValueT, table##_ValueType::KeyRefT>(table, \
  334. TCLookupTable_SIZE(table), key, value)
  335. /////////////////////////////////////////////////////////////////////////////
  336. #endif // !__LookupTable_h__