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