1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef API_BASE_CONTAINERS_FLAT_MAP_H 17 #define API_BASE_CONTAINERS_FLAT_MAP_H 18 19 #include <base/containers/iterator.h> 20 #include <base/containers/unordered_map.h> 21 #include <base/containers/vector.h> 22 #include <base/util/algorithm.h> 23 24 BASE_BEGIN_NAMESPACE() 25 template<typename KeyType, typename ValueType, typename Compare> 26 class flat_map; 27 28 namespace Detail { 29 template<typename KeyIter, typename ValueIter, typename ValueConstIter> 30 class Iterator { 31 public: 32 template<typename T> 33 using IterReference = decltype(*BASE_NS::declval<T&>()); 34 using ConstIterator = Iterator<KeyIter, ValueConstIter, ValueConstIter>; 35 using reference = BASE_NS::pair<IterReference<KeyIter>, IterReference<ValueIter>>; 36 using difference_type = ptrdiff_t; 37 38 private: 39 class RefWrapper { 40 public: RefWrapper(const reference & ref)41 explicit RefWrapper(const reference& ref) noexcept : ref_ { ref } {} 42 43 const reference* operator->() const noexcept 44 { 45 return &ref_; 46 } 47 48 private: 49 reference ref_; 50 }; 51 52 public: 53 using pointer = RefWrapper; 54 55 Iterator() = default; 56 Iterator(KeyIter key,ValueIter value)57 Iterator(KeyIter key, ValueIter value) noexcept : keyIter_(BASE_NS::move(key)), valueIter_(BASE_NS::move(value)) {} 58 59 reference operator*() const 60 { 61 return reference { *keyIter_, *valueIter_ }; 62 } 63 64 pointer operator->() const 65 { 66 return pointer { this->operator*() }; 67 } 68 69 Iterator& operator++() 70 { 71 ++keyIter_; 72 ++valueIter_; 73 return *this; 74 } 75 76 Iterator operator++(int) 77 { 78 auto prev = *this; 79 ++*this; 80 return prev; 81 } 82 83 Iterator& operator--() 84 { 85 --keyIter_; 86 --valueIter_; 87 return *this; 88 } 89 90 Iterator operator--(int) 91 { 92 auto prev = *this; 93 --*this; 94 return prev; 95 } 96 97 Iterator& operator+=(const difference_type offset) 98 { 99 keyIter_ += offset; 100 valueIter_ += offset; 101 return *this; 102 } 103 104 Iterator& operator-=(const difference_type offset) 105 { 106 keyIter_ -= offset; 107 valueIter_ -= offset; 108 return *this; 109 } 110 111 Iterator operator+(const difference_type offset) 112 { 113 auto prev = *this; 114 prev += offset; 115 return prev; 116 } 117 118 Iterator operator-(const difference_type offset) 119 { 120 auto prev = *this; 121 prev -= offset; 122 return prev; 123 } 124 125 bool operator==(const Iterator& _Right) const 126 { 127 return keyIter_ == _Right.keyIter_; 128 } 129 130 bool operator!=(const Iterator& _Right) const 131 { 132 return keyIter_ != _Right.keyIter_; 133 } 134 135 template<typename T = ValueConstIter, BASE_NS::enable_if_t<!BASE_NS::is_same_v<ValueIter, T>, bool> = true> ConstIterator()136 operator ConstIterator() const 137 { 138 return ConstIterator(keyIter_, valueIter_); 139 } 140 141 private: 142 template<typename KeyType, typename ValueType, typename Compare> 143 friend class BASE_NS::flat_map; 144 KeyIter keyIter_; 145 ValueIter valueIter_; 146 }; 147 } // namespace Detail 148 149 template<typename KeyType, typename ValueType, typename Compare = Less<KeyType>> 150 class flat_map { 151 public: 152 using key_type = KeyType; 153 using mapped_type = ValueType; 154 using value_type = BASE_NS::pair<key_type, mapped_type>; 155 using difference_type = ptrdiff_t; 156 using reference = BASE_NS::pair<const key_type&, mapped_type&>; 157 using const_reference = BASE_NS::pair<const key_type&, const mapped_type&>; 158 159 using iterator = Detail::Iterator<BASE_NS::const_iterator<BASE_NS::vector<key_type>>, 160 BASE_NS::iterator<BASE_NS::vector<mapped_type>>, BASE_NS::const_iterator<BASE_NS::vector<mapped_type>>>; 161 using const_iterator = Detail::Iterator<BASE_NS::const_iterator<BASE_NS::vector<key_type>>, 162 BASE_NS::const_iterator<BASE_NS::vector<mapped_type>>, BASE_NS::const_iterator<BASE_NS::vector<mapped_type>>>; 163 164 flat_map() = default; 165 166 template<class InputIter> flat_map(InputIter first,InputIter last)167 flat_map(InputIter first, InputIter last) 168 { 169 insert(first, last); 170 } 171 flat_map(std::initializer_list<value_type> init)172 flat_map(std::initializer_list<value_type> init) : flat_map(init.begin(), init.end()) {} 173 174 // Element access 175 mapped_type& operator[](const key_type& key) 176 { 177 return try_emplace(key).first->second; 178 } 179 180 mapped_type& operator[](key_type&& key) 181 { 182 return try_emplace(BASE_NS::move(key)).first->second; 183 } 184 185 template<typename Key> 186 mapped_type& operator[](Key&& key) 187 { 188 return try_emplace(BASE_NS::forward<Key>(key)).first->second; 189 } 190 191 // Iterators begin()192 iterator begin() noexcept 193 { 194 return iterator { keys_.cbegin(), values_.begin() }; 195 } 196 begin()197 const_iterator begin() const noexcept 198 { 199 return const_iterator { keys_.cbegin(), values_.begin() }; 200 } 201 cbegin()202 const_iterator cbegin() const noexcept 203 { 204 return const_iterator { keys_.cbegin(), values_.begin() }; 205 } 206 end()207 iterator end() noexcept 208 { 209 return iterator { keys_.cend(), values_.end() }; 210 } 211 end()212 const_iterator end() const noexcept 213 { 214 return const_iterator { keys_.cend(), values_.end() }; 215 } 216 cend()217 const_iterator cend() const noexcept 218 { 219 return const_iterator { keys_.cend(), values_.end() }; 220 } 221 222 // Capacity empty()223 bool empty() const noexcept 224 { 225 return keys_.empty(); 226 } 227 size()228 size_t size() const noexcept 229 { 230 return keys_.size(); 231 } 232 233 // Modifiers 234 template<class... Args> emplace(Args &&...args)235 BASE_NS::pair<iterator, bool> emplace(Args&&... args) 236 { 237 auto predicate = Predicate {}; 238 auto t = value_type(BASE_NS::forward<Args>(args)...); 239 const auto pos = LowerBound(keys_.cbegin(), keys_.cend(), t.first, predicate); 240 if ((pos == keys_.cend()) || predicate(t.first, *pos)) { 241 const auto index = pos - keys_.cbegin(); 242 keys_.insert(pos, (BASE_NS::move(t.first))); 243 values_.insert(values_.cbegin() + index, BASE_NS::move(t.second)); 244 return { begin() + index, true }; 245 } 246 return { begin() + (pos - keys_.begin()), false }; 247 } 248 249 template<typename Key, typename... Args> try_emplace(Key && key,Args &&...args)250 BASE_NS::pair<iterator, bool> try_emplace(Key&& key, Args&&... args) 251 { 252 auto predicate = Predicate {}; 253 const auto pos = LowerBound(keys_.cbegin(), keys_.cend(), key, predicate); 254 if ((pos == keys_.cend()) || predicate(key, *pos)) { 255 const auto index = pos - keys_.cbegin(); 256 keys_.insert(pos, key_type(BASE_NS::forward<Key>(key))); 257 values_.insert(values_.cbegin() + index, mapped_type(BASE_NS::forward<Args>(args)...)); 258 return { begin() + index, true }; 259 } 260 return { begin() + (pos - keys_.begin()), false }; 261 } 262 insert(const value_type & value)263 BASE_NS::pair<iterator, bool> insert(const value_type& value) 264 { 265 return emplace(value); 266 } 267 insert(value_type && value)268 BASE_NS::pair<iterator, bool> insert(value_type&& value) 269 { 270 return emplace(BASE_NS::move(value)); 271 } 272 273 template<class InputIt> insert(InputIt first,InputIt last)274 void insert(InputIt first, InputIt last) 275 { 276 for (; first != last; ++first) { 277 insert(*first); 278 } 279 } 280 281 template<class P> insert(P && x)282 BASE_NS::pair<iterator, bool> insert(P&& x) 283 { 284 return emplace(BASE_NS::forward<P>(x)); 285 } 286 287 template<class M> insert_or_assign(const key_type & key,M && obj)288 BASE_NS::pair<iterator, bool> insert_or_assign(const key_type& key, M&& obj) 289 { 290 auto predicate = Predicate {}; 291 const auto pos = LowerBound(keys_.begin(), keys_.end(), key, predicate); 292 const auto index = pos - keys_.begin(); 293 if ((pos == keys_.end()) || predicate(key, *pos)) { 294 keys_.insert(pos, key); 295 values_.insert(values_.cbegin() + index, mapped_type(BASE_NS::forward<M>(obj))); 296 return { begin() + index, true }; 297 } 298 *(values_.begin() + index) = BASE_NS::forward<M>(obj); 299 return { begin() + index, false }; 300 } 301 302 template<class M> insert_or_assign(key_type && key,M && obj)303 BASE_NS::pair<iterator, bool> insert_or_assign(key_type&& key, M&& obj) 304 { 305 auto predicate = Predicate {}; 306 const auto pos = LowerBound(keys_.begin(), keys_.end(), key, predicate); 307 const auto index = pos - keys_.begin(); 308 if ((pos == keys_.end()) || predicate(key, *pos)) { 309 keys_.insert(pos, BASE_NS::move(key)); 310 values_.insert(values_.cbegin() + index, mapped_type(BASE_NS::forward<M>(obj))); 311 return { begin() + index, true }; 312 } 313 *(values_.begin() + index) = BASE_NS::forward<M>(obj); 314 return { begin() + index, false }; 315 } 316 317 template<class K, class M> insert_or_assign(K && k,M && obj)318 BASE_NS::pair<iterator, bool> insert_or_assign(K&& k, M&& obj) 319 { 320 auto predicate = Predicate {}; 321 const auto pos = LowerBound(keys_.begin(), keys_.end(), BASE_NS::forward<K>(k), predicate); 322 const auto index = pos - keys_.begin(); 323 if ((pos == keys_.end()) || predicate(BASE_NS::forward<K>(k), *pos)) { 324 keys_.insert(pos, BASE_NS::forward<K>(k)); 325 values_.insert(values_.cbegin() + index, mapped_type(BASE_NS::forward<M>(obj))); 326 return { begin() + index, true }; 327 } 328 *(values_.begin() + index) = BASE_NS::forward<M>(obj); 329 return { begin() + index, false }; 330 } 331 erase(iterator pos)332 iterator erase(iterator pos) 333 { 334 keys_.erase(pos.keyIter_); 335 values_.erase(pos.valueIter_); 336 return pos; 337 } 338 erase(const_iterator pos)339 iterator erase(const_iterator pos) 340 { 341 keys_.erase(pos.keyIter_); 342 values_.erase(pos.valueIter_); 343 return pos; 344 } 345 346 template<typename Key> erase(const Key & key)347 size_t erase(const Key& key) 348 { 349 auto predicate = Predicate {}; 350 auto pos = LowerBound(keys_.cbegin(), keys_.cend(), key, predicate); 351 if ((pos == keys_.cend()) || predicate(key, *pos)) { 352 return 0u; 353 } 354 auto index = pos - keys_.cbegin(); 355 keys_.erase(pos); 356 values_.erase(values_.cbegin() + index); 357 return 1u; 358 } 359 clear()360 void clear() 361 { 362 keys_.clear(); 363 values_.clear(); 364 } 365 366 // Lookup 367 template<typename Key> find(const Key & key)368 iterator find(const Key& key) noexcept 369 { 370 auto predicate = Predicate {}; 371 auto pos = LowerBound(keys_.cbegin(), keys_.cend(), key, predicate); 372 if ((pos == keys_.cend()) || predicate(key, *pos)) { 373 return end(); 374 } 375 auto index = pos - keys_.cbegin(); 376 return iterator { pos, values_.begin() + index }; 377 } 378 379 template<typename Key> find(const Key & key)380 const_iterator find(const Key& key) const noexcept 381 { 382 auto predicate = Predicate {}; 383 auto pos = LowerBound(keys_.cbegin(), keys_.cend(), key, predicate); 384 if ((pos == keys_.cend()) || predicate(key, *pos)) { 385 return end(); 386 } 387 auto index = pos - keys_.cbegin(); 388 return const_iterator { pos, values_.begin() + index }; 389 } 390 391 private: 392 struct Predicate : Compare { operatorPredicate393 auto operator()(const key_type& lhs, const key_type& rhs) 394 { 395 return Compare::operator()(lhs, rhs); 396 } operatorPredicate397 auto operator()(const key_type& lhs, const value_type& rhs) 398 { 399 return Compare::operator()(lhs, rhs.first); 400 } operatorPredicate401 auto operator()(const value_type& lhs, const key_type& rhs) 402 { 403 return Compare::operator()(lhs.first, rhs); 404 } operatorPredicate405 auto operator()(const value_type& lhs, const value_type& rhs) 406 { 407 return Compare::operator()(lhs.first, rhs.first); 408 } 409 }; 410 BASE_NS::vector<key_type> keys_; 411 BASE_NS::vector<mapped_type> values_; 412 }; 413 414 template<typename Container> 415 bool operator!=( 416 const typename BASE_NS::iterator<Container>& lhs, const typename BASE_NS::const_iterator<Container>& rhs) noexcept 417 { 418 return lhs.ptr() != rhs.ptr(); 419 } 420 421 template<typename Container> 422 bool operator!=( 423 const typename BASE_NS::const_iterator<Container>& lhs, const typename BASE_NS::iterator<Container>& rhs) noexcept 424 { 425 return lhs.ptr() != rhs.ptr(); 426 } 427 BASE_END_NAMESPACE() 428 #endif // API_BASE_CONTAINERS_FLAT_MAP_H 429