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