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