Mercurial > foo_out_sdl
comparison foosdk/sdk/pfc/map.h @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 #pragma once | |
| 2 #include "avltree.h" | |
| 3 | |
| 4 namespace pfc { | |
| 5 PFC_DECLARE_EXCEPTION(exception_map_entry_not_found,exception,"Map entry not found"); | |
| 6 | |
| 7 template<typename t_destination> class __map_overwrite_wrapper { | |
| 8 public: | |
| 9 __map_overwrite_wrapper(t_destination & p_destination) : m_destination(p_destination) {} | |
| 10 template<typename t_key,typename t_value> void operator() (const t_key & p_key,const t_value & p_value) {m_destination.set(p_key,p_value);} | |
| 11 private: | |
| 12 t_destination & m_destination; | |
| 13 }; | |
| 14 | |
| 15 template<typename t_storage_key, typename t_storage_value, typename t_comparator = comparator_default> | |
| 16 class map_t { | |
| 17 private: | |
| 18 typedef map_t<t_storage_key,t_storage_value,t_comparator> t_self; | |
| 19 public: | |
| 20 typedef t_storage_key t_key; typedef t_storage_value t_value; | |
| 21 template<typename _t_key,typename _t_value> | |
| 22 void set(const _t_key & p_key, const _t_value & p_value) { | |
| 23 bool isnew; | |
| 24 t_storage & storage = m_data.add_ex(t_search_set<_t_key,_t_value>(p_key,p_value), isnew); | |
| 25 if (!isnew) storage.m_value = p_value; | |
| 26 } | |
| 27 | |
| 28 template<typename _t_key> | |
| 29 t_storage_value & find_or_add(_t_key const & p_key) { | |
| 30 return m_data.add(t_search_query<_t_key>(p_key)).m_value; | |
| 31 } | |
| 32 | |
| 33 template<typename _t_key> | |
| 34 t_storage_value & find_or_add_ex(_t_key const & p_key,bool & p_isnew) { | |
| 35 return m_data.add_ex(t_search_query<_t_key>(p_key),p_isnew).m_value; | |
| 36 } | |
| 37 | |
| 38 template<typename _t_key> | |
| 39 bool have_item(const _t_key & p_key) const { | |
| 40 return m_data.have_item(t_search_query<_t_key>(p_key)); | |
| 41 } | |
| 42 | |
| 43 template<typename key_t> | |
| 44 bool contains(key_t const& arg) const { return have_item(arg); } | |
| 45 | |
| 46 template<typename _t_key,typename _t_value> | |
| 47 bool query(const _t_key & p_key,_t_value & p_value) const { | |
| 48 const t_storage * storage = m_data.find_ptr(t_search_query<_t_key>(p_key)); | |
| 49 if (storage == NULL) return false; | |
| 50 p_value = storage->m_value; | |
| 51 return true; | |
| 52 } | |
| 53 | |
| 54 template<typename _t_key> | |
| 55 const t_storage_value & operator[] (const _t_key & p_key) const { | |
| 56 const t_storage_value * ptr = query_ptr(p_key); | |
| 57 if (ptr == NULL) throw exception_map_entry_not_found(); | |
| 58 return *ptr; | |
| 59 } | |
| 60 | |
| 61 template<typename _t_key> | |
| 62 t_storage_value & operator[] (const _t_key & p_key) { | |
| 63 return find_or_add(p_key); | |
| 64 } | |
| 65 | |
| 66 template<typename _t_key> | |
| 67 const t_storage_value * query_ptr(const _t_key & p_key) const { | |
| 68 const t_storage * storage = m_data.find_ptr(t_search_query<_t_key>(p_key)); | |
| 69 if (storage == NULL) return NULL; | |
| 70 return &storage->m_value; | |
| 71 } | |
| 72 | |
| 73 template<typename _t_key> | |
| 74 t_storage_value * query_ptr(const _t_key & p_key) { | |
| 75 t_storage * storage = m_data.find_ptr(t_search_query<_t_key>(p_key)); | |
| 76 if (storage == NULL) return NULL; | |
| 77 return &storage->m_value; | |
| 78 } | |
| 79 | |
| 80 template<typename _t_key> | |
| 81 bool query_ptr(const _t_key & p_key, const t_storage_value * & out) const { | |
| 82 const t_storage * storage = m_data.find_ptr(t_search_query<_t_key>(p_key)); | |
| 83 if (storage == NULL) return false; | |
| 84 out = &storage->m_value; | |
| 85 return true; | |
| 86 } | |
| 87 | |
| 88 template<typename _t_key> | |
| 89 bool query_ptr(const _t_key & p_key, t_storage_value * & out) { | |
| 90 t_storage * storage = m_data.find_ptr(t_search_query<_t_key>(p_key)); | |
| 91 if (storage == NULL) return false; | |
| 92 out = &storage->m_value; | |
| 93 return true; | |
| 94 } | |
| 95 | |
| 96 template<bool inclusive,bool above,typename _t_key> | |
| 97 const t_storage_value * query_nearest_ptr(_t_key & p_key) const { | |
| 98 const t_storage * storage = m_data.template find_nearest_item<inclusive,above>(t_search_query<_t_key>(p_key)); | |
| 99 if (storage == NULL) return NULL; | |
| 100 p_key = storage->m_key; | |
| 101 return &storage->m_value; | |
| 102 } | |
| 103 | |
| 104 template<bool inclusive,bool above,typename _t_key> | |
| 105 t_storage_value * query_nearest_ptr(_t_key & p_key) { | |
| 106 t_storage * storage = m_data.template find_nearest_item<inclusive,above>(t_search_query<_t_key>(p_key)); | |
| 107 if (storage == NULL) return NULL; | |
| 108 p_key = storage->m_key; | |
| 109 return &storage->m_value; | |
| 110 } | |
| 111 | |
| 112 template<bool inclusive,bool above,typename _t_key,typename _t_value> | |
| 113 bool query_nearest(_t_key & p_key,_t_value & p_value) const { | |
| 114 const t_storage * storage = m_data.template find_nearest_item<inclusive,above>(t_search_query<_t_key>(p_key)); | |
| 115 if (storage == NULL) return false; | |
| 116 p_key = storage->m_key; | |
| 117 p_value = storage->m_value; | |
| 118 return true; | |
| 119 } | |
| 120 | |
| 121 | |
| 122 template<typename _t_key> | |
| 123 bool remove(const _t_key & p_key) { | |
| 124 return m_data.remove_item(t_search_query<_t_key>(p_key)); | |
| 125 } | |
| 126 | |
| 127 template<typename t_callback> | |
| 128 void enumerate(t_callback && p_callback) const { | |
| 129 enumeration_wrapper<t_callback> cb(p_callback); | |
| 130 m_data.enumerate(cb); | |
| 131 } | |
| 132 | |
| 133 template<typename t_callback> | |
| 134 void enumerate(t_callback && p_callback) { | |
| 135 enumeration_wrapper_var<t_callback> cb(p_callback); | |
| 136 m_data._enumerate_var(cb); | |
| 137 } | |
| 138 | |
| 139 | |
| 140 t_size get_count() const throw() {return m_data.get_count();} | |
| 141 size_t size() const throw() { return get_count(); } | |
| 142 | |
| 143 void remove_all() throw() {m_data.remove_all();} | |
| 144 void clear() throw() { remove_all(); } | |
| 145 | |
| 146 template<typename t_source> | |
| 147 void overwrite(const t_source & p_source) { | |
| 148 __map_overwrite_wrapper<t_self> wrapper(*this); | |
| 149 p_source.enumerate(wrapper); | |
| 150 } | |
| 151 | |
| 152 //backwards compatibility method wrappers | |
| 153 template<typename _t_key> bool exists(const _t_key & p_key) const {return have_item(p_key);} | |
| 154 | |
| 155 | |
| 156 template<typename _t_key> bool get_first(_t_key & p_out) const { | |
| 157 t_retrieve_key<_t_key> wrap(p_out); | |
| 158 return m_data.get_first(wrap); | |
| 159 } | |
| 160 | |
| 161 template<typename _t_key> bool get_last(_t_key & p_out) const { | |
| 162 t_retrieve_key<_t_key> wrap(p_out); | |
| 163 return m_data.get_last(wrap); | |
| 164 } | |
| 165 | |
| 166 | |
| 167 map_t() {} | |
| 168 map_t( const t_self & other ) : m_data( other.m_data ) {} | |
| 169 map_t( t_self && other ) : m_data( std::move(other.m_data) ) {} | |
| 170 const t_self & operator=( const t_self & other ) {m_data = other.m_data; return *this;} | |
| 171 const t_self & operator=( t_self && other ) { m_data = std::move(other.m_data); return *this; } | |
| 172 | |
| 173 void move_from(t_self & other) { | |
| 174 m_data.move_from( other.m_data ); | |
| 175 } | |
| 176 | |
| 177 private: | |
| 178 template<typename _t_key> | |
| 179 struct t_retrieve_key { | |
| 180 typedef t_retrieve_key<_t_key> t_self; | |
| 181 t_retrieve_key(_t_key & p_key) : m_key(p_key) {} | |
| 182 template<typename t_what> const t_self & operator=(const t_what & p_what) {m_key = p_what.m_key; return *this;} | |
| 183 _t_key & m_key; | |
| 184 }; | |
| 185 template<typename _t_key> | |
| 186 struct t_search_query { | |
| 187 t_search_query(const _t_key & p_key) : m_key(p_key) {} | |
| 188 _t_key const & m_key; | |
| 189 }; | |
| 190 template<typename _t_key,typename _t_value> | |
| 191 struct t_search_set { | |
| 192 t_search_set(const _t_key & p_key, const _t_value & p_value) : m_key(p_key), m_value(p_value) {} | |
| 193 | |
| 194 _t_key const & m_key; | |
| 195 _t_value const & m_value; | |
| 196 }; | |
| 197 | |
| 198 struct t_storage { | |
| 199 const t_storage_key m_key; | |
| 200 t_storage_value m_value; | |
| 201 | |
| 202 template<typename _t_key> | |
| 203 t_storage(t_search_query<_t_key> const & p_source) : m_key(p_source.m_key), m_value() {} | |
| 204 | |
| 205 template<typename _t_key,typename _t_value> | |
| 206 t_storage(t_search_set<_t_key,_t_value> const & p_source) : m_key(p_source.m_key), m_value(p_source.m_value) {} | |
| 207 | |
| 208 static bool equals(const t_storage & v1, const t_storage & v2) {return v1.m_key == v2.m_key && v1.m_value == v2.m_value;} | |
| 209 bool operator==(const t_storage & other) const {return equals(*this,other);} | |
| 210 bool operator!=(const t_storage & other) const {return !equals(*this,other);} | |
| 211 }; | |
| 212 | |
| 213 class comparator_wrapper { | |
| 214 public: | |
| 215 template<typename t1,typename t2> | |
| 216 inline static int compare(const t1 & p_item1,const t2 & p_item2) { | |
| 217 return t_comparator::compare(p_item1.m_key,p_item2.m_key); | |
| 218 } | |
| 219 }; | |
| 220 | |
| 221 template<typename t_callback> | |
| 222 class enumeration_wrapper { | |
| 223 public: | |
| 224 enumeration_wrapper(t_callback & p_callback) : m_callback(p_callback) {} | |
| 225 void operator()(const t_storage & p_item) {m_callback(p_item.m_key,p_item.m_value);} | |
| 226 private: | |
| 227 t_callback & m_callback; | |
| 228 }; | |
| 229 | |
| 230 template<typename t_callback> | |
| 231 class enumeration_wrapper_var { | |
| 232 public: | |
| 233 enumeration_wrapper_var(t_callback & p_callback) : m_callback(p_callback) {} | |
| 234 void operator()(t_storage & p_item) {m_callback(implicit_cast<t_storage_key const&>(p_item.m_key),p_item.m_value);} | |
| 235 private: | |
| 236 t_callback & m_callback; | |
| 237 }; | |
| 238 | |
| 239 typedef avltree_t<t_storage,comparator_wrapper> t_content; | |
| 240 | |
| 241 t_content m_data; | |
| 242 public: | |
| 243 typedef traits_t<t_content> traits; | |
| 244 typedef typename t_content::const_iterator const_iterator; | |
| 245 typedef typename t_content::iterator iterator; | |
| 246 | |
| 247 typedef typename t_content::forward_iterator forward_iterator; | |
| 248 typedef typename t_content::forward_const_iterator forward_const_iterator; | |
| 249 | |
| 250 iterator first() throw() {return m_data._first_var();} | |
| 251 iterator last() throw() {return m_data._last_var();} | |
| 252 const_iterator first() const throw() {return m_data.first();} | |
| 253 const_iterator last() const throw() {return m_data.last();} | |
| 254 const_iterator cfirst() const throw() {return m_data.first();} | |
| 255 const_iterator clast() const throw() {return m_data.last();} | |
| 256 | |
| 257 forward_iterator begin() { return first(); } | |
| 258 forward_const_iterator begin() const { return first(); } | |
| 259 forward_iterator end() { return forward_iterator(); } | |
| 260 forward_const_iterator end() const { return forward_const_iterator(); } | |
| 261 | |
| 262 template<typename _t_key> iterator find(const _t_key & key) {return m_data.find(t_search_query<_t_key>(key));} | |
| 263 template<typename _t_key> const_iterator find(const _t_key & key) const {return m_data.find(t_search_query<_t_key>(key));} | |
| 264 | |
| 265 static bool equals(const t_self & v1, const t_self & v2) { | |
| 266 return t_content::equals(v1.m_data,v2.m_data); | |
| 267 } | |
| 268 bool operator==(const t_self & other) const {return equals(*this,other);} | |
| 269 bool operator!=(const t_self & other) const {return !equals(*this,other);} | |
| 270 | |
| 271 bool remove(iterator const& iter) { | |
| 272 PFC_ASSERT(iter.is_valid()); | |
| 273 return m_data.remove(iter); | |
| 274 //should never return false unless there's a bug in calling code | |
| 275 } | |
| 276 bool remove(const_iterator const& iter) { | |
| 277 PFC_ASSERT(iter.is_valid()); | |
| 278 return m_data.remove(iter); | |
| 279 //should never return false unless there's a bug in calling code | |
| 280 } | |
| 281 }; | |
| 282 } |
