Changeset 803 in dev for branches/egtra/ab5.0/jenga/include
- Timestamp:
- Feb 11, 2011, 10:05:14 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/egtra/ab5.0/jenga/include/common/Hashmap.h
r639 r803 1 1 #pragma once 2 2 #include <unordered_set> 3 #include <boost/range/algorithm.hpp> 4 #include <boost/checked_delete.hpp> 5 #include <boost/iterator/transform_iterator.hpp> 6 #include <boost/cast.hpp> 3 7 4 8 namespace Jenga{ 5 9 namespace Common{ 6 10 11 template<class T> 12 class ObjectInHashmap; 13 template<class T> 14 struct ObjectInHashmapHash; 15 template<class T> 16 struct ObjectInHashmapEqualTo; 7 17 8 18 #define MAX_HASHMAP 65535 9 template<class T> class Hashmap 10 { 11 T* hashArray[MAX_HASHMAP]; 19 template<class T> class Hashmap : boost::noncopyable 20 { 21 typedef std::unordered_set<ObjectInHashmap<T>*, ObjectInHashmapHash<T>, ObjectInHashmapEqualTo<T>> MapType; 22 MapType map; 23 24 struct downcast 25 { 26 typedef T* result_type; 27 T* operator ()(ObjectInHashmap<T>* p) const 28 { 29 return boost::polymorphic_cast<T*>(p); 30 } 31 }; 32 struct const_downcast 33 { 34 typedef T const* result_type; 35 T const* operator ()(ObjectInHashmap<T> const* p) const 36 { 37 return boost::polymorphic_cast<T const*>(p); 38 } 39 }; 12 40 13 41 public: 14 virtual int GetHash( const char *keyName ) const15 {16 int key;17 for(key=0;*keyName!='\0';keyName++){18 key=((key<<8)+ *keyName )%MAX_HASHMAP;19 }20 return key;21 }22 42 23 43 Hashmap() 24 : isIteratorReady( false ) 25 { 26 memset( hashArray, 0, MAX_HASHMAP*sizeof(T*) ); 44 { 27 45 } 28 46 ~Hashmap() … … 32 50 void Clear() 33 51 { 34 for( int i=0; i<MAX_HASHMAP; i++ ) 35 { 36 T* temp = hashArray[i]; 37 if( temp ) 38 { 39 delete temp; 40 } 41 } 42 memset( hashArray, 0, MAX_HASHMAP*sizeof(T*) ); 52 boost::for_each(*this, boost::checked_deleter<T const>()); 53 map.clear(); 43 54 } 44 55 … … 46 57 void PullOutAll() 47 58 { 48 memset( hashArray, 0, MAX_HASHMAP*sizeof(T*) ); 49 } 50 51 bool Put( T* value ) 52 { 53 int key = GetHash( value->GetKeyName().c_str() ); 54 55 if(hashArray[key]){ 56 T *temp = hashArray[key]; 57 while( true ){ 58 if( temp->IsDuplication( value ) ) 59 { 60 // 重複している 61 return false; 62 } 63 64 if( temp->GetChainNext() == NULL ) 65 { 66 break; 67 } 68 temp = temp->GetChainNext(); 69 } 70 temp->SetChainNext( value ); 71 } 72 else{ 73 hashArray[key] = value; 74 } 75 76 return true; 77 } 78 79 T* GetHashArrayElement( const char *keyName ) 80 { 81 return hashArray[GetHash(keyName)]; 82 } 83 const T* GetHashArrayElement( const char *keyName ) const 84 { 85 return hashArray[GetHash(keyName)]; 86 } 87 88 bool IsExistDuplicationKeyName( const std::string &keyName ) const 89 { 90 int key = GetHash( keyName.c_str() ); 91 92 if(hashArray[key]){ 93 const T *temp = hashArray[key]; 94 while( true ){ 95 if( temp->IsDuplication( keyName ) ) 96 { 97 // 重複している 98 return true; 99 } 100 101 if( temp->GetChainNext() == NULL ) 102 { 103 break; 104 } 105 temp = temp->GetChainNext(); 106 } 107 } 108 109 return false; 59 map.clear(); 60 } 61 62 bool Put(T* value) 63 { 64 if (value == nullptr) 65 { 66 throw std::invalid_argument("Hashmap::Put"); 67 } 68 return map.insert(value).second; 69 } 70 71 typedef boost::transform_iterator<downcast, typename MapType::local_iterator> local_iterator; 72 typedef boost::transform_iterator<const_downcast, typename MapType::const_local_iterator> const_local_iterator; 73 74 boost::iterator_range<local_iterator> GetHashArrayElement(std::string const& keyName) 75 { 76 ObjectInHashmapDummy<T> t(keyName); 77 return boost::iterator_range<local_iterator>( 78 local_iterator(map.begin(map.bucket(&t)), downcast()), 79 local_iterator(map.end(map.bucket(&t)), downcast())); 80 } 81 82 boost::iterator_range<const_local_iterator> GetHashArrayElement(std::string const& keyName) const 83 { 84 ObjectInHashmapDummy<T> t(keyName); 85 return boost::iterator_range<const_local_iterator>( 86 const_local_iterator(map.begin(map.bucket(&t)), const_downcast()), 87 const_local_iterator(map.end(map.bucket(&t)), const_downcast())); 88 } 89 90 bool IsExistDuplicationKeyName(const std::string &keyName) const 91 { 92 ObjectInHashmapDummy<T> t(keyName); 93 return map.find(&t) != map.end(); 110 94 } 111 95 112 96 bool IsExist( const T* value ) const 113 97 { 114 int key = GetHash( value->GetKeyName().c_str() ); 115 116 if(hashArray[key]){ 117 const T *temp = hashArray[key]; 118 while( true ){ 119 if( temp->IsDuplication( value ) ) 120 { 121 // 重複している 122 return true; 123 } 124 125 if( temp->GetChainNext() == NULL ) 126 { 127 break; 128 } 129 temp = temp->GetChainNext(); 130 } 131 } 132 133 return false; 134 } 135 136 const T *FindLike( const T* value ) const 137 { 138 int key = GetHash( value->GetKeyName().c_str() ); 139 140 if(hashArray[key]){ 141 const T *temp = hashArray[key]; 142 while( true ){ 143 if( temp->IsDuplication( value ) ) 144 { 145 // 重複している 146 return temp; 147 } 148 149 if( temp->GetChainNext() == NULL ) 150 { 151 break; 152 } 153 temp = temp->GetChainNext(); 154 } 155 } 156 157 return NULL; 98 return map.find(const_cast<T*>(value)) != map.end(); 99 } 100 101 const T *FindLike( const ObjectInHashmap<T>* value ) const 102 { 103 auto it = map.find(const_cast<ObjectInHashmap<T>*>(value)); 104 return it != map.end() 105 ? boost::polymorphic_downcast<T const*>(*it) 106 : nullptr; 158 107 } 159 108 … … 162 111 // イテレータ 163 112 ///////////////////////////////////////////////////////////////// 164 private: 165 mutable std::vector<T*> iterator_Objects; 166 mutable int iterator_CurrentNext; 167 mutable bool isIteratorReady; 168 public: 169 void Iterator_Init() const 170 { 171 iterator_Objects.clear(); 172 iterator_CurrentNext = 0; 173 174 for( int i=0; i<MAX_HASHMAP; i++ ){ 175 if( hashArray[i] ){ 176 T* temp = hashArray[i]; 177 while( temp ) 178 { 179 iterator_Objects.push_back( temp ); 180 181 temp = (T*)temp->GetChainNext(); 182 } 183 } 184 } 185 186 isIteratorReady = true; 187 } 188 void Iterator_Reset() const 189 { 190 if( !isIteratorReady ) 191 { 192 Jenga::Throw( "イテレータの準備ができていない" ); 193 } 194 iterator_CurrentNext = 0; 195 } 196 bool Iterator_HasNext() const 197 { 198 return ( iterator_CurrentNext < (int)iterator_Objects.size() ); 199 } 200 T *Iterator_GetNext() const 201 { 202 return iterator_Objects[iterator_CurrentNext++]; 203 } 204 int Iterator_GetMaxCount() const 205 { 206 return (int)iterator_Objects.size(); 207 } 208 113 //typedef boost::transform_iterator<downcast, typename MapType::iterator> iterator; 114 typedef boost::transform_iterator<downcast, typename MapType::const_iterator> const_iterator; 115 typedef const_iterator iterator; 116 typedef typename MapType::size_type size_type; 117 typedef typename MapType::difference_type difference_type; 118 //iterator begin() 119 //{ 120 // return iterator(map.begin(), downcast()); 121 //} 122 //iterator end() 123 //{ 124 // return iterator(map.end(), downcast()); 125 //} 126 const_iterator begin() const 127 { 128 return const_iterator(map.begin(), downcast()); 129 } 130 const_iterator end() const 131 { 132 return const_iterator(map.end(), downcast()); 133 } 209 134 210 135 // XMLシリアライズ用 … … 215 140 { 216 141 std::vector<T *> objects; 217 ar & BOOST_SERIALIZATION_NVP( objects ); 218 219 // 読み込み後の処理 142 ar & BOOST_SERIALIZATION_NVP(objects); 220 143 Clear(); 221 BOOST_FOREACH( T *object, objects ) 222 { 223 Put( object ); 224 } 225 Iterator_Init(); 144 map = boost::copy_range<MapType>(objects); 226 145 } 227 146 template<class Archive> void save(Archive& ar, const unsigned int version) const 228 147 { 229 // 保存準備 230 std::vector<T *> objects; 231 objects.clear(); 232 Iterator_Reset(); 233 while( Iterator_HasNext() ) 234 { 235 objects.push_back( Iterator_GetNext() ); 236 } 237 238 ar & BOOST_SERIALIZATION_NVP( objects ); 239 } 240 }; 241 242 template<class T> class ObjectInHashmap 243 { 244 T *pNextObject; 148 std::vector<T *> objects(begin(), end()); 149 ar & BOOST_SERIALIZATION_NVP(objects); 150 } 151 }; 152 153 template<class T> 154 class ObjectInHashmap 155 { 245 156 public: 246 157 247 158 ObjectInHashmap() 248 : pNextObject( NULL )249 159 { 250 160 } 251 161 ~ObjectInHashmap() 252 162 { 253 if( pNextObject )254 {255 delete pNextObject;256 }257 163 } 258 164 … … 266 172 return ( GetKeyName() == keyName ); 267 173 } 268 269 T *GetChainNext() 270 { 271 return pNextObject; 272 } 273 const T *GetChainNext() const 274 { 275 return pNextObject; 276 } 277 void SetChainNext( T *pNextObject ) 278 { 279 this->pNextObject = pNextObject; 174 }; 175 176 template<class T> 177 struct ObjectInHashmapHash 178 { 179 typedef std::size_t result_type; 180 std::size_t operator ()(ObjectInHashmap<T> const* x) const 181 { 182 return std::hash<std::string>()(x->GetKeyName()); 183 } 184 }; 185 186 // GetHashArrayElementなどで文字列から検索するために用いる。 187 template<class T> 188 class ObjectInHashmapDummy : public ObjectInHashmap<T>, boost::noncopyable 189 { 190 public: 191 explicit ObjectInHashmapDummy(std::string const& s) : str(s) {} 192 193 virtual std::string const& GetKeyName() const override 194 { 195 return str; 196 } 197 198 virtual bool IsDuplication(T const* value) const override 199 { 200 return value != nullptr 201 && value->ObjectInHashmap<T>::IsDuplication(str); 202 } 203 204 private: 205 std::string const& str; 206 }; 207 208 template<class T> 209 struct ObjectInHashmapEqualTo 210 { 211 typedef bool result_type; 212 bool operator ()(ObjectInHashmap<T> const* lhs, ObjectInHashmap<T> const* rhs) const 213 { 214 assert(lhs != nullptr); 215 assert(rhs != nullptr); 216 if (auto pl = dynamic_cast<T const*>(rhs)) 217 { 218 return lhs->IsDuplication(pl); 219 } 220 else 221 { 222 return rhs->IsDuplication(dynamic_cast<T const*>(lhs)); 223 } 280 224 } 281 225 };
Note:
See TracChangeset
for help on using the changeset viewer.