# common/include/pion/PionHashMap.hpp

    00001 // -----------------------------------------------------------------------
    00002 // pion-common: a collection of common libraries used by the Pion Platform
    00003 // -----------------------------------------------------------------------
    00004 // Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
    00005 //
    00006 // Distributed under the Boost Software License, Version 1.0.
    00007 // See http://www.boost.org/LICENSE_1_0.txt
    00008 //
    00009
    00010 #ifndef __PION_PIONHASHMAP_HEADER__
    00011 #define __PION_PIONHASHMAP_HEADER__
    00012
    00013 #include <string>
    00014 #include <cctype>
    00015 #include <boost/functional/hash.hpp>
    00016 #include <pion/PionConfig.hpp>
    00017
    00018 #if defined(PION_HAVE_UNORDERED_MAP)
    00019     #include <tr1/unordered_map>
    00020 #elif defined(PION_HAVE_EXT_HASH_MAP)
    00021     #include <ext/hash_map>
    00022 #elif defined(PION_HAVE_HASH_MAP)
    00023     #include <hash_map>
    00024 #endif
    00025
    00026
    00027 namespace pion {    // begin namespace pion
    00028
    00029
    00030 #if defined(PION_HAVE_UNORDERED_MAP)
    00031     #define PION_HASH_MAP std::tr1::unordered_map
    00032     #define PION_HASH_MULTIMAP std::tr1::unordered_multimap
    00033     #define PION_HASH_STRING boost::hash<std::string>
    00034     #define PION_HASH(TYPE) boost::hash<TYPE>
    00035 #elif defined(PION_HAVE_EXT_HASH_MAP)
    00036     #if __GNUC__ >= 3
    00037         #define PION_HASH_MAP __gnu_cxx::hash_map
    00038         #define PION_HASH_MULTIMAP __gnu_cxx::hash_multimap
    00039     #else
    00040         #define PION_HASH_MAP hash_map
    00041         #define PION_HASH_MULTIMAP hash_multimap
    00042     #endif
    00043     #define PION_HASH_STRING boost::hash<std::string>
    00044     #define PION_HASH(TYPE) boost::hash<TYPE>
    00045 #elif defined(PION_HAVE_HASH_MAP)
    00046     #ifdef _MSC_VER
    00047         #define PION_HASH_MAP stdext::hash_map
    00048         #define PION_HASH_MULTIMAP stdext::hash_multimap
    00049         #define PION_HASH_STRING stdext::hash_compare<std::string, std::less<std::string> >
    00050         #define PION_HASH(TYPE) stdext::hash_compare<TYPE, std::less<TYPE> >
    00051     #else
    00052         #define PION_HASH_MAP hash_map
    00053         #define PION_HASH_MULTIMAP hash_multimap
    00054         #define PION_HASH_STRING boost::hash<std::string>
    00055         #define PION_HASH(TYPE) boost::hash<TYPE>
    00056     #endif
    00057 #endif
    00058
    00059
    00061 struct CaseInsensitiveEqual {
    00062     inline bool operator()(const std::string& str1, const std::string& str2) const {
    00063         if (str1.size() != str2.size())
    00064             return false;
    00065         std::string::const_iterator it1 = str1.begin();
    00066         std::string::const_iterator it2 = str2.begin();
    00067         while ( (it1!=str1.end()) && (it2!=str2.end()) ) {
    00068             if (tolower(*it1) != tolower(*it2))
    00069                 return false;
    00070             ++it1;
    00071             ++it2;
    00072         }
    00073         return true;
    00074     }
    00075 };
    00076
    00077
    00079 struct CaseInsensitiveHash {
    00080     inline unsigned long operator()(const std::string& str) const {
    00081         unsigned long value = 0;
    00082         for (std::string::const_iterator i = str.begin(); i!= str.end(); ++i)
    00083             value = static_cast<unsigned char>(tolower(*i)) + (value << 6) + (value << 16) - value;
    00084         return value;
    00085     }
    00086 };
    00087
    00088
    00090 struct CaseInsensitiveLess {
    00091     inline bool operator()(const std::string& str1, const std::string& str2) const {
    00092         std::string::const_iterator it1 = str1.begin();
    00093         std::string::const_iterator it2 = str2.begin();
    00094         while ( (it1 != str1.end()) && (it2 != str2.end()) ) {
    00095             if (tolower(*it1) != tolower(*it2))
    00096                 return (tolower(*it1) < tolower(*it2));
    00097             ++it1;
    00098             ++it2;
    00099         }
    00100         return (str1.size() < str2.size());
    00101     }
    00102 };
    00103
    00104
    00105 #ifdef _MSC_VER
    00107     struct CaseInsensitiveHashCompare : public stdext::hash_compare<std::string, CaseInsensitiveLess> {
    00108         // makes operator() with two arguments visible, otherwise it would be hidden by the operator() defined here
    00109         using stdext::hash_compare<std::string, CaseInsensitiveLess>::operator();
    00110
    00111         inline size_t operator()(const std::string& str) const {
    00112             return CaseInsensitiveHash()(str);
    00113         }
    00114     };
    00115 #endif
    00116
    00117
    00119 #ifdef _MSC_VER
    00120     typedef PION_HASH_MULTIMAP<std::string, std::string, CaseInsensitiveHashCompare>    StringDictionary;
    00121 #else
    00122     typedef PION_HASH_MULTIMAP<std::string, std::string, CaseInsensitiveHash, CaseInsensitiveEqual >    StringDictionary;
    00123 #endif
    00124
    00126 //typedef PION_HASH_MULTIMAP<std::string, std::string, PION_HASH_STRING >   StringDictionary;
    00127
    00128
    00129 }   // end namespace pion
    00130
    00131 #endif