source: dev/branches/egtra/ab5.0/jenga/include/common/Hashmap.h@ 820

Last change on this file since 820 was 818, checked in by イグトランス (egtra), 14 years ago

Jenga/common/String.hに対するテストを追加

File size: 5.5 KB
Line 
1#include <stdexcept>
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>
7#include <boost/serialization/serialization.hpp>
8#include <boost/serialization/split_member.hpp>
9
10#pragma once
11
12
13namespace Jenga{
14namespace Common{
15
16template<class T>
17class ObjectInHashmap;
18template<class T>
19struct ObjectInHashmapHash;
20template<class T>
21struct ObjectInHashmapEqualTo;
22
23#define MAX_HASHMAP 65535
24template<class T> class Hashmap : boost::noncopyable
25{
26 typedef std::unordered_set<ObjectInHashmap<T>*, ObjectInHashmapHash<T>, ObjectInHashmapEqualTo<T>> MapType;
27 MapType map;
28
29 struct downcast
30 {
31 typedef T* result_type;
32 T* operator ()(ObjectInHashmap<T>* p) const
33 {
34 return boost::polymorphic_cast<T*>(p);
35 }
36 };
37 struct const_downcast
38 {
39 typedef T const* result_type;
40 T const* operator ()(ObjectInHashmap<T> const* p) const
41 {
42 return boost::polymorphic_cast<T const*>(p);
43 }
44 };
45
46public:
47
48 Hashmap()
49 {
50 }
51 ~Hashmap()
52 {
53 Clear();
54 }
55 void Clear()
56 {
57 boost::for_each(*this, boost::checked_deleter<T const>());
58 map.clear();
59 }
60
61 // 内容を破棄せずにすべて抜き取る
62 void PullOutAll()
63 {
64 map.clear();
65 }
66
67 bool Put(T* value)
68 {
69 if (value == nullptr)
70 {
71 throw std::invalid_argument("Hashmap::Put");
72 }
73 return map.insert(value).second;
74 }
75
76 typedef boost::transform_iterator<downcast, typename MapType::local_iterator> local_iterator;
77 typedef boost::transform_iterator<const_downcast, typename MapType::const_local_iterator> const_local_iterator;
78
79 boost::iterator_range<local_iterator> GetHashArrayElement(std::string const& keyName)
80 {
81 ObjectInHashmapDummy<T> t(keyName);
82 return boost::iterator_range<local_iterator>(
83 local_iterator(map.begin(map.bucket(&t)), downcast()),
84 local_iterator(map.end(map.bucket(&t)), downcast()));
85 }
86
87 boost::iterator_range<const_local_iterator> GetHashArrayElement(std::string const& keyName) const
88 {
89 ObjectInHashmapDummy<T> t(keyName);
90 return boost::iterator_range<const_local_iterator>(
91 const_local_iterator(map.begin(map.bucket(&t)), const_downcast()),
92 const_local_iterator(map.end(map.bucket(&t)), const_downcast()));
93 }
94
95 bool IsExistDuplicationKeyName(const std::string &keyName) const
96 {
97 ObjectInHashmapDummy<T> t(keyName);
98 return map.find(&t) != map.end();
99 }
100
101 bool IsExist( const T* value ) const
102 {
103 return map.find(const_cast<T*>(value)) != map.end();
104 }
105
106 const T *FindLike( const ObjectInHashmap<T>* value ) const
107 {
108 auto it = map.find(const_cast<ObjectInHashmap<T>*>(value));
109 return it != map.end()
110 ? boost::polymorphic_downcast<T const*>(*it)
111 : nullptr;
112 }
113
114
115 /////////////////////////////////////////////////////////////////
116 // イテレータ
117 /////////////////////////////////////////////////////////////////
118 //typedef boost::transform_iterator<downcast, typename MapType::iterator> iterator;
119 typedef boost::transform_iterator<downcast, typename MapType::const_iterator> const_iterator;
120 typedef const_iterator iterator;
121 typedef typename MapType::size_type size_type;
122 typedef typename MapType::difference_type difference_type;
123 //iterator begin()
124 //{
125 // return iterator(map.begin(), downcast());
126 //}
127 //iterator end()
128 //{
129 // return iterator(map.end(), downcast());
130 //}
131 const_iterator begin() const
132 {
133 return const_iterator(map.begin(), downcast());
134 }
135 const_iterator end() const
136 {
137 return const_iterator(map.end(), downcast());
138 }
139
140 // XMLシリアライズ用
141private:
142 friend class boost::serialization::access;
143 BOOST_SERIALIZATION_SPLIT_MEMBER();
144 template<class Archive> void load(Archive& ar, const unsigned int version)
145 {
146 std::vector<T *> objects;
147 ar & BOOST_SERIALIZATION_NVP(objects);
148 Clear();
149 map = boost::copy_range<MapType>(objects);
150 }
151 template<class Archive> void save(Archive& ar, const unsigned int version) const
152 {
153 std::vector<T *> objects(begin(), end());
154 ar & BOOST_SERIALIZATION_NVP(objects);
155 }
156};
157
158template<class T>
159class ObjectInHashmap
160{
161protected:
162 ObjectInHashmap()
163 {
164 }
165 ~ObjectInHashmap()
166 {
167 }
168
169public:
170 virtual const std::string &GetKeyName() const = 0;
171 virtual bool IsDuplication( const T *value ) const
172 {
173 return ( GetKeyName() == value->GetName() );
174 }
175 virtual bool IsDuplication( const std::string &keyName ) const
176 {
177 return ( GetKeyName() == keyName );
178 }
179};
180
181template<class T>
182struct ObjectInHashmapHash
183{
184 typedef std::size_t result_type;
185 std::size_t operator ()(ObjectInHashmap<T> const* x) const
186 {
187 return std::hash<std::string>()(x->GetKeyName());
188 }
189};
190
191// GetHashArrayElementなどで文字列から検索するために用いる。
192template<class T>
193class ObjectInHashmapDummy : public ObjectInHashmap<T>, boost::noncopyable
194{
195public:
196 explicit ObjectInHashmapDummy(std::string const& s) : str(s) {}
197
198 virtual std::string const& GetKeyName() const override
199 {
200 return str;
201 }
202
203 virtual bool IsDuplication(T const* value) const override
204 {
205 return value != nullptr
206 && value->ObjectInHashmap<T>::IsDuplication(str);
207 }
208
209private:
210 std::string const& str;
211};
212
213template<class T>
214struct ObjectInHashmapEqualTo
215{
216 typedef bool result_type;
217 bool operator ()(_In_ ObjectInHashmap<T> const* lhs, _In_ ObjectInHashmap<T> const* rhs) const
218 {
219 assert(lhs != nullptr);
220 assert(rhs != nullptr);
221 if (auto pl = dynamic_cast<T const*>(rhs))
222 {
223 return lhs->IsDuplication(pl);
224 }
225 else
226 {
227 return rhs->IsDuplication(dynamic_cast<T const*>(lhs));
228 }
229 }
230};
231
232
233}}
Note: See TracBrowser for help on using the repository browser.