Clean-up: tests: bt2 plug-ins: modernize the plug-ins
[lttng-tools.git] / src / common / container-wrapper.hpp
CommitLineData
b17ed2ad
JG
1/*
2 * Copyright (C) 2023 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8#ifndef LTTNG_CONTAINER_WRAPPER_H
9#define LTTNG_CONTAINER_WRAPPER_H
10
feef6f74
JG
11#include <common/exception.hpp>
12#include <common/format.hpp>
b17ed2ad
JG
13#include <common/macros.hpp>
14
15#include <cstddef>
16#include <iterator>
17
18namespace lttng {
19namespace utils {
20
21/*
22 * random_access_container_wrapper is a helper to provide an idiomatic C++ interface
23 * from a C container API. ElementAccessorCallable and ElementCountAccessorCallable
24 * are two functors which must be provided to allow access to the underlying elements
25 * of the container and to its size.
26 */
27template <typename ContainerType, typename ElementType, typename ContainerOperations>
28class random_access_container_wrapper {
f74e820c 29 template <typename IteratorContainerType, typename IteratorElementType>
b17ed2ad
JG
30 class _iterator : public std::iterator<std::random_access_iterator_tag, std::size_t> {
31 public:
f74e820c 32 explicit _iterator(IteratorContainerType& container, std::size_t start_index = 0) :
b17ed2ad
JG
33 _container(container), _index(start_index)
34 {
35 }
36
37 _iterator& operator++() noexcept
38 {
39 ++_index;
40 return *this;
41 }
42
43 _iterator& operator--() noexcept
44 {
45 --_index;
46 return *this;
47 }
48
49 _iterator& operator++(int) noexcept
50 {
51 auto this_before_increment = *this;
52
53 _index++;
54 return this_before_increment;
55 }
56
57 _iterator& operator--(int) noexcept
58 {
59 _index--;
60 return *this;
61 }
62
63 bool operator==(const _iterator& other) const noexcept
64 {
65 return _index == other._index;
66 }
67
68 bool operator!=(const _iterator& other) const noexcept
69 {
70 return !(*this == other);
71 }
72
f74e820c
JG
73 typename std::conditional<std::is_pointer<IteratorElementType>::value,
74 IteratorElementType,
75 IteratorElementType&>::type
feef6f74 76 operator*() const
b17ed2ad
JG
77 {
78 return _container[_index];
79 }
80
81 private:
f74e820c 82 IteratorContainerType& _container;
b17ed2ad
JG
83 std::size_t _index;
84 };
85
f74e820c
JG
86 using iterator = _iterator<random_access_container_wrapper, ElementType>;
87 using const_iterator = _iterator<const random_access_container_wrapper, const ElementType>;
b17ed2ad
JG
88
89public:
f74e820c
JG
90 explicit random_access_container_wrapper(ContainerType container) :
91 _container{ std::move(container) }
b17ed2ad
JG
92 {
93 }
94
95 iterator begin() noexcept
96 {
97 return iterator(*this);
98 }
99
feef6f74 100 iterator end()
b17ed2ad 101 {
58561706 102 return iterator(*this, size());
b17ed2ad
JG
103 }
104
f74e820c
JG
105 const_iterator begin() const noexcept
106 {
107 return const_iterator(*this);
108 }
109
feef6f74 110 const_iterator end() const
f74e820c 111 {
58561706 112 return const_iterator(*this, size());
f74e820c
JG
113 }
114
58561706 115 std::size_t size() const
b17ed2ad
JG
116 {
117 return ContainerOperations::size(_container);
118 }
119
d73aeddd
JG
120 bool empty() const
121 {
122 return size() == 0;
123 }
124
b17ed2ad
JG
125 typename std::conditional<std::is_pointer<ElementType>::value, ElementType, ElementType&>::type
126 operator[](std::size_t index)
127 {
feef6f74
JG
128 /*
129 * To share code between the const and mutable versions of this operator, 'this'
130 * is casted to a const reference. A const_cast then ensures that a mutable
131 * reference (or pointer) is returned.
132 *
133 * We typically avoid const_cast, but this is safe: if the user is calling the
134 * mutable version of this operator, it had a mutable object anyhow.
135 *
136 * For more information, see Item 3 of Effective C++.
137 */
69e98ad6 138 const auto& const_this = static_cast<const random_access_container_wrapper&>(*this);
feef6f74
JG
139
140 /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) */
141 return const_cast<typename std::conditional<std::is_pointer<ElementType>::value,
142 ElementType,
143 ElementType&>::type>(const_this[index]);
b17ed2ad
JG
144 }
145
146 typename std::conditional<std::is_pointer<ElementType>::value,
147 const ElementType,
148 const ElementType&>::type
149 operator[](std::size_t index) const
150 {
feef6f74 151 if (index >= ContainerOperations::size(_container)) {
d73aeddd 152 throw std::invalid_argument(lttng::format(
feef6f74
JG
153 "Out of bound access through random_access_container_wrapper: index={}, size={}",
154 index,
155 size()));
156 }
157
b17ed2ad
JG
158 return ContainerOperations::get(_container, index);
159 }
160
f74e820c 161protected:
b17ed2ad
JG
162 ContainerType _container;
163};
164} /* namespace utils */
165} /* namespace lttng */
166
167#endif /* LTTNG_CONTAINER_WRAPPER_H */
This page took 0.034179 seconds and 4 git commands to generate.