123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- #ifndef __LookupTable_h__
- #define __LookupTable_h__
- /////////////////////////////////////////////////////////////////////////////
- // LookupTable.h | Declaration of a simple lookup table.
- #pragma warning(disable: 4786)
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- // Declares a template structure that holds a pair of values of types
- // /key/ and /Value/. This is used by the TCLookupTable macros.
- //
- // Template Parameters:
- // Key - The type of the m_key public data member.
- // Value - The type of the m_value public data member;
- //
- // See Also: TCLookupTable Macros, TCLookupTable_DECLARE
- template <class Key, class Value, class KeyRef = Key const &>
- struct TCLookupTablePair
- {
- typedef Key KeyT; // {secret}
- typedef Value ValueT; // {secret}
- typedef KeyRef KeyRefT; // {secret}
- KeyT m_key; // {secret}
- ValueT m_value; // {secret}
- };
- /////////////////////////////////////////////////////////////////////////////
- // Iterates through the entries of the specified lookup table until either
- // the specified /key/ is found or the number of table entries specified by
- // /nSize/ have been searched.
- //
- // This is used by the TCLookupTable_FIND macro and probably has limited use
- // outside of that macro.
- //
- // Template Parameters:
- // Key - The type of the table's keys.
- // Value - The type of the table's associated values.
- // Parameters:
- // pTable - The address of the first entry in the table.
- // nSize - The number of table entries in the table.
- // key - The key to be located in the table.
- // value - A reference to where the located key's associated value will be
- // copied. If the key is not found, this parameter is not used.
- //
- // Return Value: true if the specified key was located in the specified
- // table, otherwise false;
- //
- // See Also: TCLookupTable Macros, TCLookupTable_FIND
- template <class Key, class Value, class KeyRef>
- bool TCLookupTable_Find(TCLookupTablePair<Key, Value, KeyRef>* ptable,
- UINT nSize, KeyRef key, Value& value)
- {
- for (UINT i = 0; i < nSize; i++)
- {
- if (key == ptable[i].m_key)
- {
- value = ptable[i].m_value;
- return true;
- }
- }
- return false;
- }
- #ifdef _DOCJET_ONLY
- ///////////////////////////////////////////////////////////////////////////
- // Macro Group: TCLookupTable Macros
- //
- // There is often the need during development to define lookup tables for a
- // variety of uses. Regardless of the use, this involves mapping a
- // /key/ to one or more /values/. For dynamic lookup tables, those that
- // will be built and modified during run-time, an obvious choice might be
- // the STL std::map class. However, many lookup tables are static in nature
- // and, as such, can be defined at compile time and do not change during
- // the course of the program. The TCLookupTable macros provide a reusable
- // mechanism to assist in the declaration and initialization of such static
- // lookup tables.
- //
- // Note: These macros are not designed to be used to declare static tables
- // in template classes. This is mostly due to limitations of the
- // C++ preprocessor which, for example, make it difficult (or impossible)
- // to specify a template class name with multiple template arguments as a
- // macro parameter; the comma's get in the way. However, for efficiency
- // reasons, using static tables in a template class is *not* recommended,
- // anyway.
- // It could be inefficient since multiple template instances would each
- // have their own copy of the static data. If you need a static table in a
- // template class, derive the template class from a non-template base class
- // that declares (and initializes) the table. Be sure to make the tables
- // *public* or *protected* in the non-template base class so that the
- // derived template class has access to them.
- //
- // To declare a static lookup table in your class, add the
- // TCLookupTable_DECLARE macro inside your class declaration:
- //
- // class CMyClass
- // {
- // // ...(Other members)...
- // …
- // // Data Members
- // protected:
- // TCLookupTable_DECLARE(fruits, int, LPCTSTR)
- // };
- //
- // The above example declares a static lookup table named "fruits" as a
- // protected data member of CMyClass. The table will map integers to
- // strings. For the sake of the example, forget that all localizable
- // strings should be put into String Table resources.
- //
- // A class can declare as many tables as needed. If the CMyClass also
- // needed a table of vegetables, it could simply specify the macro again,
- // with a different table name:
- //
- // class CMyClass
- // {
- // // ...(Other members)...
- // …
- // // Data Members
- // protected:
- // TCLookupTable_DECLARE(fruits, int, LPCTSTR)
- // TCLookupTable_DECLARE(vegetables, int, LPCTSTR)
- // };
- //
- // To initialize each table, use the TCLookupTable_ENTRY macros, enclosed
- // within the TCLookupTable_BEGIN and TCLookupTable_END macros. Keep in
- // mind that the table is a static data member of the class. So the best
- // place to initialize the static data members is in your class
- // implementation (CPP) file:
- //
- // // (In MyClass.cpp)
- // // Static Initialization
- // TCLookupTable_BEGIN(CMyClass, fruits)
- // TCLookupTable_ENTRY(10, TEXT("Apple"))
- // TCLookupTable_ENTRY(20, TEXT("Banana"))
- // TCLookupTable_ENTRY(30, TEXT("Orange"))
- // TCLookupTable_END()
- //
- // The above example only shows the TCLookupTable_ENTRY macro, but several
- // other macros are provided to assist in the declaration of other common
- // scenarios, such as when the associated value type is a structure.
- //
- // Now that your lookup table is initialized, the TCLookupTable_FIND macro
- // allows a key and its associated value to easily be found in the table:
- //
- // LPCTSTR CMyClass::FruitToString(int idFruit) const
- // {
- // // Lookup the specified fruit ID
- // LPCTSTR pszName;
- // bool bFound = TCLookupTable_FIND(fruit, idFruit, pszName);
- // return bFound ? pszName : NULL;
- // }
- //
- // While the above example demonstrates the most common use for a lookup
- // table, it is sometimes useful to manually iterate through the table
- // entries. To assist with this, the TCLookupTable_SIZE macro is provided.
- // As its name implies, it provides the number of entries in the table. The
- // table consists of a regular array of TCLookupTablePair structures. Since
- // this structure is a template, the TCLookupTable_DECLARE macro declares
- // a type definition consisting of the table name suffixed with _ValueType.
- // In the following example, the /entry/ variable is a reference of type
- // /fruit_ValueType/, which is the type definition declared by the
- // TCLookupTable_DECLARE macro:
- //
- // void CMyClass::DumpFruitTable() const
- // {
- // for (int i = 0; i < TCLookupTable_SIZE(fruit); ++i)
- // {
- // fruit_ValueType& entry = fruit[i];
- // _TRACE2("Fruit ID %d = %s\n", entry.m_key, entry.m_value);
- // }
- // }
- //
- // See Also: TCLookupTablePair, TCLookupTable_DECLARE,
- // TCLookupTable_DECLARE, TCLookupTable_BEGIN, TCLookupTable_END,
- // TCLookupTable_ENTRY Macros, TCLookupTable_SIZE, TCLookupTable_FIND,
- // TCLookupTable_Find
- #define TCLookupTable
- #endif // _DOCJET_ONLY
- /////////////////////////////////////////////////////////////////////////////
- // Declares a static lookup table as a static member variable. Also declares
- // a type definition for the entries of the table by suffixing the
- // /table/ parameter with _ValueType.
- //
- // Use this macro within a class declaration. More than one table can be
- // declared in a class by specifying a different /table/ name in each macro
- // statement.
- //
- // Parameters:
- // table - The table name, which doubles as the name of the static member
- // variable.
- // Key - The type of the table's keys.
- // Value - The type of the table's associated values.
- //
- // See Also: TCLookupTable Macros, TCLookupTable_BEGIN, TCLookupTablePair
- #define TCLookupTable_DECLARE(table, Key, Value) \
- typedef TCLookupTablePair<Key, Value> table##_ValueType; \
- static table##_ValueType table [];
- #define TCLookupTable_DECLARE_REF(table, Key, Value, KeyRef) \
- typedef TCLookupTablePair<Key, Value, KeyRef> table##_ValueType; \
- static table##_ValueType table [];
- /////////////////////////////////////////////////////////////////////////////
- // Begins the initialization scope of a static lookup table. This scope
- // should contain TCLookupTable_ENTRY macros and should end with the
- // TCLookupTable_END macro.
- //
- // Since this initializes a static member variable of the specified class, it
- // needs to be specified *outside* of the class declaration and positioned so
- // that it is included exactly *once* by the linker. The best place to
- // initialize the static data members is in the class implementation (CPP)
- // file.
- //
- // Parameters:
- // theClass - the name of the class which declares the static lookup table.
- // table - the name of the table in /theClass/.
- //
- // See Also: TCLookupTable Macros, TCLookupTable_ENTRY Macros,
- // TCLookupTable_END
- #define TCLookupTable_BEGIN(theClass, table) \
- theClass::table##_ValueType theClass::table [] = {
- /////////////////////////////////////////////////////////////////////////////
- // {alias: TCLookupTable_ENTRY2, TCLookupTable_ENTRY3, TCLookupTable_ENTRY4}
- // {alias: TCLookupTable_ENTRY_PREFIX, TCLookupTable_ENTRY_SUFFIX}
- // Initializes an entry in a static lookup table. These macros should only
- // be used within the initialization scope of a static lookup table. This
- // scope should begin with the TCLookupTable_BEGIN macro and should end with
- // the TCLookupTable_END macro.
- //
- // TCLookupTable_ENTRY is the simplest of these macros, taking just a key
- // and a value with which to initialize the table entry.
- //
- // TCLookupTable_ENTRY2 through TCLookupTable_ENTRY4 require the key and from
- // 2 to 4 value parameters, respectively. The multiple value parameters are
- // used to initialize the members of a structure when a structure is used as
- // the table's value type.
- //
- // TCLookupTable_ENTRY_PREFIX and TCLookupTable_ENTRY_SUFFIX are used when
- // the key and/or value are symbolic and the symbols contain some element of
- // identical text. For example, if a lookup table was being used to map error
- // code identifiers to string table identifiers, the following sets of
- // entries would be equivalent:
- //
- // This way is tedious and the repetition may introduce typing errors:
- //
- // TCLookupTable_ENTRY(E_FILENOTFOUND, IDS_E_FILENOTFOUND)
- // TCLookupTable_ENTRY(E_INPUTIS2UGLY, IDS_E_INPUTIS2UGLY)
- //
- // This way results in the exact same table initialization:
- //
- // TCLookupTable_ENTRY_PREFIX(E_FILENOTFOUND, IDS_)
- // TCLookupTable_ENTRY_PREFIX(E_INPUTIS2UGLY, IDS_)
- //
- // TODO: It may also be useful to provide a macro to "stringize" the key
- // symbol to derive the value:
- //
- // #define TCLookupTable_ENTRY_STRING(key) \
- // TCLookupTable_Entry(key, TEXT(#key))
- //
- // Parameters:
- // key - The value with which to initialize the table entry's key.
- // value - The value to which the table entry's key is associated.
- // value1_thru_value4 - The values with which to initialize the structure
- // associated with the table entry's key.
- // prefix - Used to create a value name based on the key parameter prefixed
- // with the specified parameter.
- // suffix - Used to create a value name based on the key parameter suffixed
- // with the specified parameter.
- //
- // Macro Group: TCLookupTable_ENTRY Macros
- //
- // Declaration:
- // #define TCLookupTable_ENTRY(key, value)
- // #define TCLookupTable_ENTRY2(key, value1, value2)
- // #define TCLookupTable_ENTRY3(key, value1, value2, value3)
- // #define TCLookupTable_ENTRY4(key, value1, value2, value3, value4)
- // #define TCLookupTable_ENTRY_PREFIX(key, prefix)
- // #define TCLookupTable_ENTRY_SUFFIX(key, suffix)
- //
- // See Also: TCLookupTable Macros, TCLookupTable_BEGIN, TCLookupTable_END
- #define TCLookupTable_ENTRY(key, value) \
- { key, value },
- /////////////////////////////////////////////////////////////////////////////
- // {partof:TCLookupTable_ENTRY}
- #define TCLookupTable_ENTRY2(key, value1, value2) \
- { key, {value1, value2} },
- /////////////////////////////////////////////////////////////////////////////
- // {partof:TCLookupTable_ENTRY}
- #define TCLookupTable_ENTRY3(key, value1, value2, value3) \
- { key, {value1, value2, value3} },
- /////////////////////////////////////////////////////////////////////////////
- // {partof:TCLookupTable_ENTRY}
- #define TCLookupTable_ENTRY4(key, value1, value2, value3, value4) \
- { key, {value1, value2, value3, value4} },
- /////////////////////////////////////////////////////////////////////////////
- // {partof:TCLookupTable_ENTRY}
- #define TCLookupTable_ENTRY_PREFIX(key, prefix) \
- TCLookupTable_ENTRY(key, prefix##key)
- /////////////////////////////////////////////////////////////////////////////
- // {partof:TCLookupTable_ENTRY}
- #define TCLookupTable_ENTRY_SUFFIX(key, suffix) \
- TCLookupTable_ENTRY(key, key##suffix)
- /////////////////////////////////////////////////////////////////////////////
- // Ends the initialization scope of a static lookup table. This scope should
- // begin with the TCLookupTable_BEGIN macro and should contain
- // TCLookupTable_ENTRY macros.
- //
- // See Also: TCLookupTable Macros, TCLookupTable_BEGIN, TCLookupTable_ENTRY
- // Macros
- #define TCLookupTable_END() };
- /////////////////////////////////////////////////////////////////////////////
- // Computes the number of entries in a static lookup table. Since the size of
- // the table is known at compile time, this macro will compile out to a
- // constant value.
- //
- // Parameters:
- // table - The name of the table.
- //
- // Return Value: The number of elements in the table.
- //
- // See Also: TCLookupTable Macros
- #define TCLookupTable_SIZE(table) (sizeof(table) / sizeof(table[0]))
- /////////////////////////////////////////////////////////////////////////////
- // Iterates through the entries of the specified lookup table until either
- // the specified /key/ is found or the end of the table is reached.
- //
- // Parameters:
- // table - The name of the table.
- // key - The key to be located in the table.
- // value - A reference to where the located key's associated value will be
- // copied. If the key is not found, this parameter is not used.
- //
- // Return Value: true if the specified key was located in the specified
- // table, otherwise false;
- //
- // See Also: TCLookupTable Macros, TCLookupTable_Find
- #define TCLookupTable_FIND(table, key, value) \
- TCLookupTable_Find<table##_ValueType::KeyT, \
- table##_ValueType::ValueT, table##_ValueType::KeyRefT>(table, \
- TCLookupTable_SIZE(table), key, value)
- /////////////////////////////////////////////////////////////////////////////
- #endif // !__LookupTable_h__
|