314111836c96157dcf8acc4a037bd3b112e2397d
[babeltrace.git] / src / cpp-common / bt2 / value.hpp
1 /*
2 * Copyright (c) 2020 Philippe Proulx <pproulx@efficios.com>
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7 #ifndef BABELTRACE_CPP_COMMON_BT2_VALUE_HPP
8 #define BABELTRACE_CPP_COMMON_BT2_VALUE_HPP
9
10 #include <type_traits>
11 #include <cstdint>
12 #include <functional>
13 #include <babeltrace2/babeltrace.h>
14
15 #include "common/assert.h"
16 #include "common/common.h"
17 #include "internal/borrowed-obj.hpp"
18 #include "internal/shared-obj.hpp"
19 #include "internal/utils.hpp"
20 #include "cpp-common/optional.hpp"
21 #include "cpp-common/string_view.hpp"
22 #include "lib-error.hpp"
23
24 namespace bt2 {
25
26 namespace internal {
27
28 struct ValueRefFuncs final
29 {
30 static void get(const bt_value * const libObjPtr)
31 {
32 bt_value_get_ref(libObjPtr);
33 }
34
35 static void put(const bt_value * const libObjPtr)
36 {
37 bt_value_put_ref(libObjPtr);
38 }
39 };
40
41 template <typename ObjT, typename LibObjT>
42 using SharedValue = internal::SharedObj<ObjT, LibObjT, internal::ValueRefFuncs>;
43
44 } // namespace internal
45
46 template <typename LibObjT>
47 class CommonNullValue;
48
49 template <typename LibObjT>
50 class CommonBoolValue;
51
52 template <typename LibObjT>
53 class CommonUnsignedIntegerValue;
54
55 template <typename LibObjT>
56 class CommonSignedIntegerValue;
57
58 template <typename LibObjT>
59 class CommonRealValue;
60
61 template <typename LibObjT>
62 class CommonStringValue;
63
64 template <typename LibObjT>
65 class CommonArrayValue;
66
67 template <typename LibObjT>
68 class CommonMapValue;
69
70 enum class ValueType
71 {
72 NUL = BT_VALUE_TYPE_NULL,
73 BOOL = BT_VALUE_TYPE_BOOL,
74 UNSIGNED_INTEGER = BT_VALUE_TYPE_UNSIGNED_INTEGER,
75 SIGNED_INTEGER = BT_VALUE_TYPE_SIGNED_INTEGER,
76 REAL = BT_VALUE_TYPE_REAL,
77 STRING = BT_VALUE_TYPE_STRING,
78 ARRAY = BT_VALUE_TYPE_ARRAY,
79 MAP = BT_VALUE_TYPE_MAP,
80 };
81
82 template <typename LibObjT>
83 class CommonValue : public internal::BorrowedObj<LibObjT>
84 {
85 // Allow append() to call `val._libObjPtr()`
86 friend class CommonArrayValue<bt_value>;
87
88 // Allow insert() to call `val._libObjPtr()`
89 friend class CommonMapValue<bt_value>;
90
91 // Allow operator==() to call `other._libObjPtr()`
92 friend class CommonValue<bt_value>;
93 friend class CommonValue<const bt_value>;
94
95 private:
96 using typename internal::BorrowedObj<LibObjT>::_ThisBorrowedObj;
97
98 protected:
99 using typename internal::BorrowedObj<LibObjT>::_LibObjPtr;
100 using _ThisCommonValue = CommonValue<LibObjT>;
101
102 public:
103 using Shared = internal::SharedValue<CommonValue<LibObjT>, LibObjT>;
104
105 explicit CommonValue(const _LibObjPtr libObjPtr) noexcept : _ThisBorrowedObj {libObjPtr}
106 {
107 }
108
109 template <typename OtherLibObjT>
110 CommonValue(const CommonValue<OtherLibObjT>& val) noexcept : _ThisBorrowedObj {val}
111 {
112 }
113
114 template <typename OtherLibObjT>
115 _ThisCommonValue& operator=(const CommonValue<OtherLibObjT>& val) noexcept
116 {
117 _ThisBorrowedObj::operator=(val);
118 return *this;
119 }
120
121 ValueType type() const noexcept
122 {
123 return static_cast<ValueType>(bt_value_get_type(this->_libObjPtr()));
124 }
125
126 bool isNull() const noexcept
127 {
128 return this->_libTypeIs(BT_VALUE_TYPE_NULL);
129 }
130
131 bool isBool() const noexcept
132 {
133 return this->_libTypeIs(BT_VALUE_TYPE_BOOL);
134 }
135
136 bool isInteger() const noexcept
137 {
138 return this->_libTypeIs(BT_VALUE_TYPE_INTEGER);
139 }
140
141 bool isUnsignedInteger() const noexcept
142 {
143 return this->_libTypeIs(BT_VALUE_TYPE_UNSIGNED_INTEGER);
144 }
145
146 bool isSignedInteger() const noexcept
147 {
148 return this->_libTypeIs(BT_VALUE_TYPE_SIGNED_INTEGER);
149 }
150
151 bool isReal() const noexcept
152 {
153 return this->_libTypeIs(BT_VALUE_TYPE_REAL);
154 }
155
156 bool isString() const noexcept
157 {
158 return this->_libTypeIs(BT_VALUE_TYPE_STRING);
159 }
160
161 bool isArray() const noexcept
162 {
163 return this->_libTypeIs(BT_VALUE_TYPE_ARRAY);
164 }
165
166 bool isMap() const noexcept
167 {
168 return this->_libTypeIs(BT_VALUE_TYPE_MAP);
169 }
170
171 template <typename OtherLibObjT>
172 bool operator==(const CommonValue<OtherLibObjT>& other) const noexcept
173 {
174 return static_cast<bool>(bt_value_is_equal(this->_libObjPtr(), other._libObjPtr()));
175 }
176
177 template <typename OtherLibObjT>
178 bool operator!=(const CommonValue<OtherLibObjT>& other) const noexcept
179 {
180 return !(*this == other);
181 }
182
183 Shared shared() const noexcept
184 {
185 return Shared {*this};
186 }
187
188 CommonNullValue<LibObjT> asNull() const noexcept;
189 CommonBoolValue<LibObjT> asBool() const noexcept;
190 CommonSignedIntegerValue<LibObjT> asSignedInteger() const noexcept;
191 CommonUnsignedIntegerValue<LibObjT> asUnsignedInteger() const noexcept;
192 CommonRealValue<LibObjT> asReal() const noexcept;
193 CommonStringValue<LibObjT> asString() const noexcept;
194 CommonArrayValue<LibObjT> asArray() const noexcept;
195 CommonMapValue<LibObjT> asMap() const noexcept;
196
197 protected:
198 bool _libTypeIs(const bt_value_type type) const noexcept
199 {
200 return bt_value_type_is(bt_value_get_type(this->_libObjPtr()), type);
201 }
202 };
203
204 using Value = CommonValue<bt_value>;
205 using ConstValue = CommonValue<const bt_value>;
206
207 template <typename LibObjT>
208 class CommonNullValue final : public CommonValue<LibObjT>
209 {
210 private:
211 using typename CommonValue<LibObjT>::_ThisCommonValue;
212
213 public:
214 using Shared = internal::SharedValue<CommonNullValue<LibObjT>, LibObjT>;
215
216 CommonNullValue() noexcept : _ThisCommonValue {bt_value_null}
217 {
218 }
219
220 template <typename OtherLibObjT>
221 CommonNullValue(const CommonNullValue<OtherLibObjT>& val) noexcept : _ThisCommonValue {val}
222 {
223 }
224
225 template <typename OtherLibObjT>
226 CommonNullValue<LibObjT>& operator=(const CommonNullValue<OtherLibObjT>& val) noexcept
227 {
228 _ThisCommonValue::operator=(val);
229 return *this;
230 }
231
232 Shared shared() const noexcept
233 {
234 return Shared {*this};
235 }
236 };
237
238 using NullValue = CommonNullValue<bt_value>;
239 using ConstNullValue = CommonNullValue<const bt_value>;
240
241 template <typename LibObjT>
242 class CommonBoolValue final : public CommonValue<LibObjT>
243 {
244 private:
245 using typename CommonValue<LibObjT>::_LibObjPtr;
246 using typename CommonValue<LibObjT>::_ThisCommonValue;
247
248 public:
249 using Shared = internal::SharedValue<CommonBoolValue<LibObjT>, LibObjT>;
250 using Value = bool;
251
252 explicit CommonBoolValue(const _LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
253 {
254 BT_ASSERT_DBG(this->isBool());
255 }
256
257 template <typename OtherLibObjT>
258 CommonBoolValue(const CommonBoolValue<OtherLibObjT>& val) noexcept : _ThisCommonValue {val}
259 {
260 }
261
262 static Shared create(const Value rawVal = false)
263 {
264 const auto libObjPtr = bt_value_bool_create_init(static_cast<bt_bool>(rawVal));
265
266 internal::validateCreatedObjPtr(libObjPtr);
267 return Shared {CommonBoolValue<LibObjT> {libObjPtr}};
268 }
269
270 template <typename OtherLibObjT>
271 CommonBoolValue<LibObjT>& operator=(const CommonBoolValue<OtherLibObjT>& val) noexcept
272 {
273 _ThisCommonValue::operator=(val);
274 return *this;
275 }
276
277 CommonBoolValue<LibObjT>& operator=(const Value rawVal) noexcept
278 {
279 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
280
281 bt_value_bool_set(this->_libObjPtr(), static_cast<bt_bool>(rawVal));
282 return *this;
283 }
284
285 Value value() const noexcept
286 {
287 return static_cast<Value>(bt_value_bool_get(this->_libObjPtr()));
288 }
289
290 operator Value() const noexcept
291 {
292 return this->value();
293 }
294
295 Shared shared() const noexcept
296 {
297 return Shared {*this};
298 }
299 };
300
301 using BoolValue = CommonBoolValue<bt_value>;
302 using ConstBoolValue = CommonBoolValue<const bt_value>;
303
304 template <typename LibObjT>
305 class CommonUnsignedIntegerValue final : public CommonValue<LibObjT>
306 {
307 private:
308 using typename CommonValue<LibObjT>::_LibObjPtr;
309 using typename CommonValue<LibObjT>::_ThisCommonValue;
310
311 public:
312 using Shared = internal::SharedValue<CommonUnsignedIntegerValue<LibObjT>, LibObjT>;
313 using Value = std::uint64_t;
314
315 explicit CommonUnsignedIntegerValue(const _LibObjPtr libObjPtr) noexcept :
316 _ThisCommonValue {libObjPtr}
317 {
318 BT_ASSERT_DBG(this->isUnsignedInteger());
319 }
320
321 static Shared create(const Value rawVal = 0)
322 {
323 const auto libObjPtr = bt_value_integer_unsigned_create_init(rawVal);
324
325 internal::validateCreatedObjPtr(libObjPtr);
326 return Shared {CommonUnsignedIntegerValue<LibObjT> {libObjPtr}};
327 }
328
329 template <typename OtherLibObjT>
330 CommonUnsignedIntegerValue(const CommonUnsignedIntegerValue<OtherLibObjT>& val) noexcept :
331 _ThisCommonValue {val}
332 {
333 }
334
335 template <typename OtherLibObjT>
336 CommonUnsignedIntegerValue<LibObjT>&
337 operator=(const CommonUnsignedIntegerValue<OtherLibObjT>& val) noexcept
338 {
339 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
340
341 _ThisCommonValue::operator=(val);
342 return *this;
343 }
344
345 CommonUnsignedIntegerValue<LibObjT>& operator=(const Value rawVal) noexcept
346 {
347 bt_value_integer_unsigned_set(this->_libObjPtr(), rawVal);
348 return *this;
349 }
350
351 Value value() const noexcept
352 {
353 return bt_value_integer_unsigned_get(this->_libObjPtr());
354 }
355
356 operator Value() const noexcept
357 {
358 return this->value();
359 }
360
361 Shared shared() const noexcept
362 {
363 return Shared {*this};
364 }
365 };
366
367 using UnsignedIntegerValue = CommonUnsignedIntegerValue<bt_value>;
368 using ConstUnsignedIntegerValue = CommonUnsignedIntegerValue<const bt_value>;
369
370 template <typename LibObjT>
371 class CommonSignedIntegerValue final : public CommonValue<LibObjT>
372 {
373 private:
374 using typename CommonValue<LibObjT>::_LibObjPtr;
375 using typename CommonValue<LibObjT>::_ThisCommonValue;
376
377 public:
378 using Shared = internal::SharedValue<CommonSignedIntegerValue<LibObjT>, LibObjT>;
379 using Value = std::int64_t;
380
381 explicit CommonSignedIntegerValue(const _LibObjPtr libObjPtr) noexcept :
382 _ThisCommonValue {libObjPtr}
383 {
384 BT_ASSERT_DBG(this->isSignedInteger());
385 }
386
387 static Shared create(const Value rawVal = 0)
388 {
389 const auto libObjPtr = bt_value_integer_signed_create_init(rawVal);
390
391 internal::validateCreatedObjPtr(libObjPtr);
392 return Shared {CommonSignedIntegerValue<LibObjT> {libObjPtr}};
393 }
394
395 template <typename OtherLibObjT>
396 CommonSignedIntegerValue(const CommonSignedIntegerValue<OtherLibObjT>& val) noexcept :
397 _ThisCommonValue {val}
398 {
399 }
400
401 template <typename OtherLibObjT>
402 CommonSignedIntegerValue<LibObjT>&
403 operator=(const CommonSignedIntegerValue<OtherLibObjT>& val) noexcept
404 {
405 _ThisCommonValue::operator=(val);
406 return *this;
407 }
408
409 CommonSignedIntegerValue<LibObjT>& operator=(const Value rawVal) noexcept
410 {
411 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
412
413 bt_value_integer_signed_set(this->_libObjPtr(), rawVal);
414 return *this;
415 }
416
417 Value value() const noexcept
418 {
419 return bt_value_integer_signed_get(this->_libObjPtr());
420 }
421
422 operator Value() const noexcept
423 {
424 return this->value();
425 }
426
427 Shared shared() const noexcept
428 {
429 return Shared {*this};
430 }
431 };
432
433 using SignedIntegerValue = CommonSignedIntegerValue<bt_value>;
434 using ConstSignedIntegerValue = CommonSignedIntegerValue<const bt_value>;
435
436 template <typename LibObjT>
437 class CommonRealValue final : public CommonValue<LibObjT>
438 {
439 private:
440 using typename CommonValue<LibObjT>::_LibObjPtr;
441 using typename CommonValue<LibObjT>::_ThisCommonValue;
442
443 public:
444 using Shared = internal::SharedValue<CommonRealValue<LibObjT>, LibObjT>;
445 using Value = double;
446
447 explicit CommonRealValue(const _LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
448 {
449 BT_ASSERT_DBG(this->isReal());
450 }
451
452 static Shared create(const Value rawVal = 0)
453 {
454 const auto libObjPtr = bt_value_real_create_init(rawVal);
455
456 internal::validateCreatedObjPtr(libObjPtr);
457 return Shared {CommonRealValue<LibObjT> {libObjPtr}};
458 }
459
460 template <typename OtherLibObjT>
461 CommonRealValue(const CommonRealValue<OtherLibObjT>& val) noexcept : _ThisCommonValue {val}
462 {
463 }
464
465 template <typename OtherLibObjT>
466 CommonRealValue<LibObjT>& operator=(const CommonRealValue<OtherLibObjT>& val) noexcept
467 {
468 _ThisCommonValue::operator=(val);
469 return *this;
470 }
471
472 CommonRealValue<LibObjT>& operator=(const Value rawVal) noexcept
473 {
474 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
475
476 bt_value_real_set(this->_libObjPtr(), rawVal);
477 return *this;
478 }
479
480 Value value() const noexcept
481 {
482 return bt_value_real_get(this->_libObjPtr());
483 }
484
485 operator Value() const noexcept
486 {
487 return this->value();
488 }
489
490 Shared shared() const noexcept
491 {
492 return Shared {*this};
493 }
494 };
495
496 using RealValue = CommonRealValue<bt_value>;
497 using ConstRealValue = CommonRealValue<const bt_value>;
498
499 template <typename LibObjT>
500 class CommonStringValue final : public CommonValue<LibObjT>
501 {
502 private:
503 using typename CommonValue<LibObjT>::_LibObjPtr;
504 using typename CommonValue<LibObjT>::_ThisCommonValue;
505
506 public:
507 using Shared = internal::SharedValue<CommonStringValue<LibObjT>, LibObjT>;
508
509 explicit CommonStringValue(const _LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
510 {
511 BT_ASSERT_DBG(this->isString());
512 }
513
514 static Shared create(const char * const rawVal = "")
515 {
516 const auto libObjPtr = bt_value_string_create_init(rawVal);
517
518 internal::validateCreatedObjPtr(libObjPtr);
519 return Shared {CommonStringValue<LibObjT> {libObjPtr}};
520 }
521
522 static Shared create(const std::string& rawVal)
523 {
524 return CommonStringValue<LibObjT>::create(rawVal.data());
525 }
526
527 template <typename OtherLibObjT>
528 CommonStringValue(const CommonStringValue<OtherLibObjT>& val) noexcept : _ThisCommonValue {val}
529 {
530 }
531
532 template <typename OtherLibObjT>
533 CommonStringValue<LibObjT>& operator=(const CommonStringValue<OtherLibObjT>& val) noexcept
534 {
535 _ThisCommonValue::operator=(val);
536 return *this;
537 }
538
539 CommonStringValue<LibObjT>& operator=(const char * const rawVal)
540 {
541 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
542
543 const auto status = bt_value_string_set(this->_libObjPtr(), rawVal);
544
545 if (status == BT_VALUE_STRING_SET_STATUS_MEMORY_ERROR) {
546 throw LibMemoryError {};
547 }
548
549 return *this;
550 }
551
552 CommonStringValue<LibObjT>& operator=(const std::string& rawVal) noexcept
553 {
554 return *this = rawVal.data();
555 }
556
557 bpstd::string_view value() const noexcept
558 {
559 return bt_value_string_get(this->_libObjPtr());
560 }
561
562 Shared shared() const noexcept
563 {
564 return Shared {*this};
565 }
566 };
567
568 using StringValue = CommonStringValue<bt_value>;
569 using ConstStringValue = CommonStringValue<const bt_value>;
570
571 namespace internal {
572
573 template <typename LibObjT>
574 struct CommonArrayValueSpec;
575
576 // Functions specific to mutable array values
577 template <>
578 struct CommonArrayValueSpec<bt_value> final
579 {
580 static bt_value *elementByIndex(bt_value * const libValPtr, const std::uint64_t index) noexcept
581 {
582 return bt_value_array_borrow_element_by_index(libValPtr, index);
583 }
584 };
585
586 // Functions specific to constant array values
587 template <>
588 struct CommonArrayValueSpec<const bt_value> final
589 {
590 static const bt_value *elementByIndex(const bt_value * const libValPtr,
591 const std::uint64_t index) noexcept
592 {
593 return bt_value_array_borrow_element_by_index_const(libValPtr, index);
594 }
595 };
596
597 } // namespace internal
598
599 template <typename LibObjT>
600 class CommonArrayValue final : public CommonValue<LibObjT>
601 {
602 private:
603 using typename CommonValue<LibObjT>::_LibObjPtr;
604 using typename CommonValue<LibObjT>::_ThisCommonValue;
605
606 public:
607 using Shared = internal::SharedValue<CommonArrayValue<LibObjT>, LibObjT>;
608
609 explicit CommonArrayValue(const _LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
610 {
611 BT_ASSERT_DBG(this->isArray());
612 }
613
614 static Shared create()
615 {
616 const auto libObjPtr = bt_value_array_create();
617
618 internal::validateCreatedObjPtr(libObjPtr);
619 return Shared {CommonArrayValue<LibObjT> {libObjPtr}};
620 }
621
622 template <typename OtherLibObjT>
623 CommonArrayValue(const CommonArrayValue<OtherLibObjT>& val) noexcept : _ThisCommonValue {val}
624 {
625 }
626
627 template <typename OtherLibObjT>
628 CommonArrayValue<LibObjT>& operator=(const CommonArrayValue<OtherLibObjT>& val) noexcept
629 {
630 _ThisCommonValue::operator=(val);
631 return *this;
632 }
633
634 std::uint64_t length() const noexcept
635 {
636 return bt_value_array_get_length(this->_libObjPtr());
637 }
638
639 bool isEmpty() const noexcept
640 {
641 return this->length() == 0;
642 }
643
644 ConstValue operator[](const std::uint64_t index) const noexcept
645 {
646 return ConstValue {internal::CommonArrayValueSpec<const bt_value>::elementByIndex(
647 this->_libObjPtr(), index)};
648 }
649
650 CommonValue<LibObjT> operator[](const std::uint64_t index) noexcept
651 {
652 return CommonValue<LibObjT> {
653 internal::CommonArrayValueSpec<LibObjT>::elementByIndex(this->_libObjPtr(), index)};
654 }
655
656 void append(const Value& val)
657 {
658 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
659
660 const auto status = bt_value_array_append_element(this->_libObjPtr(), val._libObjPtr());
661
662 this->_handleAppendLibStatus(status);
663 }
664
665 void append(const bool rawVal)
666 {
667 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
668
669 const auto status =
670 bt_value_array_append_bool_element(this->_libObjPtr(), static_cast<bt_bool>(rawVal));
671
672 this->_handleAppendLibStatus(status);
673 }
674
675 void append(const std::uint64_t rawVal)
676 {
677 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
678
679 const auto status =
680 bt_value_array_append_unsigned_integer_element(this->_libObjPtr(), rawVal);
681
682 this->_handleAppendLibStatus(status);
683 }
684
685 void append(const std::int64_t rawVal)
686 {
687 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
688
689 const auto status =
690 bt_value_array_append_signed_integer_element(this->_libObjPtr(), rawVal);
691
692 this->_handleAppendLibStatus(status);
693 }
694
695 void append(const double rawVal)
696 {
697 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
698
699 const auto status = bt_value_array_append_real_element(this->_libObjPtr(), rawVal);
700
701 this->_handleAppendLibStatus(status);
702 }
703
704 void append(const char * const rawVal)
705 {
706 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
707
708 const auto status = bt_value_array_append_string_element(this->_libObjPtr(), rawVal);
709
710 this->_handleAppendLibStatus(status);
711 }
712
713 void append(const std::string& rawVal)
714 {
715 this->append(rawVal.data());
716 }
717
718 CommonArrayValue<bt_value> appendEmptyArray();
719 CommonMapValue<bt_value> appendEmptyMap();
720
721 void operator+=(const Value& val)
722 {
723 this->append(val);
724 }
725
726 void operator+=(const bool rawVal)
727 {
728 this->append(rawVal);
729 }
730
731 void operator+=(const std::uint64_t rawVal)
732 {
733 this->append(rawVal);
734 }
735
736 void operator+=(const std::int64_t rawVal)
737 {
738 this->append(rawVal);
739 }
740
741 void operator+=(const double rawVal)
742 {
743 this->append(rawVal);
744 }
745
746 void operator+=(const char * const rawVal)
747 {
748 this->append(rawVal);
749 }
750
751 void operator+=(const std::string& rawVal)
752 {
753 this->append(rawVal);
754 }
755
756 Shared shared() const noexcept
757 {
758 return Shared {*this};
759 }
760
761 private:
762 void _handleAppendLibStatus(const bt_value_array_append_element_status status) const
763 {
764 if (status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_MEMORY_ERROR) {
765 throw LibMemoryError {};
766 }
767 }
768 };
769
770 using ArrayValue = CommonArrayValue<bt_value>;
771 using ConstArrayValue = CommonArrayValue<const bt_value>;
772
773 namespace internal {
774
775 /*
776 * Type of a user function passed to `CommonMapValue<ObjT>::forEach()`.
777 *
778 * First argument is the entry's key, second is its value.
779 */
780 template <typename ObjT>
781 using CommonMapValueForEachUserFunc = std::function<void(const bpstd::string_view&, ObjT)>;
782
783 /*
784 * Template of a function to be passed to bt_value_map_foreach_entry()
785 * for bt_value_map_foreach_entry_const() which calls a user function.
786 *
787 * `userData` is casted to a `const` pointer to
788 * `CommonMapValueForEachUserFunc<ObjT>` (the user function to call).
789 *
790 * This function catches any exception which the user function throws
791 * and returns the `ErrorStatus` value. If there's no execption, this
792 * function returns the `OkStatus` value.
793 */
794 template <typename ObjT, typename LibObjT, typename LibStatusT, int OkStatus, int ErrorStatus>
795 LibStatusT mapValueForEachLibFunc(const char * const key, LibObjT * const libObjPtr,
796 void * const userData)
797 {
798 const auto& userFunc = *reinterpret_cast<const CommonMapValueForEachUserFunc<ObjT> *>(userData);
799
800 try {
801 userFunc(key, ObjT {libObjPtr});
802 } catch (...) {
803 return static_cast<LibStatusT>(ErrorStatus);
804 }
805
806 return static_cast<LibStatusT>(OkStatus);
807 }
808
809 template <typename LibObjT>
810 struct CommonMapValueSpec;
811
812 // Functions specific to mutable map values
813 template <>
814 struct CommonMapValueSpec<bt_value> final
815 {
816 static bt_value *entryByKey(bt_value * const libValPtr, const char * const key) noexcept
817 {
818 return bt_value_map_borrow_entry_value(libValPtr, key);
819 }
820
821 static void forEach(bt_value * const libValPtr,
822 const CommonMapValueForEachUserFunc<Value>& func)
823 {
824 const auto status = bt_value_map_foreach_entry(
825 libValPtr,
826 mapValueForEachLibFunc<Value, bt_value, bt_value_map_foreach_entry_func_status,
827 BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_OK,
828 BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_ERROR>,
829 const_cast<void *>(reinterpret_cast<const void *>(&func)));
830
831 switch (status) {
832 case BT_VALUE_MAP_FOREACH_ENTRY_STATUS_OK:
833 return;
834 case BT_VALUE_MAP_FOREACH_ENTRY_STATUS_USER_ERROR:
835 case BT_VALUE_MAP_FOREACH_ENTRY_STATUS_ERROR:
836 throw LibError {};
837 default:
838 bt_common_abort();
839 }
840 }
841 };
842
843 // Functions specific to constant map values
844 template <>
845 struct CommonMapValueSpec<const bt_value> final
846 {
847 static const bt_value *entryByKey(const bt_value * const libValPtr,
848 const char * const key) noexcept
849 {
850 return bt_value_map_borrow_entry_value_const(libValPtr, key);
851 }
852
853 static void forEach(const bt_value * const libValPtr,
854 const CommonMapValueForEachUserFunc<ConstValue>& func)
855 {
856 const auto status = bt_value_map_foreach_entry_const(
857 libValPtr,
858 mapValueForEachLibFunc<ConstValue, const bt_value,
859 bt_value_map_foreach_entry_const_func_status,
860 BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_OK,
861 BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_ERROR>,
862 const_cast<void *>(reinterpret_cast<const void *>(&func)));
863
864 switch (status) {
865 case BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_OK:
866 return;
867 case BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_USER_ERROR:
868 case BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_ERROR:
869 throw LibError {};
870 default:
871 bt_common_abort();
872 }
873 }
874 };
875
876 } // namespace internal
877
878 template <typename LibObjT>
879 class CommonMapValue final : public CommonValue<LibObjT>
880 {
881 private:
882 using typename CommonValue<LibObjT>::_LibObjPtr;
883 using typename CommonValue<LibObjT>::_ThisCommonValue;
884
885 public:
886 using Shared = internal::SharedValue<CommonMapValue<LibObjT>, LibObjT>;
887
888 explicit CommonMapValue(const _LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
889 {
890 BT_ASSERT_DBG(this->isMap());
891 }
892
893 static Shared create()
894 {
895 const auto libObjPtr = bt_value_map_create();
896
897 internal::validateCreatedObjPtr(libObjPtr);
898 return Shared {CommonMapValue<LibObjT> {libObjPtr}};
899 }
900
901 template <typename OtherLibObjT>
902 CommonMapValue(const CommonMapValue<OtherLibObjT>& val) noexcept : _ThisCommonValue {val}
903 {
904 }
905
906 template <typename OtherLibObjT>
907 CommonMapValue<LibObjT>& operator=(const CommonMapValue<OtherLibObjT>& val) noexcept
908 {
909 _ThisCommonValue::operator=(val);
910 return *this;
911 }
912
913 std::uint64_t size() const noexcept
914 {
915 return bt_value_map_get_size(this->_libObjPtr());
916 }
917
918 bool isEmpty() const noexcept
919 {
920 return this->size() == 0;
921 }
922
923 nonstd::optional<ConstValue> operator[](const char * const key) const noexcept
924 {
925 const auto libObjPtr =
926 internal::CommonMapValueSpec<const bt_value>::entryByKey(this->_libObjPtr(), key);
927
928 if (!libObjPtr) {
929 return nonstd::nullopt;
930 }
931
932 return ConstValue {libObjPtr};
933 }
934
935 nonstd::optional<ConstValue> operator[](const std::string& key) const noexcept
936 {
937 return (*this)[key.data()];
938 }
939
940 nonstd::optional<CommonValue<LibObjT>> operator[](const char * const key) noexcept
941 {
942 const auto libObjPtr =
943 internal::CommonMapValueSpec<LibObjT>::entryByKey(this->_libObjPtr(), key);
944
945 if (!libObjPtr) {
946 return nonstd::nullopt;
947 }
948
949 return CommonValue<LibObjT> {libObjPtr};
950 }
951
952 nonstd::optional<CommonValue<LibObjT>> operator[](const std::string& key) noexcept
953 {
954 return (*this)[key.data()];
955 }
956
957 bool hasEntry(const char * const key) const noexcept
958 {
959 return static_cast<bool>(bt_value_map_has_entry(this->_libObjPtr(), key));
960 }
961
962 bool hasEntry(const std::string& key) const noexcept
963 {
964 return this->hasEntry(key.data());
965 }
966
967 void insert(const char * const key, const Value& val)
968 {
969 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
970
971 const auto status = bt_value_map_insert_entry(this->_libObjPtr(), key, val._libObjPtr());
972
973 this->_handleInsertLibStatus(status);
974 }
975
976 void insert(const std::string& key, const Value& val)
977 {
978 this->insert(key.data(), val);
979 }
980
981 void insert(const char * const key, const bool rawVal)
982 {
983 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
984
985 const auto status =
986 bt_value_map_insert_bool_entry(this->_libObjPtr(), key, static_cast<bt_bool>(rawVal));
987
988 this->_handleInsertLibStatus(status);
989 }
990
991 void insert(const std::string& key, const bool rawVal)
992 {
993 this->insert(key.data(), rawVal);
994 }
995
996 void insert(const char * const key, const std::uint64_t rawVal)
997 {
998 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
999
1000 const auto status =
1001 bt_value_map_insert_unsigned_integer_entry(this->_libObjPtr(), key, rawVal);
1002
1003 this->_handleInsertLibStatus(status);
1004 }
1005
1006 void insert(const std::string& key, const std::uint64_t rawVal)
1007 {
1008 this->insert(key.data(), rawVal);
1009 }
1010
1011 void insert(const char * const key, const std::int64_t rawVal)
1012 {
1013 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1014
1015 const auto status =
1016 bt_value_map_insert_signed_integer_entry(this->_libObjPtr(), key, rawVal);
1017
1018 this->_handleInsertLibStatus(status);
1019 }
1020
1021 void insert(const std::string& key, const std::int64_t rawVal)
1022 {
1023 this->insert(key.data(), rawVal);
1024 }
1025
1026 void insert(const char * const key, const double rawVal)
1027 {
1028 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1029
1030 const auto status = bt_value_map_insert_real_entry(this->_libObjPtr(), key, rawVal);
1031
1032 this->_handleInsertLibStatus(status);
1033 }
1034
1035 void insert(const std::string& key, const double rawVal)
1036 {
1037 this->insert(key.data(), rawVal);
1038 }
1039
1040 void insert(const char * const key, const char * const rawVal)
1041 {
1042 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1043
1044 const auto status = bt_value_map_insert_string_entry(this->_libObjPtr(), key, rawVal);
1045
1046 this->_handleInsertLibStatus(status);
1047 }
1048
1049 void insert(const char * const key, const std::string& rawVal)
1050 {
1051 this->insert(key, rawVal.data());
1052 }
1053
1054 void insert(const std::string& key, const char * const rawVal)
1055 {
1056 this->insert(key.data(), rawVal);
1057 }
1058
1059 void insert(const std::string& key, const std::string& rawVal)
1060 {
1061 this->insert(key.data(), rawVal.data());
1062 }
1063
1064 CommonArrayValue<bt_value> insertEmptyArray(const char *key);
1065 CommonArrayValue<bt_value> insertEmptyArray(const std::string& key);
1066 CommonMapValue<bt_value> insertEmptyMap(const char *key);
1067 CommonMapValue<bt_value> insertEmptyMap(const std::string& key);
1068
1069 void forEach(const internal::CommonMapValueForEachUserFunc<ConstValue>& func) const
1070 {
1071 internal::CommonMapValueSpec<const bt_value>::forEach(this->_libObjPtr(), func);
1072 }
1073
1074 void forEach(const internal::CommonMapValueForEachUserFunc<CommonValue<LibObjT>>& func)
1075 {
1076 internal::CommonMapValueSpec<LibObjT>::forEach(this->_libObjPtr(), func);
1077 }
1078
1079 Shared shared() const noexcept
1080 {
1081 return Shared {*this};
1082 }
1083
1084 private:
1085 void _handleInsertLibStatus(const bt_value_map_insert_entry_status status) const
1086 {
1087 if (status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_MEMORY_ERROR) {
1088 throw LibMemoryError {};
1089 }
1090 }
1091 };
1092
1093 using MapValue = CommonMapValue<bt_value>;
1094 using ConstMapValue = CommonMapValue<const bt_value>;
1095
1096 template <typename LibObjT>
1097 CommonNullValue<LibObjT> CommonValue<LibObjT>::asNull() const noexcept
1098 {
1099 BT_ASSERT_DBG(this->isNull());
1100 return CommonNullValue<LibObjT> {this->_libObjPtr()};
1101 }
1102
1103 template <typename LibObjT>
1104 CommonBoolValue<LibObjT> CommonValue<LibObjT>::asBool() const noexcept
1105 {
1106 BT_ASSERT_DBG(this->isBool());
1107 return CommonBoolValue<LibObjT> {this->_libObjPtr()};
1108 }
1109
1110 template <typename LibObjT>
1111 CommonSignedIntegerValue<LibObjT> CommonValue<LibObjT>::asSignedInteger() const noexcept
1112 {
1113 BT_ASSERT_DBG(this->isSignedInteger());
1114 return CommonSignedIntegerValue<LibObjT> {this->_libObjPtr()};
1115 }
1116
1117 template <typename LibObjT>
1118 CommonUnsignedIntegerValue<LibObjT> CommonValue<LibObjT>::asUnsignedInteger() const noexcept
1119 {
1120 BT_ASSERT_DBG(this->isUnsignedInteger());
1121 return CommonUnsignedIntegerValue<LibObjT> {this->_libObjPtr()};
1122 }
1123
1124 template <typename LibObjT>
1125 CommonRealValue<LibObjT> CommonValue<LibObjT>::asReal() const noexcept
1126 {
1127 BT_ASSERT_DBG(this->isReal());
1128 return CommonRealValue<LibObjT> {this->_libObjPtr()};
1129 }
1130
1131 template <typename LibObjT>
1132 CommonStringValue<LibObjT> CommonValue<LibObjT>::asString() const noexcept
1133 {
1134 BT_ASSERT_DBG(this->isString());
1135 return CommonStringValue<LibObjT> {this->_libObjPtr()};
1136 }
1137
1138 template <typename LibObjT>
1139 CommonArrayValue<LibObjT> CommonValue<LibObjT>::asArray() const noexcept
1140 {
1141 BT_ASSERT_DBG(this->isArray());
1142 return CommonArrayValue<LibObjT> {this->_libObjPtr()};
1143 }
1144
1145 template <typename LibObjT>
1146 CommonMapValue<LibObjT> CommonValue<LibObjT>::asMap() const noexcept
1147 {
1148 BT_ASSERT_DBG(this->isMap());
1149 return CommonMapValue<LibObjT> {this->_libObjPtr()};
1150 }
1151
1152 template <typename LibObjT>
1153 ArrayValue CommonArrayValue<LibObjT>::appendEmptyArray()
1154 {
1155 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1156
1157 bt_value *libElemPtr;
1158 const auto status = bt_value_array_append_empty_array_element(this->_libObjPtr(), &libElemPtr);
1159
1160 this->_handleAppendLibStatus(status);
1161 return ArrayValue {libElemPtr};
1162 }
1163
1164 template <typename LibObjT>
1165 MapValue CommonArrayValue<LibObjT>::appendEmptyMap()
1166 {
1167 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1168
1169 bt_value *libElemPtr;
1170 const auto status = bt_value_array_append_empty_map_element(this->_libObjPtr(), &libElemPtr);
1171
1172 this->_handleAppendLibStatus(status);
1173 return MapValue {libElemPtr};
1174 }
1175
1176 template <typename LibObjT>
1177 ArrayValue CommonMapValue<LibObjT>::insertEmptyArray(const char * const key)
1178 {
1179 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1180
1181 bt_value *libEntryPtr;
1182 const auto status =
1183 bt_value_map_insert_empty_array_entry(this->_libObjPtr(), key, &libEntryPtr);
1184
1185 this->_handleInsertLibStatus(status);
1186 return ArrayValue {libEntryPtr};
1187 }
1188
1189 template <typename LibObjT>
1190 ArrayValue CommonMapValue<LibObjT>::insertEmptyArray(const std::string& key)
1191 {
1192 return this->insertEmptyArray(key.data());
1193 }
1194
1195 template <typename LibObjT>
1196 MapValue CommonMapValue<LibObjT>::insertEmptyMap(const char * const key)
1197 {
1198 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1199
1200 bt_value *libEntryPtr;
1201 const auto status = bt_value_map_insert_empty_map_entry(this->_libObjPtr(), key, &libEntryPtr);
1202
1203 this->_handleInsertLibStatus(status);
1204 return MapValue {libEntryPtr};
1205 }
1206
1207 template <typename LibObjT>
1208 MapValue CommonMapValue<LibObjT>::insertEmptyMap(const std::string& key)
1209 {
1210 return this->insertEmptyMap(key.data());
1211 }
1212
1213 inline BoolValue::Shared createValue(const bool rawVal)
1214 {
1215 return BoolValue::create(rawVal);
1216 }
1217
1218 inline UnsignedIntegerValue::Shared createValue(const std::uint64_t rawVal)
1219 {
1220 return UnsignedIntegerValue::create(rawVal);
1221 }
1222
1223 inline SignedIntegerValue::Shared createValue(const std::int64_t rawVal)
1224 {
1225 return SignedIntegerValue::create(rawVal);
1226 }
1227
1228 inline RealValue::Shared createValue(const double rawVal)
1229 {
1230 return RealValue::create(rawVal);
1231 }
1232
1233 inline StringValue::Shared createValue(const char * const rawVal)
1234 {
1235 return StringValue::create(rawVal);
1236 }
1237
1238 inline StringValue::Shared createValue(const std::string& rawVal)
1239 {
1240 return StringValue::create(rawVal);
1241 }
1242
1243 } // namespace bt2
1244
1245 #endif // BABELTRACE_CPP_COMMON_BT2_VALUE_HPP
This page took 0.052164 seconds and 3 git commands to generate.