Commit | Line | Data |
---|---|---|
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 | ||
11 | #include <common/macros.hpp> | |
12 | ||
13 | #include <cstddef> | |
14 | #include <iterator> | |
15 | ||
16 | namespace lttng { | |
17 | namespace utils { | |
18 | ||
19 | /* | |
20 | * random_access_container_wrapper is a helper to provide an idiomatic C++ interface | |
21 | * from a C container API. ElementAccessorCallable and ElementCountAccessorCallable | |
22 | * are two functors which must be provided to allow access to the underlying elements | |
23 | * of the container and to its size. | |
24 | */ | |
25 | template <typename ContainerType, typename ElementType, typename ContainerOperations> | |
26 | class random_access_container_wrapper { | |
f74e820c | 27 | template <typename IteratorContainerType, typename IteratorElementType> |
b17ed2ad JG |
28 | class _iterator : public std::iterator<std::random_access_iterator_tag, std::size_t> { |
29 | public: | |
f74e820c | 30 | explicit _iterator(IteratorContainerType& container, std::size_t start_index = 0) : |
b17ed2ad JG |
31 | _container(container), _index(start_index) |
32 | { | |
33 | } | |
34 | ||
35 | _iterator& operator++() noexcept | |
36 | { | |
37 | ++_index; | |
38 | return *this; | |
39 | } | |
40 | ||
41 | _iterator& operator--() noexcept | |
42 | { | |
43 | --_index; | |
44 | return *this; | |
45 | } | |
46 | ||
47 | _iterator& operator++(int) noexcept | |
48 | { | |
49 | auto this_before_increment = *this; | |
50 | ||
51 | _index++; | |
52 | return this_before_increment; | |
53 | } | |
54 | ||
55 | _iterator& operator--(int) noexcept | |
56 | { | |
57 | _index--; | |
58 | return *this; | |
59 | } | |
60 | ||
61 | bool operator==(const _iterator& other) const noexcept | |
62 | { | |
63 | return _index == other._index; | |
64 | } | |
65 | ||
66 | bool operator!=(const _iterator& other) const noexcept | |
67 | { | |
68 | return !(*this == other); | |
69 | } | |
70 | ||
f74e820c JG |
71 | typename std::conditional<std::is_pointer<IteratorElementType>::value, |
72 | IteratorElementType, | |
73 | IteratorElementType&>::type | |
b17ed2ad JG |
74 | operator*() const noexcept |
75 | { | |
76 | return _container[_index]; | |
77 | } | |
78 | ||
79 | private: | |
f74e820c | 80 | IteratorContainerType& _container; |
b17ed2ad JG |
81 | std::size_t _index; |
82 | }; | |
83 | ||
f74e820c JG |
84 | using iterator = _iterator<random_access_container_wrapper, ElementType>; |
85 | using const_iterator = _iterator<const random_access_container_wrapper, const ElementType>; | |
b17ed2ad JG |
86 | |
87 | public: | |
f74e820c JG |
88 | explicit random_access_container_wrapper(ContainerType container) : |
89 | _container{ std::move(container) } | |
b17ed2ad JG |
90 | { |
91 | } | |
92 | ||
93 | iterator begin() noexcept | |
94 | { | |
95 | return iterator(*this); | |
96 | } | |
97 | ||
98 | iterator end() noexcept | |
99 | { | |
100 | return iterator(*this, ContainerOperations::size(_container)); | |
101 | } | |
102 | ||
f74e820c JG |
103 | const_iterator begin() const noexcept |
104 | { | |
105 | return const_iterator(*this); | |
106 | } | |
107 | ||
108 | const_iterator end() const noexcept | |
109 | { | |
110 | return const_iterator(*this, ContainerOperations::size(_container)); | |
111 | } | |
112 | ||
b17ed2ad JG |
113 | std::size_t size() const noexcept |
114 | { | |
115 | return ContainerOperations::size(_container); | |
116 | } | |
117 | ||
118 | typename std::conditional<std::is_pointer<ElementType>::value, ElementType, ElementType&>::type | |
119 | operator[](std::size_t index) | |
120 | { | |
121 | LTTNG_ASSERT(index < ContainerOperations::size(_container)); | |
122 | return ContainerOperations::get(_container, index); | |
123 | } | |
124 | ||
125 | typename std::conditional<std::is_pointer<ElementType>::value, | |
126 | const ElementType, | |
127 | const ElementType&>::type | |
128 | operator[](std::size_t index) const | |
129 | { | |
130 | LTTNG_ASSERT(index < ContainerOperations::size(_container)); | |
131 | return ContainerOperations::get(_container, index); | |
132 | } | |
133 | ||
f74e820c | 134 | protected: |
b17ed2ad JG |
135 | ContainerType _container; |
136 | }; | |
137 | } /* namespace utils */ | |
138 | } /* namespace lttng */ | |
139 | ||
140 | #endif /* LTTNG_CONTAINER_WRAPPER_H */ |