| 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 ()(_In_ ObjectInHashmap<T> const* lhs, _In_ 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 | }}
|
|---|