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