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