dictionary.hpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*************************************************************************
  2. *
  3. * Copyright 2019 Realm Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. **************************************************************************/
  18. #ifndef REALM_DICTIONARY_HPP
  19. #define REALM_DICTIONARY_HPP
  20. #include <realm/collection.hpp>
  21. #include <realm/obj.hpp>
  22. #include <realm/mixed.hpp>
  23. #include <realm/array_mixed.hpp>
  24. #include <realm/dictionary_cluster_tree.hpp>
  25. namespace realm {
  26. class DictionaryClusterTree;
  27. class Dictionary final : public CollectionBaseImpl<CollectionBase> {
  28. public:
  29. using Base = CollectionBaseImpl<CollectionBase>;
  30. class Iterator;
  31. Dictionary() {}
  32. ~Dictionary();
  33. Dictionary(const Obj& obj, ColKey col_key);
  34. Dictionary(const Dictionary& other)
  35. : Base(static_cast<const Base&>(other))
  36. , m_key_type(other.m_key_type)
  37. {
  38. *this = other;
  39. }
  40. Dictionary& operator=(const Dictionary& other);
  41. bool operator==(const Dictionary& other) const noexcept
  42. {
  43. return CollectionBaseImpl<CollectionBase>::operator==(other);
  44. }
  45. DataType get_key_data_type() const;
  46. DataType get_value_data_type() const;
  47. // Overriding members of CollectionBase:
  48. std::unique_ptr<CollectionBase> clone_collection() const;
  49. size_t size() const final;
  50. bool is_null(size_t ndx) const final;
  51. Mixed get_any(size_t ndx) const final;
  52. std::pair<Mixed, Mixed> get_pair(size_t ndx) const;
  53. size_t find_any(Mixed value) const final;
  54. Mixed min(size_t* return_ndx = nullptr) const final;
  55. Mixed max(size_t* return_ndx = nullptr) const final;
  56. Mixed sum(size_t* return_cnt = nullptr) const final;
  57. Mixed avg(size_t* return_cnt = nullptr) const final;
  58. void sort(std::vector<size_t>& indices, bool ascending = true) const final;
  59. void distinct(std::vector<size_t>& indices, util::Optional<bool> sort_order = util::none) const final;
  60. void create();
  61. // first points to inserted/updated element.
  62. // second is true if the element was inserted
  63. std::pair<Iterator, bool> insert(Mixed key, Mixed value);
  64. std::pair<Iterator, bool> insert(Mixed key, const Obj& obj);
  65. // throws std::out_of_range if key is not found
  66. Mixed get(Mixed key) const;
  67. // Noexcept version
  68. util::Optional<Mixed> try_get(Mixed key) const noexcept;
  69. // adds entry if key is not found
  70. const Mixed operator[](Mixed key);
  71. bool contains(Mixed key);
  72. Iterator find(Mixed key);
  73. void erase(Mixed key);
  74. void erase(Iterator it);
  75. void nullify(Mixed);
  76. void clear() final;
  77. template <class T>
  78. void for_all_values(T&& f)
  79. {
  80. if (m_clusters) {
  81. ArrayMixed leaf(m_obj.get_alloc());
  82. // Iterate through cluster and call f on each value
  83. auto trv_func = [&leaf, &f](const Cluster* cluster) {
  84. size_t e = cluster->node_size();
  85. cluster->init_leaf(DictionaryClusterTree::s_values_col, &leaf);
  86. for (size_t i = 0; i < e; i++) {
  87. f(leaf.get(i));
  88. }
  89. // Continue
  90. return false;
  91. };
  92. m_clusters->traverse(trv_func);
  93. }
  94. }
  95. template <class T, class Func>
  96. void for_all_keys(Func&& f)
  97. {
  98. if (m_clusters) {
  99. typename ColumnTypeTraits<T>::cluster_leaf_type leaf(m_obj.get_alloc());
  100. ColKey col = m_clusters->get_keys_column_key();
  101. // Iterate through cluster and call f on each value
  102. auto trv_func = [&leaf, &f, col](const Cluster* cluster) {
  103. size_t e = cluster->node_size();
  104. cluster->init_leaf(col, &leaf);
  105. for (size_t i = 0; i < e; i++) {
  106. f(leaf.get(i));
  107. }
  108. // Continue
  109. return false;
  110. };
  111. m_clusters->traverse(trv_func);
  112. }
  113. }
  114. Iterator begin() const;
  115. Iterator end() const;
  116. private:
  117. friend class DictionaryAggregate;
  118. mutable DictionaryClusterTree* m_clusters = nullptr;
  119. DataType m_key_type = type_String;
  120. bool init_from_parent() const final;
  121. Mixed do_get(const ClusterNode::State&) const;
  122. std::pair<Mixed, Mixed> do_get_pair(const ClusterNode::State&) const;
  123. friend struct CollectionIterator<Dictionary>;
  124. };
  125. class Dictionary::Iterator : public ClusterTree::Iterator {
  126. public:
  127. typedef std::forward_iterator_tag iterator_category;
  128. typedef std::pair<const Mixed, Mixed> value_type;
  129. typedef ptrdiff_t difference_type;
  130. typedef const value_type* pointer;
  131. typedef const value_type& reference;
  132. value_type operator*() const;
  133. Iterator& operator++()
  134. {
  135. return static_cast<Iterator&>(ClusterTree::Iterator::operator++());
  136. }
  137. Iterator& operator+=(ptrdiff_t adj)
  138. {
  139. return static_cast<Iterator&>(ClusterTree::Iterator::operator+=(adj));
  140. }
  141. Iterator operator+(ptrdiff_t n) const
  142. {
  143. Iterator ret(*this);
  144. ret += n;
  145. return ret;
  146. }
  147. private:
  148. friend class Dictionary;
  149. using ClusterTree::Iterator::get_position;
  150. DataType m_key_type;
  151. Iterator(const Dictionary* dict, size_t pos);
  152. };
  153. inline std::pair<Dictionary::Iterator, bool> Dictionary::insert(Mixed key, const Obj& obj)
  154. {
  155. return insert(key, Mixed(obj.get_link()));
  156. }
  157. inline std::unique_ptr<CollectionBase> Dictionary::clone_collection() const
  158. {
  159. return m_obj.get_dictionary_ptr(m_col_key);
  160. }
  161. } // namespace realm
  162. #endif /* SRC_REALM_DICTIONARY_HPP_ */