Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmcppdap/include/dap/any.h
3158 views
1
// Copyright 2019 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#ifndef dap_any_h
16
#define dap_any_h
17
18
#include "typeinfo.h"
19
20
#include <assert.h>
21
#include <stdint.h>
22
23
namespace dap {
24
25
template <typename T>
26
struct TypeOf;
27
class Deserializer;
28
class Serializer;
29
30
// any provides a type-safe container for values of any of dap type (boolean,
31
// integer, number, array, variant, any, null, dap-structs).
32
class any {
33
public:
34
// constructors
35
inline any() = default;
36
inline any(const any& other) noexcept;
37
inline any(any&& other) noexcept;
38
39
template <typename T>
40
inline any(const T& val);
41
42
// destructors
43
inline ~any();
44
45
// replaces the contained value with a null.
46
inline void reset();
47
48
// assignment
49
inline any& operator=(const any& rhs);
50
inline any& operator=(any&& rhs) noexcept;
51
template <typename T>
52
inline any& operator=(const T& val);
53
inline any& operator=(const std::nullptr_t& val);
54
55
// get() returns the contained value of the type T.
56
// If the any does not contain a value of type T, then get() will assert.
57
template <typename T>
58
inline T& get() const;
59
60
// is() returns true iff the contained value is of type T.
61
template <typename T>
62
inline bool is() const;
63
64
private:
65
friend class Deserializer;
66
friend class Serializer;
67
68
static inline void* alignUp(void* val, size_t alignment);
69
inline void alloc(size_t size, size_t align);
70
inline void free();
71
inline bool isInBuffer(void* ptr) const;
72
73
void* value = nullptr;
74
const TypeInfo* type = nullptr;
75
void* heap = nullptr; // heap allocation
76
uint8_t buffer[32]; // or internal allocation
77
};
78
79
inline any::~any() {
80
reset();
81
}
82
83
template <typename T>
84
inline any::any(const T& val) {
85
*this = val;
86
}
87
88
any::any(const any& other) noexcept : type(other.type) {
89
if (other.value != nullptr) {
90
alloc(type->size(), type->alignment());
91
type->copyConstruct(value, other.value);
92
}
93
}
94
95
any::any(any&& other) noexcept : type(other.type) {
96
if (other.isInBuffer(other.value)) {
97
alloc(type->size(), type->alignment());
98
type->copyConstruct(value, other.value);
99
} else {
100
value = other.value;
101
}
102
other.value = nullptr;
103
other.type = nullptr;
104
}
105
106
void any::reset() {
107
if (value != nullptr) {
108
type->destruct(value);
109
free();
110
}
111
value = nullptr;
112
type = nullptr;
113
}
114
115
any& any::operator=(const any& rhs) {
116
reset();
117
type = rhs.type;
118
if (rhs.value != nullptr) {
119
alloc(type->size(), type->alignment());
120
type->copyConstruct(value, rhs.value);
121
}
122
return *this;
123
}
124
125
any& any::operator=(any&& rhs) noexcept {
126
reset();
127
type = rhs.type;
128
if (rhs.isInBuffer(rhs.value)) {
129
alloc(type->size(), type->alignment());
130
type->copyConstruct(value, rhs.value);
131
} else {
132
value = rhs.value;
133
}
134
rhs.value = nullptr;
135
rhs.type = nullptr;
136
return *this;
137
}
138
139
template <typename T>
140
any& any::operator=(const T& val) {
141
if (!is<T>()) {
142
reset();
143
type = TypeOf<T>::type();
144
alloc(type->size(), type->alignment());
145
type->copyConstruct(value, &val);
146
} else {
147
#ifdef __clang_analyzer__
148
assert(value != nullptr);
149
#endif
150
*reinterpret_cast<T*>(value) = val;
151
}
152
return *this;
153
}
154
155
any& any::operator=(const std::nullptr_t&) {
156
reset();
157
return *this;
158
}
159
160
template <typename T>
161
T& any::get() const {
162
static_assert(!std::is_same<T, std::nullptr_t>::value,
163
"Cannot get nullptr from 'any'.");
164
assert(is<T>());
165
return *reinterpret_cast<T*>(value);
166
}
167
168
template <typename T>
169
bool any::is() const {
170
return type == TypeOf<T>::type();
171
}
172
173
template <>
174
inline bool any::is<std::nullptr_t>() const {
175
return value == nullptr;
176
}
177
178
void* any::alignUp(void* val, size_t alignment) {
179
auto ptr = reinterpret_cast<uintptr_t>(val);
180
return reinterpret_cast<void*>(alignment *
181
((ptr + alignment - 1) / alignment));
182
}
183
184
void any::alloc(size_t size, size_t align) {
185
assert(value == nullptr);
186
value = alignUp(buffer, align);
187
if (isInBuffer(reinterpret_cast<uint8_t*>(value) + size - 1)) {
188
return;
189
}
190
heap = new uint8_t[size + align];
191
value = alignUp(heap, align);
192
}
193
194
void any::free() {
195
assert(value != nullptr);
196
if (heap != nullptr) {
197
delete[] reinterpret_cast<uint8_t*>(heap);
198
heap = nullptr;
199
}
200
value = nullptr;
201
}
202
203
bool any::isInBuffer(void* ptr) const {
204
auto addr = reinterpret_cast<uintptr_t>(ptr);
205
return addr >= reinterpret_cast<uintptr_t>(buffer) &&
206
addr < reinterpret_cast<uintptr_t>(buffer + sizeof(buffer));
207
}
208
209
} // namespace dap
210
211
#endif // dap_any_h
212
213