1.3.64
 
Loading...
Searching...
No Matches
IndexTypes.h
Go to the documentation of this file.
1
16#ifndef HELIOS_INDEX_TYPES_H
17#define HELIOS_INDEX_TYPES_H
18
19#include <cstddef>
20#include <vector>
21#include <stdexcept>
22#include <algorithm>
23#include <iostream>
24
25namespace helios {
26
27 // ========== Strong Index Types ==========
28
50
52 explicit constexpr PrimitiveUUID(uint v) : value(v) {
53 }
54
56 explicit operator uint() const {
57 return value;
58 }
59
61 constexpr bool operator==(const PrimitiveUUID &other) const {
62 return value == other.value;
63 }
64 constexpr bool operator!=(const PrimitiveUUID &other) const {
65 return value != other.value;
66 }
67 };
68
83 size_t value;
84
86 explicit constexpr ArrayPosition(size_t v) : value(v) {
87 }
88
90 constexpr operator size_t() const {
91 return value;
92 }
93
95 constexpr bool operator==(const ArrayPosition &other) const {
96 return value == other.value;
97 }
98 constexpr bool operator!=(const ArrayPosition &other) const {
99 return value != other.value;
100 }
101 };
102
104 constexpr ArrayPosition INVALID_POSITION{SIZE_MAX};
105
106 // ========== UUID ↔ Position Mapper ==========
107
134 private:
135 std::vector<size_t> uuid_to_position_;
136 std::vector<uint> position_to_uuid_;
137
138#ifndef NDEBUG
139 bool debug_validation_enabled_ = true;
140#endif
141
142 public:
156 void build(const std::vector<uint> &primitive_uuids) {
157 position_to_uuid_ = primitive_uuids;
158
159 if (primitive_uuids.empty()) {
160 uuid_to_position_.clear();
161 return;
162 }
163
164 // Find max UUID to size sparse array
165 uint max_uuid = *std::max_element(primitive_uuids.begin(), primitive_uuids.end());
166 uuid_to_position_.assign(max_uuid + 1, SIZE_MAX);
167
168 // Populate UUID → position mapping
169 for (size_t pos = 0; pos < primitive_uuids.size(); ++pos) {
170 uuid_to_position_[primitive_uuids[pos]] = pos;
171 }
172 }
173
191 if (uuid.value >= uuid_to_position_.size()) {
192 return INVALID_POSITION;
193 }
194
195 size_t pos = uuid_to_position_[uuid.value];
196 if (pos == SIZE_MAX) {
197 return INVALID_POSITION;
198 }
199
200 return ArrayPosition{pos};
201 }
202
218 if (pos.value >= position_to_uuid_.size()) {
219 throw std::out_of_range("ArrayPosition " + std::to_string(pos.value) + " out of range [0, " + std::to_string(position_to_uuid_.size()) + ")");
220 }
221 return PrimitiveUUID{position_to_uuid_[pos.value]};
222 }
223
236 bool isValidUUID(PrimitiveUUID uuid) const {
237 return toPosition(uuid) != INVALID_POSITION;
238 }
239
245 size_t getPrimitiveCount() const {
246 return position_to_uuid_.size();
247 }
248
252 bool empty() const {
253 return position_to_uuid_.empty();
254 }
255 };
256
257 // ========== Debug Validation (compiled out in release builds) ==========
258
259#ifndef NDEBUG
260
278 private:
279 const UUIDPositionMapper *mapper_;
280
281 public:
283 explicit IndexValidator(const UUIDPositionMapper *mapper) : mapper_(mapper) {
284 }
285
293 void validatePosition(size_t value, const char *context) const {
294 if (value >= mapper_->getPrimitiveCount()) {
295 throw std::runtime_error(std::string(context) + ": Position " + std::to_string(value) + " out of range [0, " + std::to_string(mapper_->getPrimitiveCount()) + ")");
296 }
297 }
298
308 void warnPossibleMixup(size_t value, const char *context) const {
309 if (value >= mapper_->getPrimitiveCount()) {
310 PrimitiveUUID test_uuid{static_cast<uint>(value)};
311 if (mapper_->isValidUUID(test_uuid)) {
312 std::cerr << "WARNING [" << context << "]: Value " << value << " looks like UUID but used as position\n";
313 }
314 }
315 }
316 };
317
319#define VALIDATE_POSITION(mapper, pos, ctx) IndexValidator(mapper).validatePosition(pos, ctx)
320
322#define WARN_UUID_MIXUP(mapper, val, ctx) IndexValidator(mapper).warnPossibleMixup(val, ctx)
323
324#else
326#define VALIDATE_POSITION(mapper, pos, ctx) ((void) 0)
328#define WARN_UUID_MIXUP(mapper, val, ctx) ((void) 0)
329#endif
330
331} // namespace helios
332
333#endif // HELIOS_INDEX_TYPES_H