cpp-common: template ArrayValueIterator for reuse with other containers
[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 =
735 bt_value_array_append_signed_integer_element(this->_libObjPtr(), rawVal);
736
737 this->_handleAppendLibStatus(status);
738 }
739
740 void append(const double rawVal)
741 {
742 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
743
744 const auto status = bt_value_array_append_real_element(this->_libObjPtr(), rawVal);
745
746 this->_handleAppendLibStatus(status);
747 }
748
749 void append(const char * const rawVal)
750 {
751 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
752
753 const auto status = bt_value_array_append_string_element(this->_libObjPtr(), rawVal);
754
755 this->_handleAppendLibStatus(status);
756 }
757
758 void append(const std::string& rawVal)
759 {
760 this->append(rawVal.data());
761 }
762
763 CommonArrayValue<bt_value> appendEmptyArray();
764 CommonMapValue<bt_value> appendEmptyMap();
765
766 void operator+=(const Value& val)
767 {
768 this->append(val);
769 }
770
771 void operator+=(const bool rawVal)
772 {
773 this->append(rawVal);
774 }
775
776 void operator+=(const std::uint64_t rawVal)
777 {
778 this->append(rawVal);
779 }
780
781 void operator+=(const std::int64_t rawVal)
782 {
783 this->append(rawVal);
784 }
785
786 void operator+=(const double rawVal)
787 {
788 this->append(rawVal);
789 }
790
791 void operator+=(const char * const rawVal)
792 {
793 this->append(rawVal);
794 }
795
796 void operator+=(const std::string& rawVal)
797 {
798 this->append(rawVal);
799 }
800
801 Shared shared() const noexcept
802 {
803 return Shared {*this};
804 }
805
806 private:
807 void _handleAppendLibStatus(const bt_value_array_append_element_status status) const
808 {
809 if (status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_MEMORY_ERROR) {
810 throw LibMemoryError {};
811 }
812 }
813 };
814
815 using ArrayValue = CommonArrayValue<bt_value>;
816 using ConstArrayValue = CommonArrayValue<const bt_value>;
817
818 namespace internal {
819
820 /*
821 * Type of a user function passed to `CommonMapValue<ObjT>::forEach()`.
822 *
823 * First argument is the entry's key, second is its value.
824 */
825 template <typename ObjT>
826 using CommonMapValueForEachUserFunc = std::function<void(const bpstd::string_view&, ObjT)>;
827
828 /*
829 * Template of a function to be passed to bt_value_map_foreach_entry()
830 * for bt_value_map_foreach_entry_const() which calls a user function.
831 *
832 * `userData` is casted to a `const` pointer to
833 * `CommonMapValueForEachUserFunc<ObjT>` (the user function to call).
834 *
835 * This function catches any exception which the user function throws
836 * and returns the `ErrorStatus` value. If there's no execption, this
837 * function returns the `OkStatus` value.
838 */
839 template <typename ObjT, typename LibObjT, typename LibStatusT, int OkStatus, int ErrorStatus>
840 LibStatusT mapValueForEachLibFunc(const char * const key, LibObjT * const libObjPtr,
841 void * const userData)
842 {
843 const auto& userFunc = *reinterpret_cast<const CommonMapValueForEachUserFunc<ObjT> *>(userData);
844
845 try {
846 userFunc(key, ObjT {libObjPtr});
847 } catch (...) {
848 return static_cast<LibStatusT>(ErrorStatus);
849 }
850
851 return static_cast<LibStatusT>(OkStatus);
852 }
853
854 template <typename LibObjT>
855 struct CommonMapValueSpec;
856
857 /* Functions specific to mutable map values */
858 template <>
859 struct CommonMapValueSpec<bt_value> final
860 {
861 static bt_value *entryByKey(bt_value * const libValPtr, const char * const key) noexcept
862 {
863 return bt_value_map_borrow_entry_value(libValPtr, key);
864 }
865
866 static void forEach(bt_value * const libValPtr,
867 const CommonMapValueForEachUserFunc<Value>& func)
868 {
869 const auto status = bt_value_map_foreach_entry(
870 libValPtr,
871 mapValueForEachLibFunc<Value, bt_value, bt_value_map_foreach_entry_func_status,
872 BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_OK,
873 BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_ERROR>,
874 const_cast<void *>(reinterpret_cast<const void *>(&func)));
875
876 switch (status) {
877 case BT_VALUE_MAP_FOREACH_ENTRY_STATUS_OK:
878 return;
879 case BT_VALUE_MAP_FOREACH_ENTRY_STATUS_USER_ERROR:
880 case BT_VALUE_MAP_FOREACH_ENTRY_STATUS_ERROR:
881 throw LibError {};
882 default:
883 bt_common_abort();
884 }
885 }
886 };
887
888 /* Functions specific to constant map values */
889 template <>
890 struct CommonMapValueSpec<const bt_value> final
891 {
892 static const bt_value *entryByKey(const bt_value * const libValPtr,
893 const char * const key) noexcept
894 {
895 return bt_value_map_borrow_entry_value_const(libValPtr, key);
896 }
897
898 static void forEach(const bt_value * const libValPtr,
899 const CommonMapValueForEachUserFunc<ConstValue>& func)
900 {
901 const auto status = bt_value_map_foreach_entry_const(
902 libValPtr,
903 mapValueForEachLibFunc<ConstValue, const bt_value,
904 bt_value_map_foreach_entry_const_func_status,
905 BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_OK,
906 BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_ERROR>,
907 const_cast<void *>(reinterpret_cast<const void *>(&func)));
908
909 switch (status) {
910 case BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_OK:
911 return;
912 case BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_USER_ERROR:
913 case BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_ERROR:
914 throw LibError {};
915 default:
916 bt_common_abort();
917 }
918 }
919 };
920
921 } /* namespace internal */
922
923 template <typename LibObjT>
924 class CommonMapValue final : public CommonValue<LibObjT>
925 {
926 private:
927 using typename CommonValue<LibObjT>::_LibObjPtr;
928 using typename CommonValue<LibObjT>::_ThisCommonValue;
929
930 public:
931 using Shared = internal::SharedValue<CommonMapValue<LibObjT>, LibObjT>;
932
933 explicit CommonMapValue(const _LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
934 {
935 BT_ASSERT_DBG(this->isMap());
936 }
937
938 static Shared create()
939 {
940 const auto libObjPtr = bt_value_map_create();
941
942 internal::validateCreatedObjPtr(libObjPtr);
943 return Shared {CommonMapValue<LibObjT> {libObjPtr}};
944 }
945
946 template <typename OtherLibObjT>
947 CommonMapValue(const CommonMapValue<OtherLibObjT>& val) noexcept : _ThisCommonValue {val}
948 {
949 }
950
951 template <typename OtherLibObjT>
952 CommonMapValue<LibObjT>& operator=(const CommonMapValue<OtherLibObjT>& val) noexcept
953 {
954 _ThisCommonValue::operator=(val);
955 return *this;
956 }
957
958 std::uint64_t size() const noexcept
959 {
960 return bt_value_map_get_size(this->_libObjPtr());
961 }
962
963 bool isEmpty() const noexcept
964 {
965 return this->size() == 0;
966 }
967
968 nonstd::optional<ConstValue> operator[](const char * const key) const noexcept
969 {
970 const auto libObjPtr =
971 internal::CommonMapValueSpec<const bt_value>::entryByKey(this->_libObjPtr(), key);
972
973 if (!libObjPtr) {
974 return nonstd::nullopt;
975 }
976
977 return ConstValue {libObjPtr};
978 }
979
980 nonstd::optional<ConstValue> operator[](const std::string& key) const noexcept
981 {
982 return (*this)[key.data()];
983 }
984
985 nonstd::optional<CommonValue<LibObjT>> operator[](const char * const key) noexcept
986 {
987 const auto libObjPtr =
988 internal::CommonMapValueSpec<LibObjT>::entryByKey(this->_libObjPtr(), key);
989
990 if (!libObjPtr) {
991 return nonstd::nullopt;
992 }
993
994 return CommonValue<LibObjT> {libObjPtr};
995 }
996
997 nonstd::optional<CommonValue<LibObjT>> operator[](const std::string& key) noexcept
998 {
999 return (*this)[key.data()];
1000 }
1001
1002 bool hasEntry(const char * const key) const noexcept
1003 {
1004 return static_cast<bool>(bt_value_map_has_entry(this->_libObjPtr(), key));
1005 }
1006
1007 bool hasEntry(const std::string& key) const noexcept
1008 {
1009 return this->hasEntry(key.data());
1010 }
1011
1012 void insert(const char * const key, const Value& val)
1013 {
1014 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1015
1016 const auto status = bt_value_map_insert_entry(this->_libObjPtr(), key, val._libObjPtr());
1017
1018 this->_handleInsertLibStatus(status);
1019 }
1020
1021 void insert(const std::string& key, const Value& val)
1022 {
1023 this->insert(key.data(), val);
1024 }
1025
1026 void insert(const char * const key, const bool rawVal)
1027 {
1028 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1029
1030 const auto status =
1031 bt_value_map_insert_bool_entry(this->_libObjPtr(), key, static_cast<bt_bool>(rawVal));
1032
1033 this->_handleInsertLibStatus(status);
1034 }
1035
1036 void insert(const std::string& key, const bool rawVal)
1037 {
1038 this->insert(key.data(), rawVal);
1039 }
1040
1041 void insert(const char * const key, const std::uint64_t rawVal)
1042 {
1043 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1044
1045 const auto status =
1046 bt_value_map_insert_unsigned_integer_entry(this->_libObjPtr(), key, rawVal);
1047
1048 this->_handleInsertLibStatus(status);
1049 }
1050
1051 void insert(const std::string& key, const std::uint64_t rawVal)
1052 {
1053 this->insert(key.data(), rawVal);
1054 }
1055
1056 void insert(const char * const key, const std::int64_t rawVal)
1057 {
1058 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1059
1060 const auto status =
1061 bt_value_map_insert_signed_integer_entry(this->_libObjPtr(), key, rawVal);
1062
1063 this->_handleInsertLibStatus(status);
1064 }
1065
1066 void insert(const std::string& key, const std::int64_t rawVal)
1067 {
1068 this->insert(key.data(), rawVal);
1069 }
1070
1071 void insert(const char * const key, const double rawVal)
1072 {
1073 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1074
1075 const auto status = bt_value_map_insert_real_entry(this->_libObjPtr(), key, rawVal);
1076
1077 this->_handleInsertLibStatus(status);
1078 }
1079
1080 void insert(const std::string& key, const double rawVal)
1081 {
1082 this->insert(key.data(), rawVal);
1083 }
1084
1085 void insert(const char * const key, const char * const rawVal)
1086 {
1087 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1088
1089 const auto status = bt_value_map_insert_string_entry(this->_libObjPtr(), key, rawVal);
1090
1091 this->_handleInsertLibStatus(status);
1092 }
1093
1094 void insert(const char * const key, const std::string& rawVal)
1095 {
1096 this->insert(key, rawVal.data());
1097 }
1098
1099 void insert(const std::string& key, const char * const rawVal)
1100 {
1101 this->insert(key.data(), rawVal);
1102 }
1103
1104 void insert(const std::string& key, const std::string& rawVal)
1105 {
1106 this->insert(key.data(), rawVal.data());
1107 }
1108
1109 CommonArrayValue<bt_value> insertEmptyArray(const char *key);
1110 CommonArrayValue<bt_value> insertEmptyArray(const std::string& key);
1111 CommonMapValue<bt_value> insertEmptyMap(const char *key);
1112 CommonMapValue<bt_value> insertEmptyMap(const std::string& key);
1113
1114 void forEach(const internal::CommonMapValueForEachUserFunc<ConstValue>& func) const
1115 {
1116 internal::CommonMapValueSpec<const bt_value>::forEach(this->_libObjPtr(), func);
1117 }
1118
1119 void forEach(const internal::CommonMapValueForEachUserFunc<CommonValue<LibObjT>>& func)
1120 {
1121 internal::CommonMapValueSpec<LibObjT>::forEach(this->_libObjPtr(), func);
1122 }
1123
1124 Shared shared() const noexcept
1125 {
1126 return Shared {*this};
1127 }
1128
1129 private:
1130 void _handleInsertLibStatus(const bt_value_map_insert_entry_status status) const
1131 {
1132 if (status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_MEMORY_ERROR) {
1133 throw LibMemoryError {};
1134 }
1135 }
1136 };
1137
1138 using MapValue = CommonMapValue<bt_value>;
1139 using ConstMapValue = CommonMapValue<const bt_value>;
1140
1141 template <typename LibObjT>
1142 CommonNullValue<LibObjT> CommonValue<LibObjT>::asNull() const noexcept
1143 {
1144 BT_ASSERT_DBG(this->isNull());
1145 return CommonNullValue<LibObjT> {this->_libObjPtr()};
1146 }
1147
1148 template <typename LibObjT>
1149 CommonBoolValue<LibObjT> CommonValue<LibObjT>::asBool() const noexcept
1150 {
1151 BT_ASSERT_DBG(this->isBool());
1152 return CommonBoolValue<LibObjT> {this->_libObjPtr()};
1153 }
1154
1155 template <typename LibObjT>
1156 CommonSignedIntegerValue<LibObjT> CommonValue<LibObjT>::asSignedInteger() const noexcept
1157 {
1158 BT_ASSERT_DBG(this->isSignedInteger());
1159 return CommonSignedIntegerValue<LibObjT> {this->_libObjPtr()};
1160 }
1161
1162 template <typename LibObjT>
1163 CommonUnsignedIntegerValue<LibObjT> CommonValue<LibObjT>::asUnsignedInteger() const noexcept
1164 {
1165 BT_ASSERT_DBG(this->isUnsignedInteger());
1166 return CommonUnsignedIntegerValue<LibObjT> {this->_libObjPtr()};
1167 }
1168
1169 template <typename LibObjT>
1170 CommonRealValue<LibObjT> CommonValue<LibObjT>::asReal() const noexcept
1171 {
1172 BT_ASSERT_DBG(this->isReal());
1173 return CommonRealValue<LibObjT> {this->_libObjPtr()};
1174 }
1175
1176 template <typename LibObjT>
1177 CommonStringValue<LibObjT> CommonValue<LibObjT>::asString() const noexcept
1178 {
1179 BT_ASSERT_DBG(this->isString());
1180 return CommonStringValue<LibObjT> {this->_libObjPtr()};
1181 }
1182
1183 template <typename LibObjT>
1184 CommonArrayValue<LibObjT> CommonValue<LibObjT>::asArray() const noexcept
1185 {
1186 BT_ASSERT_DBG(this->isArray());
1187 return CommonArrayValue<LibObjT> {this->_libObjPtr()};
1188 }
1189
1190 template <typename LibObjT>
1191 CommonMapValue<LibObjT> CommonValue<LibObjT>::asMap() const noexcept
1192 {
1193 BT_ASSERT_DBG(this->isMap());
1194 return CommonMapValue<LibObjT> {this->_libObjPtr()};
1195 }
1196
1197 template <typename LibObjT>
1198 ArrayValue CommonArrayValue<LibObjT>::appendEmptyArray()
1199 {
1200 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1201
1202 bt_value *libElemPtr;
1203 const auto status = bt_value_array_append_empty_array_element(this->_libObjPtr(), &libElemPtr);
1204
1205 this->_handleAppendLibStatus(status);
1206 return ArrayValue {libElemPtr};
1207 }
1208
1209 template <typename LibObjT>
1210 MapValue CommonArrayValue<LibObjT>::appendEmptyMap()
1211 {
1212 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1213
1214 bt_value *libElemPtr;
1215 const auto status = bt_value_array_append_empty_map_element(this->_libObjPtr(), &libElemPtr);
1216
1217 this->_handleAppendLibStatus(status);
1218 return MapValue {libElemPtr};
1219 }
1220
1221 template <typename LibObjT>
1222 ArrayValue CommonMapValue<LibObjT>::insertEmptyArray(const char * const key)
1223 {
1224 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1225
1226 bt_value *libEntryPtr;
1227 const auto status =
1228 bt_value_map_insert_empty_array_entry(this->_libObjPtr(), key, &libEntryPtr);
1229
1230 this->_handleInsertLibStatus(status);
1231 return ArrayValue {libEntryPtr};
1232 }
1233
1234 template <typename LibObjT>
1235 ArrayValue CommonMapValue<LibObjT>::insertEmptyArray(const std::string& key)
1236 {
1237 return this->insertEmptyArray(key.data());
1238 }
1239
1240 template <typename LibObjT>
1241 MapValue CommonMapValue<LibObjT>::insertEmptyMap(const char * const key)
1242 {
1243 static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
1244
1245 bt_value *libEntryPtr;
1246 const auto status = bt_value_map_insert_empty_map_entry(this->_libObjPtr(), key, &libEntryPtr);
1247
1248 this->_handleInsertLibStatus(status);
1249 return MapValue {libEntryPtr};
1250 }
1251
1252 template <typename LibObjT>
1253 MapValue CommonMapValue<LibObjT>::insertEmptyMap(const std::string& key)
1254 {
1255 return this->insertEmptyMap(key.data());
1256 }
1257
1258 inline BoolValue::Shared createValue(const bool rawVal)
1259 {
1260 return BoolValue::create(rawVal);
1261 }
1262
1263 inline UnsignedIntegerValue::Shared createValue(const std::uint64_t rawVal)
1264 {
1265 return UnsignedIntegerValue::create(rawVal);
1266 }
1267
1268 inline SignedIntegerValue::Shared createValue(const std::int64_t rawVal)
1269 {
1270 return SignedIntegerValue::create(rawVal);
1271 }
1272
1273 inline RealValue::Shared createValue(const double rawVal)
1274 {
1275 return RealValue::create(rawVal);
1276 }
1277
1278 inline StringValue::Shared createValue(const char * const rawVal)
1279 {
1280 return StringValue::create(rawVal);
1281 }
1282
1283 inline StringValue::Shared createValue(const std::string& rawVal)
1284 {
1285 return StringValue::create(rawVal);
1286 }
1287
1288 } /* namespace bt2 */
1289
1290 #endif /* BABELTRACE_CPP_COMMON_BT2_VALUE_HPP */
This page took 0.057336 seconds and 5 git commands to generate.