19#ifndef CPPREALM_MANAGED_DICTIONARY_HPP
20#define CPPREALM_MANAGED_DICTIONARY_HPP
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>
30 template<
typename mapped_type>
33 const std::string &key,
35 : m_backing_map(std::move(backing_map)), m_key(key), m_realm(r) {}
39 const std::string &key,
41 m_rbool_query = query;
42 m_col_key = column_key;
47 box_base &operator=(
const mapped_type &o) {
51 box_base &operator=(mapped_type &&o) {
54 if constexpr (o->is_managed) {
55 m_backing_map.insert(m_key, o->m_managed.m_obj.get_key());
60 m_obj = m_backing_map.create_and_insert_linked_object(m_key, pk.value);
62 m_obj = m_backing_map.create_and_insert_linked_object(m_key);
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)), ...);
75 if constexpr (internal::type_info::is_primitive<mapped_type>::value) {
76 m_backing_map.insert(m_key, serialize(std::move(o)));
79 m_backing_map.insert(m_key, o.managed.m_obj.get_key());
84 m_obj = m_backing_map.create_and_insert_linked_object(m_key, pk.value);
86 m_obj = m_backing_map.create_and_insert_linked_object(m_key);
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)), ...);
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));
105 return m_backing_map.get(m_key) == serialize(rhs, m_realm);
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)));
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)));
118 return !operator==(rhs);
126 rbool* m_rbool_query =
nullptr;
128 template<
typename V,
typename =
void>
134 int64_t operator*() {
135 return m_backing_map.get(m_key).operator int64_t();
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);
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);
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);
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);
171 return m_backing_map.get(m_key).operator double();
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);
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);
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);
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);
207 return m_backing_map.get(m_key).operator bool();
211 struct box<V, std::enable_if_t<std::is_enum_v<V>>> :
public box_base<V> {
215 return this->m_backing_map.get(this->m_key).operator int64_t();
227 template<
typename Mixed>
228 struct box<Mixed, std::enable_if_t<internal::type_info::MixedPersistableConcept<Mixed>::value>> :
public box_base<Mixed> {
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));
236 return this->m_backing_map.get(this->m_key) > serialize(rhs, this->m_realm);
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));
243 return this->m_backing_map.get(this->m_key) >= serialize(rhs, this->m_realm);
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));
250 return this->m_backing_map.get(this->m_key) < serialize(rhs, this->m_realm);
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));
257 return this->m_backing_map.get(this->m_key) <= serialize(rhs, this->m_realm);
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));
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));
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));
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));
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>();
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));
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));
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));
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));
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*() {
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();
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);
360 std::string lhs = m_backing_map.get(m_key);
361 return lhs.find(rhs) != std::string::npos;
373 if (this->m_rbool_query) {
374 return this->m_rbool_query->dictionary_has_value_for_key_equals(this->m_col_key,
378 auto a =
const_cast<box<managed<V*>> *>(
this)->m_backing_map.get_object(this->m_key);
380 if (this->m_realm != *rhs.m_realm) {
383 return a.get_key() == b->get_key();
387 if (this->m_rbool_query) {
388 return this->m_rbool_query->dictionary_has_value_for_key_not_equals(this->m_col_key,
392 return !this->operator==(rhs);
396 if (this->m_rbool_query) {
397 return this->m_rbool_query->dictionary_has_value_for_key_equals(this->m_col_key,
402 auto a =
const_cast<box<managed<V*>> *>(
this)->m_backing_map.get_object(this->m_key);
404 if (this->m_realm != rhs.m_realm) {
407 return a.get_key() == b.get_key();
411 if (this->m_rbool_query) {
412 return this->m_rbool_query->dictionary_has_value_for_key_not_equals(this->m_col_key,
417 return !this->operator==(rhs);
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()) {
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));
436 auto obj = this->m_backing_map.get_object(this->m_key);
440 box& operator=(V* o) {
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);
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)), ...);
463 this->m_backing_map.insert(this->m_key, o->m_obj.get_key());
468 this->m_backing_map.insert(this->m_key, o.m_obj.get_key());
473 auto a =
const_cast<box<managed<V*>>*>(
this)->m_backing_map.get_object(this->m_key);
475 if (this->m_realm != rhs.m_realm) {
478 return a.get_key() == b.get_key();
482 return !this->operator==(rhs);
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) {
491 return a.get_key() == b.get_key();
494 bool operator!=(
const box<V*>& rhs)
const {
495 return !this->operator==(rhs);
501 using managed<std::map<std::string, T>>::managed_base::operator=;
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);
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>;
514 auto assign = [&m, &v](
auto& pair) {
515 (*v).*(std::decay_t<
decltype(pair.first)>::ptr) = (m.*(pair.second)).detach();
519 std::apply([&v, &m, &assign](
auto && ...pair) {
528 auto ret = std::map<std::string, T>();
529 for (
auto [k, v] : *
this) {
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) {
545 using iterator_category = std::input_iterator_tag;
547 bool operator!=(
const iterator& other)
const
549 return !(*
this == other);
552 bool operator==(
const iterator& other)
const
554 return (m_parent == other.m_parent) && (m_i == other.m_i);
557 std::pair<std::string, T> operator*()
noexcept
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) };
563 iterator& operator++()
569 const iterator& operator++(
int i)
575 template<
typename,
typename>
578 iterator(
size_t i,
const managed<std::map<std::string, T>>* parent)
579 : m_i(i), m_parent(parent)
588 return m_obj->get_dictionary(m_key).size();
591 iterator begin()
const
593 return iterator(0,
this);
598 return iterator(size(),
this);
601 iterator find(
const std::string& key) {
603 throw std::runtime_error(
"`find` is not available in Type Safe Queries, use `contains_key` instead.");
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);
611 return iterator(i,
this);
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>) {
618 return box<managed<T>>(m_rbool_query, m_key, key, *m_realm);
620 return box<managed<T>>(m_obj->get_dictionary(m_key), key, *m_realm);
623 return box<T>(m_rbool_query, m_key, key, *m_realm);
625 return box<T>(m_obj->get_dictionary(m_key), key, *m_realm);
629 void erase(
const std::string& key) {
630 m_obj->get_dictionary(m_key).erase(key);
636 return m_rbool_query->dictionary_has_key(m_key, key);
638 return m_obj->get_dictionary(m_key).find_any_key(key) != size_t(-1);
645 auto dict = std::make_shared<realm::internal::bridge::dictionary>(o.get_dictionary(m_key));
647 std::make_shared<realm::dictionary_callback_wrapper>(std::move(fn),
false));
648 token.m_realm = *m_realm;
649 token.m_dictionary = dict;
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;
Definition: accessors.hpp:33
Definition: managed_dictionary.hpp:31
Definition: managed_dictionary.hpp:129
Definition: dictionary.hpp:53
Definition: binary.hpp:30
Definition: col_key.hpp:28
Definition: dictionary.hpp:106
Definition: decimal128.hpp:30
Definition: obj_key.hpp:53
Definition: object_id.hpp:31
Definition: object.hpp:154
Definition: timestamp.hpp:30
Definition: type_info.hpp:145
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: notifications.hpp:38
Definition: managed_primary_key.hpp:30