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