Realm C++ SDK Version v2.2.0

managed_dictionary.hpp

1
2//
3// Copyright 2024 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//
18
19#ifndef CPPREALM_MANAGED_DICTIONARY_HPP
20#define CPPREALM_MANAGED_DICTIONARY_HPP
21
22#include <cpprealm/accessors.hpp>
23#include <cpprealm/macros.hpp>
24#include <cpprealm/notifications.hpp>
25#include <cpprealm/observation.hpp>
26#include <cpprealm/rbool.hpp>
27
28namespace realm {
29
30 template<typename mapped_type>
31 struct box_base {
33 const std::string &key,
35 : m_backing_map(std::move(backing_map)), m_key(key), m_realm(r) {}
36
37 box_base(rbool* query,
39 const std::string &key,
40 const internal::bridge::realm &r) {
41 m_rbool_query = query;
42 m_col_key = column_key;
43 m_key = key;
44 m_realm = r;
45 }
46
47 box_base &operator=(const mapped_type &o) {
48 m_backing_map.insert(m_key, internal::bridge::mixed(std::move(o)));
49 return *this;
50 }
51 box_base &operator=(mapped_type &&o) {
53 if (o) {
54 if constexpr (o->is_managed) {
55 m_backing_map.insert(m_key, o->m_managed.m_obj.get_key());
56 } else {
58 if constexpr (managed<typename mapped_type::value_type::value_type>::schema.HasPrimaryKeyProperty) {
60 m_obj = m_backing_map.create_and_insert_linked_object(m_key, pk.value);
61 } else {
62 m_obj = m_backing_map.create_and_insert_linked_object(m_key);
63 }
64
65 std::apply([&m_obj, &o](auto && ...p) {
66 (accessor<typename std::decay_t<decltype(p)>::Result>::set(
67 m_obj, m_obj.get_table().get_column_key(p.name),
68 (*o->unmanaged).*(std::decay_t<decltype(p)>::ptr)), ...);
70 }
71 } else {
72 m_backing_map.insert(m_key, internal::bridge::mixed());
73 }
74 } else {
75 if constexpr (internal::type_info::is_primitive<mapped_type>::value) {
76 m_backing_map.insert(m_key, serialize(std::move(o)));
77 } else {
78 if (o.is_managed) {
79 m_backing_map.insert(m_key, o.managed.m_obj.get_key());
80 } else {
82 if constexpr (managed<typename mapped_type::value_type>::schema.HasPrimaryKeyProperty) {
83 auto pk = (*o->unmanaged).*(managed<typename mapped_type::value_type>::schema.primary_key().ptr);
84 m_obj = m_backing_map.create_and_insert_linked_object(m_key, pk.value);
85 } else {
86 m_obj = m_backing_map.create_and_insert_linked_object(m_key);
87 }
88
89 std::apply([&m_obj, &o](auto && ...p) {
90 (accessor<typename std::decay_t<decltype(p)>::Result>::set(
91 m_obj, m_obj.get_table().get_column_key(p.name),
92 o.unmanaged.*(std::decay_t<decltype(p)>::ptr)), ...);
94 }
95 }
96 }
97 return *this;
98 }
99
100 rbool operator==(const mapped_type &rhs) const {
101 if constexpr (realm::internal::type_info::MixedPersistableConcept<mapped_type>::value) {
102 if (this->m_rbool_query) {
103 return this->m_rbool_query->dictionary_has_value_for_key_equals(this->m_col_key, m_key, serialize(rhs, m_realm));
104 }
105 return m_backing_map.get(m_key) == serialize(rhs, m_realm);
106 } else {
107 if (this->m_rbool_query) {
108 return this->m_rbool_query->dictionary_has_value_for_key_equals(this->m_col_key, m_key, internal::bridge::mixed(serialize(rhs)));
109 }
110 return m_backing_map.get(m_key) == internal::bridge::mixed(serialize(rhs));
111 }
112 }
113
114 rbool operator!=(const mapped_type &rhs) const {
115 if (this->m_rbool_query) {
116 return this->m_rbool_query->dictionary_has_value_for_key_not_equals(this->m_col_key, m_key, internal::bridge::mixed(serialize(rhs, m_realm)));
117 } else {
118 return !operator==(rhs);
119 }
120 }
121
124 std::string m_key;
126 rbool* m_rbool_query = nullptr;
127 };
128 template<typename V, typename = void>
129 struct box;
130 template<>
131 struct box<int64_t> : public box_base<int64_t> {
132 using box_base<int64_t>::box_base;
133 using box_base<int64_t>::operator=;
134 int64_t operator*() {
135 return m_backing_map.get(m_key).operator int64_t();
136 }
137
138 rbool operator>(int64_t rhs) const {
139 if (this->m_rbool_query) {
140 return this->m_rbool_query->dictionary_has_value_for_key_greater_than(this->m_col_key, m_key, rhs);
141 }
142 return m_backing_map.get(m_key) > internal::bridge::mixed(rhs);
143 }
144
145 rbool operator>=(int64_t rhs) const {
146 if (this->m_rbool_query) {
147 return this->m_rbool_query->dictionary_has_value_for_key_greater_than_equals(this->m_col_key, m_key, rhs);
148 }
149 return m_backing_map.get(m_key) >= internal::bridge::mixed(rhs);
150 }
151
152 rbool operator<(int64_t rhs) const {
153 if (this->m_rbool_query) {
154 return this->m_rbool_query->dictionary_has_value_for_key_less_than(this->m_col_key, m_key, rhs);
155 }
156 return m_backing_map.get(m_key) < internal::bridge::mixed(rhs);
157 }
158
159 rbool operator<=(int64_t rhs) const {
160 if (this->m_rbool_query) {
161 return this->m_rbool_query->dictionary_has_value_for_key_less_than_equals(this->m_col_key, m_key, rhs);
162 }
163 return m_backing_map.get(m_key) <= internal::bridge::mixed(rhs);
164 }
165 };
166 template<>
167 struct box<double> : public box_base<double> {
168 using box_base<double>::box_base;
169 using box_base<double>::operator=;
170 double operator*() {
171 return m_backing_map.get(m_key).operator double();
172 }
173
174 rbool operator>(double rhs) const {
175 if (this->m_rbool_query) {
176 return this->m_rbool_query->dictionary_has_value_for_key_greater_than(this->m_col_key, m_key, rhs);
177 }
178 return m_backing_map.get(m_key) > internal::bridge::mixed(rhs);
179 }
180
181 rbool operator>=(double rhs) const {
182 if (this->m_rbool_query) {
183 return this->m_rbool_query->dictionary_has_value_for_key_greater_than_equals(this->m_col_key, m_key, rhs);
184 }
185 return m_backing_map.get(m_key) >= internal::bridge::mixed(rhs);
186 }
187
188 rbool operator<(double rhs) const {
189 if (this->m_rbool_query) {
190 return this->m_rbool_query->dictionary_has_value_for_key_less_than(this->m_col_key, m_key, rhs);
191 }
192 return m_backing_map.get(m_key) < internal::bridge::mixed(rhs);
193 }
194
195 rbool operator<=(double rhs) const {
196 if (this->m_rbool_query) {
197 return this->m_rbool_query->dictionary_has_value_for_key_less_than_equals(this->m_col_key, m_key, rhs);
198 }
199 return m_backing_map.get(m_key) <= internal::bridge::mixed(rhs);
200 }
201 };
202 template<>
203 struct box<bool> : public box_base<bool> {
204 using box_base<bool>::box_base;
205 using box_base<bool>::operator=;
206 bool operator*() {
207 return m_backing_map.get(m_key).operator bool();
208 }
209 };
210 template<typename V>
211 struct box<V, std::enable_if_t<std::is_enum_v<V>>> : public box_base<V> {
212 using box_base<V>::box_base;
213 using box_base<V>::operator=;
214 V operator*() {
215 return this->m_backing_map.get(this->m_key).operator int64_t();
216 }
217 };
218
219 template<>
220 struct box<uuid> : public box_base<uuid> {
221 using box_base<uuid>::box_base;
222 using box_base<uuid>::operator=;
223 uuid operator*() {
224 return this->m_backing_map.get(this->m_key).operator internal::bridge::uuid().operator ::realm::uuid();
225 }
226 };
227 template<typename Mixed>
228 struct box<Mixed, std::enable_if_t<internal::type_info::MixedPersistableConcept<Mixed>::value>> : public box_base<Mixed> {
229 using box_base<Mixed>::box_base;
230 using box_base<Mixed>::operator=;
231
232 rbool operator>(Mixed rhs) const {
233 if (this->m_rbool_query) {
234 return this->m_rbool_query->dictionary_has_value_for_key_greater_than(this->m_col_key, this->m_key, serialize(rhs, this->m_realm));
235 }
236 return this->m_backing_map.get(this->m_key) > serialize(rhs, this->m_realm);
237 }
238
239 rbool operator>=(Mixed rhs) const {
240 if (this->m_rbool_query) {
241 return this->m_rbool_query->dictionary_has_value_for_key_greater_than_equals(this->m_col_key, this->m_key, serialize(rhs, this->m_realm));
242 }
243 return this->m_backing_map.get(this->m_key) >= serialize(rhs, this->m_realm);
244 }
245
246 rbool operator<(Mixed rhs) const {
247 if (this->m_rbool_query) {
248 return this->m_rbool_query->dictionary_has_value_for_key_less_than(this->m_col_key, this->m_key, serialize(rhs, this->m_realm));
249 }
250 return this->m_backing_map.get(this->m_key) < serialize(rhs, this->m_realm);
251 }
252
253 rbool operator<=(Mixed rhs) const {
254 if (this->m_rbool_query) {
255 return this->m_rbool_query->dictionary_has_value_for_key_less_than_equals(this->m_col_key, this->m_key, serialize(rhs, this->m_realm));
256 }
257 return this->m_backing_map.get(this->m_key) <= serialize(rhs, this->m_realm);
258 }
259 };
260 template<>
261 struct box<object_id> : public box_base<object_id> {
262 using box_base<object_id>::box_base;
263 using box_base<object_id>::operator=;
264 object_id operator*() {
265 return this->m_backing_map.get(this->m_key).operator internal::bridge::object_id().operator ::realm::object_id();
266 }
267 };
268 template<>
269 struct box<decimal128> : public box_base<decimal128> {
270 using box_base<decimal128>::box_base;
271 using box_base<decimal128>::operator=;
272 decimal128 operator*() {
273 return this->m_backing_map.get(this->m_key).operator internal::bridge::decimal128().operator ::realm::decimal128();
274 }
275
276 rbool operator>(decimal128 rhs) const {
277 if (this->m_rbool_query) {
278 return this->m_rbool_query->dictionary_has_value_for_key_greater_than(this->m_col_key, m_key, serialize(rhs));
279 }
280 return m_backing_map.get(m_key) > internal::bridge::mixed(serialize(rhs));
281 }
282
283 rbool operator>=(decimal128 rhs) const {
284 if (this->m_rbool_query) {
285 return this->m_rbool_query->dictionary_has_value_for_key_greater_than_equals(this->m_col_key, m_key, serialize(rhs));
286 }
287 return m_backing_map.get(m_key) >= internal::bridge::mixed(serialize(rhs));
288 }
289
290 rbool operator<(decimal128 rhs) const {
291 if (this->m_rbool_query) {
292 return this->m_rbool_query->dictionary_has_value_for_key_less_than(this->m_col_key, m_key, serialize(rhs));
293 }
294 return m_backing_map.get(m_key) < internal::bridge::mixed(serialize(rhs));
295 }
296
297 rbool operator<=(decimal128 rhs) const {
298 if (this->m_rbool_query) {
299 return this->m_rbool_query->dictionary_has_value_for_key_less_than_equals(this->m_col_key, m_key, serialize(rhs));
300 }
301 return m_backing_map.get(m_key) <= internal::bridge::mixed(serialize(rhs));
302 }
303 };
304 template<>
305 struct box<std::chrono::time_point<std::chrono::system_clock>> : public box_base<std::chrono::time_point<std::chrono::system_clock>> {
306 using box_base<std::chrono::time_point<std::chrono::system_clock>>::box_base;
307 using box_base<std::chrono::time_point<std::chrono::system_clock>>::operator=;
308 std::chrono::time_point<std::chrono::system_clock> operator*() {
309 return this->m_backing_map.get(this->m_key).operator internal::bridge::timestamp().operator std::chrono::time_point<std::chrono::system_clock>();
310 }
311
312 rbool operator>(std::chrono::time_point<std::chrono::system_clock> rhs) const {
313 if (this->m_rbool_query) {
314 return this->m_rbool_query->dictionary_has_value_for_key_greater_than(this->m_col_key, m_key, serialize(rhs));
315 }
316 return m_backing_map.get(m_key) > internal::bridge::mixed(rhs);
317 }
318
319 rbool operator>=(std::chrono::time_point<std::chrono::system_clock> rhs) const {
320 if (this->m_rbool_query) {
321 return this->m_rbool_query->dictionary_has_value_for_key_greater_than_equals(this->m_col_key, m_key, serialize(rhs));
322 }
323 return m_backing_map.get(m_key) >= internal::bridge::mixed(rhs);
324 }
325
326 rbool operator<(std::chrono::time_point<std::chrono::system_clock> rhs) const {
327 if (this->m_rbool_query) {
328 return this->m_rbool_query->dictionary_has_value_for_key_less_than(this->m_col_key, m_key, serialize(rhs));
329 }
330 return m_backing_map.get(m_key) < internal::bridge::mixed(rhs);
331 }
332
333 rbool operator<=(std::chrono::time_point<std::chrono::system_clock> rhs) const {
334 if (this->m_rbool_query) {
335 return this->m_rbool_query->dictionary_has_value_for_key_less_than_equals(this->m_col_key, m_key, serialize(rhs));
336 }
337 return m_backing_map.get(m_key) <= internal::bridge::mixed(rhs);
338 }
339 };
340 template<>
341 struct box<std::vector<uint8_t>> : public box_base<std::vector<uint8_t>> {
342 using box_base<std::vector<uint8_t>>::box_base;
343 using box_base<std::vector<uint8_t>>::operator=;
344 std::vector<uint8_t> operator*() {
345 return this->m_backing_map.get(this->m_key).operator internal::bridge::binary().operator std::vector<uint8_t>();
346 }
347 };
348 template<>
349 struct box<std::string> : public box_base<std::string> {
350 using box_base<std::string>::box_base;
351 using box_base<std::string>::operator=;
352 std::string operator*() {
353 return this->m_backing_map.get(this->m_key).operator std::string();
354 }
355
356 rbool contains(const std::string& rhs) const {
357 if (this->m_rbool_query) {
358 return this->m_rbool_query->dictionary_contains_string_for_key(this->m_col_key, m_key, rhs);
359 }
360 std::string lhs = m_backing_map.get(m_key);
361 return lhs.find(rhs) != std::string::npos;
362 }
363 };
364
365 //MARK: - Boxed Link
366 template<typename V>
367 struct box<managed<V*>> : public box_base<managed<V*>> {
368 using box_base<managed<V*>>::box_base;
369 using box_base<managed<V*>>::operator=;
370 using box_base<managed<V*>>::operator==;
371
372 rbool operator==(const managed<V*> &rhs) const {
373 if (this->m_rbool_query) {
374 return this->m_rbool_query->dictionary_has_value_for_key_equals(this->m_col_key,
375 this->m_key,
376 rhs ? internal::bridge::mixed(internal::bridge::obj_link(rhs.m_obj->get_table().get_key(), rhs.m_obj->get_key())) : internal::bridge::mixed());
377 }
378 auto a = const_cast<box<managed<V*>> *>(this)->m_backing_map.get_object(this->m_key);
379 auto &b = rhs.m_obj;
380 if (this->m_realm != *rhs.m_realm) {
381 return false;
382 }
383 return a.get_key() == b->get_key();
384 }
385
386 rbool operator!=(const managed<V*> rhs) const {
387 if (this->m_rbool_query) {
388 return this->m_rbool_query->dictionary_has_value_for_key_not_equals(this->m_col_key,
389 this->m_key,
390 rhs ? internal::bridge::mixed(internal::bridge::obj_link(rhs.m_obj->get_table().get_key(), rhs.m_obj->get_key())) : internal::bridge::mixed());
391 }
392 return !this->operator==(rhs);
393 }
394
395 rbool operator==(const managed<V> &rhs) const {
396 if (this->m_rbool_query) {
397 return this->m_rbool_query->dictionary_has_value_for_key_equals(this->m_col_key,
398 this->m_key,
399 internal::bridge::obj_link(rhs.m_obj.get_table().get_key(), rhs.m_obj.get_key()));
400 }
401
402 auto a = const_cast<box<managed<V*>> *>(this)->m_backing_map.get_object(this->m_key);
403 auto &b = rhs.m_obj;
404 if (this->m_realm != rhs.m_realm) {
405 return false;
406 }
407 return a.get_key() == b.get_key();
408 }
409
410 rbool operator!=(const managed<V> rhs) const {
411 if (this->m_rbool_query) {
412 return this->m_rbool_query->dictionary_has_value_for_key_not_equals(this->m_col_key,
413 this->m_key,
414 internal::bridge::obj_link(rhs.m_obj.get_table().get_key(), rhs.m_obj.get_key()));
415 }
416
417 return !this->operator==(rhs);
418 }
419
420 std::optional<typename managed<V*>::ref_type> operator*() {
421 auto obj = this->m_backing_map.get_object(this->m_key);
422 if (!obj.is_valid()) {
423 return std::nullopt;
424 }
425 return typename managed<V*>::ref_type(managed<V>(std::move(obj), this->m_realm));
426 }
427
428 typename managed<V*>::ref_type operator->() {
429 if (this->m_rbool_query) {
431 ctx.m_key = this->m_key;
432 ctx.origin_col_key = this->m_col_key;
433 this->m_rbool_query->add_dictionary_link_chain(std::move(ctx));
434 return typename managed<V*>::ref_type(managed<V>::prepare_for_query(this->m_realm, this->m_rbool_query));
435 }
436 auto obj = this->m_backing_map.get_object(this->m_key);
437 return typename managed<V*>::ref_type(managed<V>(std::move(obj), this->m_realm));
438 }
439
440 box& operator=(V* o) {
441 if (!o) {
442 // Insert null link for key.
443 this->m_backing_map.insert(this->m_key, realm::internal::bridge::mixed());
444 return *this;
445 }
447 if constexpr (managed<V>::schema.HasPrimaryKeyProperty) {
448 auto pk = (*o).*(managed<V>::schema.primary_key().ptr);
449 m_obj = const_cast<box<managed<V*>> *>(this)->m_backing_map.create_and_insert_linked_object(const_cast<box<managed<V*>> *>(this)->m_key, pk.value);
450 } else {
451 m_obj = const_cast<box<managed<V*>> *>(this)->m_backing_map.create_and_insert_linked_object(const_cast<box<managed<V*>> *>(this)->m_key);
452 }
453
454 std::apply([&m_obj, &o, realm = this->m_realm](auto && ...p) {
455 (accessor<typename std::decay_t<decltype(p)>::Result>::set(
456 m_obj, m_obj.get_table().get_column_key(p.name), realm,
457 (*o).*(std::decay_t<decltype(p)>::ptr)), ...);
458 }, managed<V>::schema.ps);
459 return *this;
460 }
461
462 box& operator=(const managed<V*>& o) {
463 this->m_backing_map.insert(this->m_key, o->m_obj.get_key());
464 return *this;
465 }
466
467 box& operator=(const managed<V>& o) {
468 this->m_backing_map.insert(this->m_key, o.m_obj.get_key());
469 return *this;
470 }
471
472 bool operator==(const box<managed<V*>> &rhs) const {
473 auto a = const_cast<box<managed<V*>>*>(this)->m_backing_map.get_object(this->m_key);
474 auto &b = static_cast<box<managed<V*>>>(rhs)->m_obj;
475 if (this->m_realm != rhs.m_realm) {
476 return false;
477 }
478 return a.get_key() == b.get_key();
479 }
480
481 bool operator!=(const box<managed<V*>> rhs) const {
482 return !this->operator==(rhs);
483 }
484
485 bool operator==(const box<V*>& rhs) {
486 auto a = const_cast<box<managed<V*>> *>(this)->m_backing_map.get_object(this->m_key);
487 auto &b = (&rhs)->m_obj;
488 if (this->m_realm != rhs.m_realm) {
489 return false;
490 }
491 return a.get_key() == b.get_key();
492 }
493
494 bool operator!=(const box<V*>& rhs) const {
495 return !this->operator==(rhs);
496 }
497 };
498
499 template<typename T>
500 struct managed<std::map<std::string, T>, void> : managed_base {
501 using managed<std::map<std::string, T>>::managed_base::operator=;
502
503 [[nodiscard]] std::map<std::string, T> detach() const {
504 if constexpr (std::is_pointer_v<T>) {
505 auto d = internal::bridge::get<internal::bridge::core_dictionary>(*m_obj, m_key);
506 size_t s = d.size();
507 std::map<std::string, T> ret;
508 for (size_t i = 0; i < s; i++) {
509 auto pair = d.get_pair(i);
510 using Type = std::remove_pointer_t<T>;
511 T v = new Type;
512 managed<Type, void> m(d.get_object(pair.first), *m_realm);
513
514 auto assign = [&m, &v](auto& pair) {
515 (*v).*(std::decay_t<decltype(pair.first)>::ptr) = (m.*(pair.second)).detach();
516 };
517 auto zipped = internal::zip_tuples(managed<Type>::schema.ps, managed<Type>::managed_pointers());
518
519 std::apply([&v, &m, &assign](auto && ...pair) {
520 (assign(pair), ...);
521 }, zipped);
522
523 ret[pair.first] = v;
524 }
525
526 return ret;
527 }
528 auto ret = std::map<std::string, T>();
529 for (auto [k, v] : *this) {
530 ret[k] = v;
531 }
532 return ret;
533 }
534
535 std::enable_if<std::is_pointer_v<T>, std::map<std::string, managed<T>>> to_map() const {
536 auto ret = std::map<std::string, T>();
537 for (auto [k, v] : *this) {
538 ret[k] = v;
539 }
540 return ret;
541 }
542
543 class iterator {
544 public:
545 using iterator_category = std::input_iterator_tag;
546
547 bool operator!=(const iterator& other) const
548 {
549 return !(*this == other);
550 }
551
552 bool operator==(const iterator& other) const
553 {
554 return (m_parent == other.m_parent) && (m_i == other.m_i);
555 }
556
557 std::pair<std::string, T> operator*() noexcept
558 {
559 auto pair = m_parent->m_obj->get_dictionary(m_parent->m_key).get_pair(m_i);
560 return { pair.first, deserialize<T>(pair.second) };
561 }
562
563 iterator& operator++()
564 {
565 this->m_i++;
566 return *this;
567 }
568
569 const iterator& operator++(int i)
570 {
571 this->m_i += i;
572 return *this;
573 }
574 private:
575 template<typename, typename>
576 friend struct managed;
577
578 iterator(size_t i, const managed<std::map<std::string, T>>* parent)
579 : m_i(i), m_parent(parent)
580 {
581 }
582 size_t m_i;
583 const managed<std::map<std::string, T>>* m_parent;
584 };
585
586 size_t size() const
587 {
588 return m_obj->get_dictionary(m_key).size();
589 }
590
591 iterator begin() const
592 {
593 return iterator(0, this);
594 }
595
596 iterator end() const
597 {
598 return iterator(size(), this);
599 }
600
601 iterator find(const std::string& key) {
602 if (m_rbool_query) {
603 throw std::runtime_error("`find` is not available in Type Safe Queries, use `contains_key` instead.");
604 }
605 // Dictionary's `find` searches for the index of the value and not the key.
606 auto d = m_obj->get_dictionary(m_key);
607 auto i = d.find_any_key(key);
608 if (i == size_t(-1)) {
609 return iterator(size(), this);
610 } else {
611 return iterator(i, this);
612 }
613 }
614
615 box<std::conditional_t<std::is_pointer_v<T>, managed<T>, T>> operator[](const std::string &key) {
616 if constexpr (std::is_pointer_v<T>) {
617 if (m_rbool_query) {
618 return box<managed<T>>(m_rbool_query, m_key, key, *m_realm);
619 }
620 return box<managed<T>>(m_obj->get_dictionary(m_key), key, *m_realm);
621 } else {
622 if (m_rbool_query) {
623 return box<T>(m_rbool_query, m_key, key, *m_realm);
624 }
625 return box<T>(m_obj->get_dictionary(m_key), key, *m_realm);
626 }
627 }
628
629 void erase(const std::string& key) {
630 m_obj->get_dictionary(m_key).erase(key);
631 }
632
634 rbool contains_key(const std::string& key) {
635 if (m_rbool_query) {
636 return m_rbool_query->dictionary_has_key(m_key, key);
637 } else {
638 return m_obj->get_dictionary(m_key).find_any_key(key) != size_t(-1);
639 }
640 }
641
642 notification_token observe(std::function<void(realm::dictionary_collection_change)>&& fn)
643 {
644 auto o = internal::bridge::object(*m_realm, *m_obj);
645 auto dict = std::make_shared<realm::internal::bridge::dictionary>(o.get_dictionary(m_key));
646 realm::notification_token token = dict->add_key_based_notification_callback(
647 std::make_shared<realm::dictionary_callback_wrapper>(std::move(fn), false));
648 token.m_realm = *m_realm;
649 token.m_dictionary = dict;
650 return token;
651 }
652
653 private:
654 managed() = default;
655 managed(const managed&) = delete;
656 managed(managed &&) = delete;
657 managed& operator=(const managed&) = delete;
658 managed& operator=(managed&&) = delete;
659 template<typename, typename>
660 friend struct managed;
661 };
662
663} // namespace realm
664
665#endif//CPPREALM_MANAGED_DICTIONARY_HPP
Definition: rbool.hpp:36
Definition: accessors.hpp:33
Definition: managed_dictionary.hpp:31
Definition: managed_dictionary.hpp:129
Definition: types.hpp:75
Definition: dictionary.hpp:53
Definition: binary.hpp:30
Definition: col_key.hpp:28
Definition: dictionary.hpp:106
Definition: decimal128.hpp:30
Definition: mixed.hpp:69
Definition: obj.hpp:123
Definition: object_id.hpp:31
Definition: object.hpp:154
Definition: realm.hpp:67
Definition: timestamp.hpp:30
Definition: uuid.hpp:32
rbool contains_key(const std::string &key)
Convenience method to be primarily used in type safe queries.
Definition: managed_dictionary.hpp:634
Definition: macros.hpp:286
Definition: obj.hpp:62
Definition: notifications.hpp:38
Definition: types.hpp:56
Definition: managed_primary_key.hpp:30
Definition: rbool.hpp:38
Definition: types.hpp:35