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