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