1 ////////////////////////////////////////////////////////////////////////////
3 // Copyright 2015 Realm Inc.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 ////////////////////////////////////////////////////////////////////////////
19 #ifndef REALM_OS_LIST_HPP
20 #define REALM_OS_LIST_HPP
22 #include "collection_notifications.hpp"
23 #include "impl/collection_notifier.hpp"
24 #include "property.hpp"
26 #include <realm/link_view_fwd.hpp>
27 #include <realm/row.hpp>
28 #include <realm/table_ref.hpp>
39 template <typename T> class ThreadSafeReference;
48 List(std::shared_ptr<Realm> r, Table& parent_table, size_t col, size_t row);
49 List(std::shared_ptr<Realm> r, LinkViewRef l) noexcept;
50 List(std::shared_ptr<Realm> r, TableRef l) noexcept;
54 List& operator=(const List&);
56 List& operator=(List&&);
58 const std::shared_ptr<Realm>& get_realm() const { return m_realm; }
59 Query get_query() const;
60 size_t get_origin_row_index() const;
62 // Get the type of the values contained in this List
63 PropertyType get_type() const;
65 // Get the ObjectSchema of the values in this List
66 // Only valid if get_type() returns PropertyType::Object
67 ObjectSchema const& get_object_schema() const;
69 bool is_valid() const;
70 void verify_attached() const;
71 void verify_in_transaction() const;
75 void move(size_t source_ndx, size_t dest_ndx);
76 void remove(size_t list_ndx);
78 void swap(size_t ndx1, size_t ndx2);
79 void delete_at(size_t list_ndx);
82 template<typename T = RowExpr>
83 T get(size_t row_ndx) const;
85 size_t find(T const& value) const;
87 // Find the index in the List of the first row matching the query
88 size_t find(Query&& query) const;
93 void insert(size_t list_ndx, T value);
95 void set(size_t row_ndx, T value);
97 Results sort(SortDescriptor order) const;
98 Results sort(std::vector<std::pair<std::string, bool>> const& keypaths) const;
99 Results filter(Query q) const;
101 // Return a Results representing a live view of this List.
102 Results as_results() const;
104 // Return a Results representing a snapshot of this List.
105 Results snapshot() const;
107 // Get the min/max/average/sum of the given column
108 // All but sum() returns none when there are zero matching rows
110 // Throws UnsupportedColumnTypeException for sum/average on timestamp or non-numeric column
111 // Throws OutOfBoundsIndexException for an out-of-bounds column
112 util::Optional<Mixed> max(size_t column=0);
113 util::Optional<Mixed> min(size_t column=0);
114 util::Optional<double> average(size_t column=0);
115 Mixed sum(size_t column=0);
117 bool operator==(List const& rgt) const noexcept;
119 NotificationToken add_notification_callback(CollectionChangeCallback cb) &;
121 template<typename Context>
122 auto get(Context&, size_t row_ndx) const;
123 template<typename T, typename Context>
124 size_t find(Context&, T&& value) const;
126 template<typename T, typename Context>
127 void add(Context&, T&& value, bool update=false);
128 template<typename T, typename Context>
129 void insert(Context&, size_t list_ndx, T&& value, bool update=false);
130 template<typename T, typename Context>
131 void set(Context&, size_t row_ndx, T&& value, bool update=false);
133 // Replace the values in this list with the values from an enumerable object
134 template<typename T, typename Context>
135 void assign(Context&, T&& value, bool update=false);
137 // The List object has been invalidated (due to the Realm being invalidated,
138 // or the containing object being deleted)
139 // All non-noexcept functions can throw this
140 struct InvalidatedException : public std::logic_error {
141 InvalidatedException() : std::logic_error("Access to invalidated List object") {}
144 // The input index parameter was out of bounds
145 struct OutOfBoundsIndexException : public std::out_of_range {
146 OutOfBoundsIndexException(size_t r, size_t c);
152 friend ThreadSafeReference<List>;
154 std::shared_ptr<Realm> m_realm;
155 mutable const ObjectSchema* m_object_schema = nullptr;
156 LinkViewRef m_link_view;
158 _impl::CollectionNotifier::Handle<_impl::CollectionNotifier> m_notifier;
160 void verify_valid_row(size_t row_ndx, bool insertion = false) const;
161 void validate(RowExpr) const;
163 template<typename Fn>
164 auto dispatch(Fn&&) const;
166 size_t to_table_ndx(size_t row) const noexcept;
168 friend struct std::hash<List>;
171 template<typename Fn>
172 auto List::dispatch(Fn&& fn) const
174 return switch_on_type(get_type(), std::forward<Fn>(fn));
177 template<typename Context>
178 auto List::get(Context& ctx, size_t row_ndx) const
180 return dispatch([&](auto t) { return ctx.box(this->get<std::decay_t<decltype(*t)>>(row_ndx)); });
183 template<typename T, typename Context>
184 size_t List::find(Context& ctx, T&& value) const
186 return dispatch([&](auto t) { return this->find(ctx.template unbox<std::decay_t<decltype(*t)>>(value)); });
189 template<typename T, typename Context>
190 void List::add(Context& ctx, T&& value, bool update)
192 dispatch([&](auto t) { this->add(ctx.template unbox<std::decay_t<decltype(*t)>>(value, true, update)); });
195 template<typename T, typename Context>
196 void List::insert(Context& ctx, size_t list_ndx, T&& value, bool update)
198 dispatch([&](auto t) { this->insert(list_ndx, ctx.template unbox<std::decay_t<decltype(*t)>>(value, true, update)); });
201 template<typename T, typename Context>
202 void List::set(Context& ctx, size_t row_ndx, T&& value, bool update)
204 dispatch([&](auto t) { this->set(row_ndx, ctx.template unbox<std::decay_t<decltype(*t)>>(value, true, update)); });
207 template<typename T, typename Context>
208 void List::assign(Context& ctx, T&& values, bool update)
210 if (ctx.is_same_list(*this, values))
214 if (ctx.is_null(values))
217 ctx.enumerate_list(values, [&](auto&& element) {
218 this->add(ctx, element, update);
224 template<> struct hash<realm::List> {
225 size_t operator()(realm::List const&) const;
229 #endif // REALM_OS_LIST_HPP