• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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