1 | #pragma once
|
---|
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 |
|
---|
8 | namespace Jenga{
|
---|
9 | namespace Common{
|
---|
10 |
|
---|
11 | template<class T>
|
---|
12 | class ObjectInHashmap;
|
---|
13 | template<class T>
|
---|
14 | struct ObjectInHashmapHash;
|
---|
15 | template<class T>
|
---|
16 | struct ObjectInHashmapEqualTo;
|
---|
17 |
|
---|
18 | #define MAX_HASHMAP 65535
|
---|
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 | };
|
---|
40 |
|
---|
41 | public:
|
---|
42 |
|
---|
43 | Hashmap()
|
---|
44 | {
|
---|
45 | }
|
---|
46 | ~Hashmap()
|
---|
47 | {
|
---|
48 | Clear();
|
---|
49 | }
|
---|
50 | void Clear()
|
---|
51 | {
|
---|
52 | boost::for_each(*this, boost::checked_deleter<T const>());
|
---|
53 | map.clear();
|
---|
54 | }
|
---|
55 |
|
---|
56 | // 内容を破棄せずにすべて抜き取る
|
---|
57 | void PullOutAll()
|
---|
58 | {
|
---|
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();
|
---|
94 | }
|
---|
95 |
|
---|
96 | bool IsExist( const T* value ) const
|
---|
97 | {
|
---|
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;
|
---|
107 | }
|
---|
108 |
|
---|
109 |
|
---|
110 | /////////////////////////////////////////////////////////////////
|
---|
111 | // イテレータ
|
---|
112 | /////////////////////////////////////////////////////////////////
|
---|
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 | }
|
---|
134 |
|
---|
135 | // XMLシリアライズ用
|
---|
136 | private:
|
---|
137 | friend class boost::serialization::access;
|
---|
138 | BOOST_SERIALIZATION_SPLIT_MEMBER();
|
---|
139 | template<class Archive> void load(Archive& ar, const unsigned int version)
|
---|
140 | {
|
---|
141 | std::vector<T *> objects;
|
---|
142 | ar & BOOST_SERIALIZATION_NVP(objects);
|
---|
143 | Clear();
|
---|
144 | map = boost::copy_range<MapType>(objects);
|
---|
145 | }
|
---|
146 | template<class Archive> void save(Archive& ar, const unsigned int version) const
|
---|
147 | {
|
---|
148 | std::vector<T *> objects(begin(), end());
|
---|
149 | ar & BOOST_SERIALIZATION_NVP(objects);
|
---|
150 | }
|
---|
151 | };
|
---|
152 |
|
---|
153 | template<class T>
|
---|
154 | class ObjectInHashmap
|
---|
155 | {
|
---|
156 | public:
|
---|
157 |
|
---|
158 | ObjectInHashmap()
|
---|
159 | {
|
---|
160 | }
|
---|
161 | ~ObjectInHashmap()
|
---|
162 | {
|
---|
163 | }
|
---|
164 |
|
---|
165 | virtual const std::string &GetKeyName() const = 0;
|
---|
166 | virtual bool IsDuplication( const T *value ) const
|
---|
167 | {
|
---|
168 | return ( GetKeyName() == value->GetName() );
|
---|
169 | }
|
---|
170 | virtual bool IsDuplication( const std::string &keyName ) const
|
---|
171 | {
|
---|
172 | return ( GetKeyName() == keyName );
|
---|
173 | }
|
---|
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 | }
|
---|
224 | }
|
---|
225 | };
|
---|
226 |
|
---|
227 |
|
---|
228 | }}
|
---|