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