Realm C++ SDK Version v2.2.0

accessors.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_ACCESSORS_HPP
20#define CPPREALM_ACCESSORS_HPP
21
22#include <cpprealm/internal/bridge/lnklst.hpp>
23#include <cpprealm/internal/bridge/obj.hpp>
24#include <cpprealm/internal/bridge/realm.hpp>
25#include <cpprealm/internal/bridge/table.hpp>
26#include <cpprealm/types.hpp>
27
28namespace realm {
29 template<typename>
30 struct primary_key;
31
32 template <typename T, typename = void>
33 struct accessor {
34 static inline void set(internal::bridge::obj& obj,
37 const T& value);
38 };
39
40 template <>
41 struct accessor<int64_t> {
42 static inline void set(internal::bridge::obj& obj,
45 const int64_t& value) {
46 obj.set(key, value);
47 }
48 };
49 template <>
50 struct accessor<std::optional<int64_t>> {
51 static inline void set(internal::bridge::obj& obj,
54 const std::optional<int64_t>& value) {
55 if (value) {
56 obj.set(key, *value);
57 } else {
58 obj.set_null(key);
59 }
60 }
61 };
62 template <>
63 struct accessor<double> {
64 static inline void set(internal::bridge::obj& obj,
67 const double& value) {
68 obj.set(key, value);
69 }
70 };
71 template <>
72 struct accessor<std::optional<double>> {
73 static inline void set(internal::bridge::obj& obj,
76 const std::optional<double>& value) {
77 if (value) {
78 obj.set(key, *value);
79 } else {
80 obj.set_null(key);
81 }
82 }
83 };
84 template <>
85 struct accessor<bool> {
86 static inline void set(internal::bridge::obj& obj,
89 const bool& value) {
90 obj.set(key, value);
91 }
92 };
93 template <>
94 struct accessor<std::optional<bool>> {
95 static inline void set(internal::bridge::obj& obj,
98 const std::optional<bool>& value) {
99 if (value) {
100 obj.set(key, *value);
101 } else {
102 obj.set_null(key);
103 }
104 }
105 };
106
107
108 template <typename T>
109 struct accessor<T, std::enable_if_t<std::is_enum_v<T>>> {
110 static inline void set(internal::bridge::obj& obj,
111 const internal::bridge::col_key& key,
113 const T& value) {
114 obj.set(key, static_cast<int64_t>(value));
115 }
116 };
117 template <typename T>
118 struct accessor<T, std::enable_if_t<std::conjunction_v<internal::type_info::is_optional<T>, std::is_enum<typename T::value_type>>>> {
119 static inline void set(internal::bridge::obj& obj,
120 const internal::bridge::col_key& key,
122 const T& value) {
123 if (value) {
124 obj.set(key, static_cast<int64_t>(*value));
125 } else {
126 obj.set_null(key);
127 }
128 }
129 };
130
131 template <typename T>
132 struct accessor<T, std::enable_if_t<internal::type_info::MixedPersistableConcept<T>::value>> {
133 static inline void set(internal::bridge::obj& obj,
134 const internal::bridge::col_key& key,
136 const T& value) {
137 obj.set(key, serialize(value));
138 }
139 };
140
141
142 template <>
143 struct accessor<uuid> {
144 static inline void set(internal::bridge::obj& obj,
145 const internal::bridge::col_key& key,
147 const uuid& value) {
148 obj.set(key, value);
149 }
150 };
151 template <>
152 struct accessor<std::optional<uuid>> {
153 static inline void set(internal::bridge::obj& obj,
154 const internal::bridge::col_key& key,
156 const std::optional<uuid>& value) {
157 if (value) {
158 obj.set(key, *value);
159 } else {
160 obj.set_null(key);
161 }
162 }
163 };
164 template <>
166 static inline void set(internal::bridge::obj& obj,
167 const internal::bridge::col_key& key,
169 const object_id& value) {
170 obj.set(key, value);
171 }
172 };
173 template <>
174 struct accessor<std::optional<object_id>> {
175 static inline void set(internal::bridge::obj& obj,
176 const internal::bridge::col_key& key,
178 const std::optional<object_id>& value) {
179 if (value) {
180 obj.set(key, *value);
181 } else {
182 obj.set_null(key);
183 }
184 }
185 };
186
187 template <>
189 static inline void set(internal::bridge::obj& obj,
190 const internal::bridge::col_key& key,
192 const decimal128& value) {
193 obj.set(key, value);
194 }
195 };
196 template <>
197 struct accessor<std::optional<decimal128>> {
198 static inline void set(internal::bridge::obj& obj,
199 const internal::bridge::col_key& key,
201 const std::optional<decimal128>& value) {
202 if (value) {
203 obj.set(key, *value);
204 } else {
205 obj.set_null(key);
206 }
207 }
208 };
209
210 template <>
211 struct accessor<std::chrono::time_point<std::chrono::system_clock>> {
212 static inline void set(internal::bridge::obj& obj,
213 const internal::bridge::col_key& key,
215 const std::chrono::time_point<std::chrono::system_clock>& value) {
216 obj.set(key, value);
217 }
218 };
219 template <>
220 struct accessor<std::optional<std::chrono::time_point<std::chrono::system_clock>>> {
221 static inline void set(internal::bridge::obj& obj,
222 const internal::bridge::col_key& key,
224 const std::optional<std::chrono::time_point<std::chrono::system_clock>>& value) {
225 if (value) {
226 obj.set(key, *value);
227 } else {
228 obj.set_null(key);
229 }
230 }
231 };
232
233 template <>
234 struct accessor<std::string> {
235 static inline void set(internal::bridge::obj& obj,
236 const internal::bridge::col_key& key,
238 const std::string& value) {
239 obj.set(key, value);
240 }
241 };
242 template <>
243 struct accessor<std::optional<std::string>> {
244 static inline void set(internal::bridge::obj& obj,
245 const internal::bridge::col_key& key,
247 const std::optional<std::string>& value) {
248 if (value) {
249 obj.set(key, *value);
250 } else {
251 obj.set_null(key);
252 }
253 }
254 };
255
256 template <>
257 struct accessor<std::vector<uint8_t>> {
258 static inline void set(internal::bridge::obj& obj,
259 const internal::bridge::col_key& key,
261 const std::vector<uint8_t>& value) {
262 obj.set(key, value);
263 }
264 };
265 template <>
266 struct accessor<std::optional<std::vector<uint8_t>>> {
267 static inline void set(internal::bridge::obj& obj,
268 const internal::bridge::col_key& key,
270 const std::optional<std::vector<uint8_t>>& value) {
271 if (value) {
272 obj.set(key, *value);
273 } else {
274 obj.set_null(key);
275 }
276 }
277 };
278 template <typename T>
279 struct accessor<std::vector<T>> {
280 static inline void set(internal::bridge::obj& obj,
281 const internal::bridge::col_key& key,
283 const std::vector<T>& value) {
284 obj.set_list_values(key, value);
285 }
286 };
287 template <typename T>
288 struct accessor<std::vector<T*>> {
289 static inline void set(internal::bridge::obj& obj,
290 const internal::bridge::col_key& key,
291 const internal::bridge::realm& realm,
292 const std::vector<T*>& value) {
293 auto list = obj.get_linklist(key);
294 for (size_t i = 0; i < value.size(); i++) {
295 auto& lnk = value[i];
296 if (!lnk) {
297 continue;
298 }
299 auto table = obj.get_target_table(key);
301 if constexpr (managed<T, void>::schema.HasPrimaryKeyProperty) {
302 auto pk = (*lnk).*(managed<T, void>::schema.primary_key().ptr);
303 m_obj = table.create_object_with_primary_key(realm::internal::bridge::mixed(serialize(pk.value)));
304 } else if (managed<T, void>::schema.is_embedded()) {
305 m_obj = list.create_and_insert_linked_object(i);
306 } else {
307 m_obj = table.create_object();
308 }
309 std::apply([&m_obj, &lnk, &realm](auto && ...p) {
310 (accessor<typename std::decay_t<decltype(p)>::Result>::set(
311 m_obj, m_obj.get_table().get_column_key(p.name), realm,
312 (*lnk).*(std::decay_t<decltype(p)>::ptr)), ...);
314 if (!managed<T, void>::schema.is_embedded()) {
315 list.add(m_obj.get_key());
316 }
317 }
318 }
319 };
320 template <typename T>
321 struct accessor<std::set<T>> {
322 static inline void set(internal::bridge::obj& obj,
323 const internal::bridge::col_key& key,
324 const internal::bridge::realm& realm,
325 const std::set<T>& value) {
326 auto set = realm::internal::bridge::set(realm, obj, key);
327 for (const auto& v : value) {
328 set.insert(serialize(v));
329 }
330 }
331 };
332 template <typename T>
333 struct accessor<std::set<T*>> {
334 static inline void set(internal::bridge::obj& obj,
335 const internal::bridge::col_key& key,
336 const internal::bridge::realm& realm,
337 const std::set<T*>& value) {
338 auto set = realm::internal::bridge::set(realm, obj, key);
339 for (const auto& lnk : value) {
340 if (!lnk) {
341 continue;
342 }
343 auto table = obj.get_target_table(key);
345 if constexpr (managed<T, void>::schema.HasPrimaryKeyProperty) {
346 auto pk = (*lnk).*(managed<T, void>::schema.primary_key().ptr);
347 m_obj = table.create_object_with_primary_key(realm::internal::bridge::mixed(serialize(pk.value)));
348 } else {
349 m_obj = table.create_object();
350 }
351 std::apply([&m_obj, &lnk, &realm](auto && ...p) {
352 (accessor<typename std::decay_t<decltype(p)>::Result>::set(
353 m_obj, m_obj.get_table().get_column_key(p.name), realm,
354 (*lnk).*(std::decay_t<decltype(p)>::ptr)), ...);
356 if (!managed<T, void>::schema.is_embedded()) {
357 set.insert(m_obj.get_key());
358 }
359 }
360 }
361 };
362 template <typename T>
363 struct accessor<std::map<std::string, T>> {
364 static void set(internal::bridge::obj& obj,
365 const internal::bridge::col_key& key,
367 const std::map<std::string, T>& value) {
368 auto d = obj.get_dictionary(key);
369 for (auto& [k, v] : value) {
370 if constexpr (internal::type_info::MixedPersistableConcept<T>::value) {
371 d.insert(k, std::visit([](auto&& arg) {
372 using M = typename internal::type_info::type_info<std::decay_t<decltype(arg)>>::internal_type;
373 return internal::bridge::mixed(M(arg));
374 }, v));
375 } else {
377 if constexpr (std::is_enum_v<typename T::value_type>) {
378 if (v) {
379 d.insert(k, static_cast<typename std::underlying_type<typename T::value_type>::type>(*v));
380 } else {
381 d.insert(k, internal::bridge::mixed());
382 }
383 } else {
385 d.insert(k, U(v));
386 }
387 } else {
389 d.insert(k, U(v));
390 }
391 }
392 }
393 }
394 };
395 template <typename T>
396 struct accessor<std::map<std::string, T*>> {
397 static void set(internal::bridge::obj& obj,
398 const internal::bridge::col_key& key,
399 const internal::bridge::realm& realm,
400 const std::map<std::string, T*>& value) {
401 auto d = obj.get_dictionary(key);
402 for (auto& [k, v] : value) {
403 if (v) {
405 if constexpr (managed<T, void>::schema.HasPrimaryKeyProperty) {
406 auto pk = (*v).*(managed<T, void>::schema.primary_key().ptr);
407 m_obj = d.create_and_insert_linked_object(k, pk.value);
408 } else {
409 m_obj = d.create_and_insert_linked_object(k);
410 }
411 std::apply([&m_obj, &realm, o = *v](auto && ...p) {
412 (accessor<typename std::decay_t<decltype(p)>::Result>::set(
413 m_obj, m_obj.get_table().get_column_key(p.name), realm,
414 o.*(std::decay_t<decltype(p)>::ptr)), ...);
416 d.insert(k, m_obj.get_key());
417 } else {
418 d.insert(k, internal::bridge::mixed());
419 }
420 }
421 }
422 };
423 // MARK: - accessor link
424
425 template <typename T>
426 struct accessor<T*> {
427 static inline void set(internal::bridge::obj& obj,
428 const internal::bridge::col_key& key,
429 const internal::bridge::realm& realm,
430 const T* value) {
431 if (!value) {
432 return;
433 }
434 auto table = obj.get_target_table(key);
436 if constexpr (managed<T, void>::schema.HasPrimaryKeyProperty) {
437 auto pk = (*value).*(managed<T, void>::schema.primary_key().ptr);
438 m_obj = table.create_object_with_primary_key(realm::internal::bridge::mixed(serialize(pk.value)));
439 obj.set(key, m_obj.get_key());
440 } else if (managed<T, void>::schema.is_embedded()) {
441 m_obj = obj.create_and_set_linked_object(key);
442 } else {
443 m_obj = table.create_object();
444 obj.set(key, m_obj.get_key());
445 }
446 std::apply([&m_obj, &realm, &value](auto && ...p) {
447 (accessor<typename std::decay_t<decltype(p)>::Result>::set(
448 m_obj, m_obj.get_table().get_column_key(p.name), realm,
449 (*value).*(std::decay_t<decltype(p)>::ptr)), ...);
451 }
452 };
453
454 template <auto T>
456 static inline void set(const internal::bridge::obj&,
459 const linking_objects<T>&) {
460 }
461 };
462 // MARK: - accessor primary key
463 template <typename T>
465 static inline void set(internal::bridge::obj& obj,
466 const internal::bridge::col_key& key,
468 const primary_key<T>& value) {
469 if constexpr (std::is_enum_v<T>) {
470 obj.set(key, static_cast<int64_t>(value.value));
471 } else {
472 obj.set(key, value.value);
473 }
474 }
475 };
476} // realm
477#endif//CPPREALM_ACCESSORS_HPP
478
Definition: accessors.hpp:33
Definition: types.hpp:75
Definition: col_key.hpp:28
Definition: mixed.hpp:69
Definition: obj.hpp:123
Definition: realm.hpp:67
Definition: set.hpp:48
Definition: type_info.hpp:45
Definition: results.hpp:419
Definition: obj.hpp:62
Definition: types.hpp:56
Definition: managed_primary_key.hpp:30
Definition: types.hpp:35