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 |
|
---|
13 | namespace Jenga{
|
---|
14 | namespace Common{
|
---|
15 |
|
---|
16 | template<class T>
|
---|
17 | class ObjectInHashmap;
|
---|
18 | template<class T>
|
---|
19 | struct ObjectInHashmapHash;
|
---|
20 | template<class T>
|
---|
21 | struct ObjectInHashmapEqualTo;
|
---|
22 |
|
---|
23 | #define MAX_HASHMAP 65535
|
---|
24 | template<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 |
|
---|
46 | public:
|
---|
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シリアライズ用
|
---|
141 | private:
|
---|
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 |
|
---|
158 | template<class T>
|
---|
159 | class ObjectInHashmap
|
---|
160 | {
|
---|
161 | protected:
|
---|
162 | ObjectInHashmap()
|
---|
163 | {
|
---|
164 | }
|
---|
165 | ~ObjectInHashmap()
|
---|
166 | {
|
---|
167 | }
|
---|
168 |
|
---|
169 | public:
|
---|
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 |
|
---|
181 | template<class T>
|
---|
182 | struct 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などで文字列から検索するために用いる。
|
---|
192 | template<class T>
|
---|
193 | class ObjectInHashmapDummy : public ObjectInHashmap<T>, boost::noncopyable
|
---|
194 | {
|
---|
195 | public:
|
---|
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 |
|
---|
209 | private:
|
---|
210 | std::string const& str;
|
---|
211 | };
|
---|
212 |
|
---|
213 | template<class T>
|
---|
214 | struct 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 | }}
|
---|