00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 #ifndef __PION_HASH_MAP_HEADER__
00011 #define __PION_HASH_MAP_HEADER__
00012 
00013 #include <string>
00014 #include <locale>
00015 #include <boost/algorithm/string.hpp>
00016 #include <boost/functional/hash.hpp>
00017 #include <pion/config.hpp>
00018 
00019 #if defined(PION_HAVE_UNORDERED_MAP)
00020     #include <tr1/unordered_map>
00021 #elif defined(PION_HAVE_EXT_HASH_MAP)
00022     #include <ext/hash_map>
00023 #elif defined(PION_HAVE_HASH_MAP)
00024     #include <hash_map>
00025 #endif
00026 
00027 
00028 namespace pion {    
00029 
00030 
00031 #if defined(PION_HAVE_UNORDERED_MAP)
00032     #define PION_HASH_MAP std::tr1::unordered_map
00033     #define PION_HASH_MULTIMAP std::tr1::unordered_multimap
00034     #define PION_HASH_STRING boost::hash<std::string>
00035     #define PION_HASH(TYPE) boost::hash<TYPE>
00036 #elif defined(PION_HAVE_EXT_HASH_MAP)
00037     #if __GNUC__ >= 3
00038         #define PION_HASH_MAP __gnu_cxx::hash_map
00039         #define PION_HASH_MULTIMAP __gnu_cxx::hash_multimap
00040     #else
00041         #define PION_HASH_MAP hash_map
00042         #define PION_HASH_MULTIMAP hash_multimap
00043     #endif
00044     #define PION_HASH_STRING boost::hash<std::string>
00045     #define PION_HASH(TYPE) boost::hash<TYPE>
00046 #elif defined(PION_HAVE_HASH_MAP)
00047     #ifdef _MSC_VER
00048         #define PION_HASH_MAP stdext::hash_map
00049         #define PION_HASH_MULTIMAP stdext::hash_multimap
00050         #define PION_HASH_STRING stdext::hash_compare<std::string, std::less<std::string> >
00051         #define PION_HASH(TYPE) stdext::hash_compare<TYPE, std::less<TYPE> >
00052     #else
00053         #define PION_HASH_MAP hash_map
00054         #define PION_HASH_MULTIMAP hash_multimap
00055         #define PION_HASH_STRING boost::hash<std::string>
00056         #define PION_HASH(TYPE) boost::hash<TYPE>
00057     #endif
00058 #endif
00059 
00063     struct iequal_to
00064         : std::binary_function<std::string, std::string, bool>
00065     {
00066         bool operator()(std::string const& x,
00067                         std::string const& y) const
00068         {
00069             return boost::algorithm::iequals(x, y, std::locale());
00070         }
00071     };
00072     
00076     struct ihash
00077         : std::unary_function<std::string, std::size_t>
00078     {
00079         std::size_t operator()(std::string const& x) const
00080         {
00081             std::size_t seed = 0;
00082             std::locale locale;
00083             
00084             for(std::string::const_iterator it = x.begin();
00085                 it != x.end(); ++it)
00086             {
00087                 boost::hash_combine(seed, std::toupper(*it, locale));
00088             }
00089             
00090             return seed;
00091         }
00092     };
00093     
00094 #ifdef _MSC_VER
00096     template<class _Ty> struct is_iless : public std::binary_function<_Ty, _Ty, bool>
00097     {
00099         is_iless( const std::locale& Loc=std::locale() ) : m_Loc( Loc ) {}
00100 
00102         bool operator()( const _Ty& Arg1, const _Ty& Arg2 ) const
00103         {
00104             return _Ty(boost::algorithm::to_upper_copy(Arg1, m_Loc)) < _Ty(boost::algorithm::to_upper_copy(Arg2, m_Loc));
00105         }
00106 
00107         private:
00108             std::locale m_Loc;
00109     };
00110 
00112     struct ihash_windows : public stdext::hash_compare<std::string, is_iless<std::string> > {
00113         
00114         using stdext::hash_compare<std::string, is_iless<std::string> >::operator();
00115         
00116         inline size_t operator()(const std::string& str) const {
00117             return ihash()(str);
00118         }
00119     };
00120 
00122     typedef PION_HASH_MULTIMAP<std::string, std::string, ihash_windows >    ihash_multimap;
00123 #else
00125     typedef PION_HASH_MULTIMAP<std::string, std::string, ihash, iequal_to >    ihash_multimap;
00126 #endif
00127 
00128 
00129 }   
00130 
00131 #endif