You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

map.h 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * Frozen
  3. * Copyright 2016 QuarksLab
  4. *
  5. * Licensed to the Apache Software Foundation (ASF) under one
  6. * or more contributor license agreements. See the NOTICE file
  7. * distributed with this work for additional information
  8. * regarding copyright ownership. The ASF licenses this file
  9. * to you under the Apache License, Version 2.0 (the
  10. * "License"); you may not use this file except in compliance
  11. * with the License. You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing,
  16. * software distributed under the License is distributed on an
  17. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  18. * KIND, either express or implied. See the License for the
  19. * specific language governing permissions and limitations
  20. * under the License.
  21. */
  22. #ifndef FROZEN_LETITGO_MAP_H
  23. #define FROZEN_LETITGO_MAP_H
  24. #include "frozen/bits/algorithms.h"
  25. #include "frozen/bits/basic_types.h"
  26. #include "frozen/bits/constexpr_assert.h"
  27. #include "frozen/bits/exceptions.h"
  28. #include "frozen/bits/version.h"
  29. #include <utility>
  30. namespace frozen {
  31. namespace impl {
  32. template <class Comparator> class CompareKey {
  33. Comparator const comparator_;
  34. public:
  35. constexpr CompareKey(Comparator const &comparator)
  36. : comparator_(comparator) {}
  37. template <class Key, class Value>
  38. constexpr int operator()(std::pair<Key, Value> const &self,
  39. std::pair<Key, Value> const &other) const {
  40. return comparator_(std::get<0>(self), std::get<0>(other));
  41. }
  42. template <class Key, class Value>
  43. constexpr int operator()(Key const &self_key,
  44. std::pair<Key, Value> const &other) const {
  45. return comparator_(self_key, std::get<0>(other));
  46. }
  47. template <class Key, class Value>
  48. constexpr int operator()(std::pair<Key, Value> const &self,
  49. Key const &other_key) const {
  50. return comparator_(std::get<0>(self), other_key);
  51. }
  52. template <class Key>
  53. constexpr int operator()(Key const &self_key, Key const &other_key) const {
  54. return comparator_(self_key, other_key);
  55. }
  56. };
  57. } // namespace impl
  58. template <class Key, class Value, std::size_t N, class Compare = std::less<Key>>
  59. class map {
  60. using container_type = bits::carray<std::pair<Key, Value>, N>;
  61. impl::CompareKey<Compare> less_than_;
  62. container_type items_;
  63. public:
  64. using key_type = Key;
  65. using mapped_type = Value;
  66. using value_type = typename container_type::value_type;
  67. using size_type = typename container_type::size_type;
  68. using difference_type = typename container_type::difference_type;
  69. using key_compare = decltype(less_than_);
  70. using reference = typename container_type::reference;
  71. using const_reference = typename container_type::const_reference;
  72. using pointer = typename container_type::pointer;
  73. using const_pointer = typename container_type::const_pointer;
  74. using iterator = typename container_type::iterator;
  75. using const_iterator = typename container_type::const_iterator;
  76. using reverse_iterator = typename container_type::reverse_iterator;
  77. using const_reverse_iterator =
  78. typename container_type::const_reverse_iterator;
  79. public:
  80. /* constructors */
  81. constexpr map(container_type items, Compare const &compare)
  82. : less_than_{compare}
  83. , items_{bits::quicksort(items, less_than_)} {}
  84. explicit constexpr map(container_type items)
  85. : map{items, Compare{}} {}
  86. constexpr map(std::initializer_list<value_type> items, Compare const &compare)
  87. : map{container_type {items}, compare} {
  88. constexpr_assert(items.size() == N, "Inconsistent initializer_list size and type size argument");
  89. }
  90. constexpr map(std::initializer_list<value_type> items)
  91. : map{items, Compare{}} {}
  92. /* element access */
  93. constexpr Value const& at(Key const &key) const {
  94. return at_impl(*this, key);
  95. }
  96. constexpr Value& at(Key const &key) {
  97. return at_impl(*this, key);
  98. }
  99. /* iterators */
  100. constexpr iterator begin() { return items_.begin(); }
  101. constexpr const_iterator begin() const { return items_.begin(); }
  102. constexpr const_iterator cbegin() const { return items_.cbegin(); }
  103. constexpr iterator end() { return items_.end(); }
  104. constexpr const_iterator end() const { return items_.end(); }
  105. constexpr const_iterator cend() const { return items_.cend(); }
  106. constexpr reverse_iterator rbegin() { return items_.rbegin(); }
  107. constexpr const_reverse_iterator rbegin() const { return items_.rbegin(); }
  108. constexpr const_reverse_iterator crbegin() const { return items_.crbegin(); }
  109. constexpr reverse_iterator rend() { return items_.rend(); }
  110. constexpr const_reverse_iterator rend() const { return items_.rend(); }
  111. constexpr const_reverse_iterator crend() const { return items_.crend(); }
  112. /* capacity */
  113. constexpr bool empty() const { return !N; }
  114. constexpr size_type size() const { return N; }
  115. constexpr size_type max_size() const { return N; }
  116. /* lookup */
  117. constexpr std::size_t count(Key const &key) const {
  118. return bits::binary_search<N>(items_.begin(), key, less_than_);
  119. }
  120. constexpr const_iterator find(Key const &key) const {
  121. return find_impl(*this, key);
  122. }
  123. constexpr iterator find(Key const &key) {
  124. return find_impl(*this, key);
  125. }
  126. constexpr std::pair<const_iterator, const_iterator>
  127. equal_range(Key const &key) const {
  128. return equal_range_impl(*this, key);
  129. }
  130. constexpr std::pair<iterator, iterator> equal_range(Key const &key) {
  131. return equal_range_impl(*this, key);
  132. }
  133. constexpr const_iterator lower_bound(Key const &key) const {
  134. return lower_bound_impl(*this, key);
  135. }
  136. constexpr iterator lower_bound(Key const &key) {
  137. return lower_bound_impl(*this, key);
  138. }
  139. constexpr const_iterator upper_bound(Key const &key) const {
  140. return upper_bound_impl(*this, key);
  141. }
  142. constexpr iterator upper_bound(Key const &key) {
  143. return upper_bound_impl(*this, key);
  144. }
  145. /* observers */
  146. constexpr key_compare key_comp() const { return less_than_; }
  147. constexpr key_compare value_comp() const { return less_than_; }
  148. private:
  149. template <class This>
  150. static inline constexpr auto& at_impl(This&& self, Key const &key) {
  151. auto where = self.lower_bound(key);
  152. if (where != self.end())
  153. return where->second;
  154. else
  155. FROZEN_THROW_OR_ABORT(std::out_of_range("unknown key"));
  156. }
  157. template <class This>
  158. static inline constexpr auto find_impl(This&& self, Key const &key) {
  159. auto where = self.lower_bound(key);
  160. if ((where != self.end()) && !self.less_than_(key, *where))
  161. return where;
  162. else
  163. return self.end();
  164. }
  165. template <class This>
  166. static inline constexpr auto equal_range_impl(This&& self, Key const &key) {
  167. auto lower = self.lower_bound(key);
  168. using lower_t = decltype(lower);
  169. if (lower == self.end())
  170. return std::pair<lower_t, lower_t>{lower, lower};
  171. else
  172. return std::pair<lower_t, lower_t>{lower, lower + 1};
  173. }
  174. template <class This>
  175. static inline constexpr auto lower_bound_impl(This&& self, Key const &key) -> decltype(self.end()) {
  176. auto where = bits::lower_bound<N>(self.items_.begin(), key, self.less_than_);
  177. if ((where != self.end()) && !self.less_than_(key, *where))
  178. return where;
  179. else
  180. return self.end();
  181. }
  182. template <class This>
  183. static inline constexpr auto upper_bound_impl(This&& self, Key const &key) -> decltype(self.end()) {
  184. auto where = bits::lower_bound<N>(self.items_.begin(), key, self.less_than_);
  185. if ((where != self.end()) && !self.less_than_(key, *where))
  186. return where + 1;
  187. else
  188. return self.end();
  189. }
  190. };
  191. template <class Key, class Value, class Compare>
  192. class map<Key, Value, 0, Compare> {
  193. using container_type = bits::carray<std::pair<Key, Value>, 0>;
  194. impl::CompareKey<Compare> less_than_;
  195. public:
  196. using key_type = Key;
  197. using mapped_type = Value;
  198. using value_type = typename container_type::value_type;
  199. using size_type = typename container_type::size_type;
  200. using difference_type = typename container_type::difference_type;
  201. using key_compare = decltype(less_than_);
  202. using reference = typename container_type::reference;
  203. using const_reference = typename container_type::const_reference;
  204. using pointer = typename container_type::pointer;
  205. using const_pointer = typename container_type::const_pointer;
  206. using iterator = pointer;
  207. using const_iterator = const_pointer;
  208. using reverse_iterator = pointer;
  209. using const_reverse_iterator = const_pointer;
  210. public:
  211. /* constructors */
  212. constexpr map(const map &other) = default;
  213. constexpr map(std::initializer_list<value_type>, Compare const &compare)
  214. : less_than_{compare} {}
  215. constexpr map(std::initializer_list<value_type> items)
  216. : map{items, Compare{}} {}
  217. /* element access */
  218. constexpr mapped_type at(Key const &) const {
  219. FROZEN_THROW_OR_ABORT(std::out_of_range("invalid key"));
  220. }
  221. constexpr mapped_type at(Key const &) {
  222. FROZEN_THROW_OR_ABORT(std::out_of_range("invalid key"));
  223. }
  224. /* iterators */
  225. constexpr iterator begin() { return nullptr; }
  226. constexpr const_iterator begin() const { return nullptr; }
  227. constexpr const_iterator cbegin() const { return nullptr; }
  228. constexpr iterator end() { return nullptr; }
  229. constexpr const_iterator end() const { return nullptr; }
  230. constexpr const_iterator cend() const { return nullptr; }
  231. constexpr reverse_iterator rbegin() { return nullptr; }
  232. constexpr const_reverse_iterator rbegin() const { return nullptr; }
  233. constexpr const_reverse_iterator crbegin() const { return nullptr; }
  234. constexpr reverse_iterator rend() { return nullptr; }
  235. constexpr const_reverse_iterator rend() const { return nullptr; }
  236. constexpr const_reverse_iterator crend() const { return nullptr; }
  237. /* capacity */
  238. constexpr bool empty() const { return true; }
  239. constexpr size_type size() const { return 0; }
  240. constexpr size_type max_size() const { return 0; }
  241. /* lookup */
  242. constexpr std::size_t count(Key const &) const { return 0; }
  243. constexpr const_iterator find(Key const &) const { return end(); }
  244. constexpr iterator find(Key const &) { return end(); }
  245. constexpr std::pair<const_iterator, const_iterator>
  246. equal_range(Key const &) const {
  247. return {end(), end()};
  248. }
  249. constexpr std::pair<iterator, iterator>
  250. equal_range(Key const &) {
  251. return {end(), end()};
  252. }
  253. constexpr const_iterator lower_bound(Key const &) const { return end(); }
  254. constexpr iterator lower_bound(Key const &) { return end(); }
  255. constexpr const_iterator upper_bound(Key const &) const { return end(); }
  256. constexpr iterator upper_bound(Key const &) { return end(); }
  257. /* observers */
  258. constexpr key_compare key_comp() const { return less_than_; }
  259. constexpr key_compare value_comp() const { return less_than_; }
  260. };
  261. template <typename T, typename U>
  262. constexpr auto make_map(bits::ignored_arg = {}/* for consistency with the initializer below for N = 0*/) {
  263. return map<T, U, 0>{};
  264. }
  265. template <typename T, typename U, std::size_t N>
  266. constexpr auto make_map(std::pair<T, U> const (&items)[N]) {
  267. return map<T, U, N>{items};
  268. }
  269. } // namespace frozen
  270. #endif