cesium-native 0.57.0
Loading...
Searching...
No Matches
PropertyArrayView.h
1#pragma once
2
3#include <CesiumGltf/PropertyType.h>
4#include <CesiumGltf/getOffsetFromOffsetsBuffer.h>
5#include <CesiumUtility/SpanHelper.h>
6
7#include <cstddef>
8#include <cstring>
9#include <span>
10#include <vector>
11
12namespace CesiumGltf {
13
21template <typename ElementType> class PropertyArrayView {
22public:
26 PropertyArrayView() : _values{} {}
27
33 PropertyArrayView(const std::span<const std::byte>& buffer) noexcept
35
39 const ElementType& operator[](int64_t index) const noexcept {
40 return this->_values[static_cast<size_t>(index)];
41 }
42
46 int64_t size() const noexcept {
47 return static_cast<int64_t>(this->_values.size());
48 }
49
53 auto begin() { return this->_values.begin(); }
57 auto end() { return this->_values.end(); }
59 auto begin() const { return this->_values.begin(); }
61 auto end() const { return this->_values.end(); }
62
63private:
64 std::span<const ElementType> _values;
65};
66
77template <typename ElementType> class PropertyArrayCopy {
78public:
82 PropertyArrayCopy() : _storage{}, _view() {}
83
89 PropertyArrayCopy(const std::vector<ElementType>& values) noexcept
90 : _storage(), _view() {
91 size_t numberOfElements = values.size();
92 size_t sizeInBytes = numberOfElements * sizeof(ElementType);
93 this->_storage.resize(sizeInBytes);
94 std::memcpy(
95 this->_storage.data(),
96 reinterpret_cast<const std::byte*>(values.data()),
97 sizeInBytes);
98 // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
99 this->_view = PropertyArrayView<ElementType>(this->_storage);
100 }
101
106
109 PropertyArrayCopy(std::vector<std::byte>&& buffer) noexcept
110 : _storage(std::move(buffer)), _view(this->_storage) {}
111
114 : _storage(rhs._storage), _view(this->_storage) {}
115
118 this->_storage = rhs._storage;
119 this->_view = PropertyArrayView<ElementType>(this->_storage);
120 return *this;
121 }
122
129 const ElementType& operator[](int64_t index) const noexcept {
130 return this->_view[index];
131 }
132
134 int64_t size() const noexcept { return this->_view.size(); }
135
137 auto begin() { return this->_view.begin(); }
139 auto end() { return this->_view.end(); }
141 auto begin() const { return this->_view.begin(); }
143 auto end() const { return this->_view.end(); }
144
148 const PropertyArrayView<ElementType>& view() const { return this->_view; }
149
158 toViewAndExternalBuffer(std::vector<std::byte>& outBuffer) && {
159 outBuffer = std::move(this->_storage);
160 PropertyArrayView<ElementType> result = std::move(this->_view);
161 this->_view = PropertyArrayView<ElementType>();
162 return result;
163 }
164
165private:
166 std::vector<std::byte> _storage;
168};
169
177template <> class PropertyArrayView<bool> {
178public:
182 PropertyArrayView() : _values{}, _bitOffset{0}, _size{0} {}
183
193 const std::span<const std::byte>& buffer,
194 int64_t bitOffset,
195 int64_t size) noexcept
196 : _values{buffer}, _bitOffset{bitOffset}, _size{size} {}
197
201 bool operator[](int64_t index) const noexcept {
202 index += _bitOffset;
203 const int64_t byteIndex = index / 8;
204 const int64_t bitIndex = index % 8;
205 const int bitValue =
206 static_cast<int>(_values[static_cast<size_t>(byteIndex)] >> bitIndex) &
207 1;
208 return bitValue == 1;
209 }
210
214 int64_t size() const noexcept { return _size; }
215
216private:
217 std::span<const std::byte> _values;
218 int64_t _bitOffset;
219 int64_t _size;
220};
221
232template <> class PropertyArrayCopy<bool> {
233public:
237 PropertyArrayCopy() : _storage{}, _view() {}
238
244 PropertyArrayCopy(const std::vector<bool>& values) noexcept
245 : _storage(), _view() {
246 size_t numberOfElements = values.size();
247 size_t sizeInBytes = (numberOfElements + 7) / 8;
248 this->_storage.resize(sizeInBytes);
249
250 for (size_t byteIndex = 0, valueIndex = 0; byteIndex < sizeInBytes;
251 byteIndex++) {
252 uint8_t byte = 0;
253 for (size_t bitIndex = 0; bitIndex < 8 && valueIndex < numberOfElements;
254 bitIndex++, valueIndex++) {
255 uint8_t bit = uint8_t(values[valueIndex]);
256 byte |= bit << bitIndex;
257 }
258 this->_storage[byteIndex] = std::byte(byte);
259 }
260
261 this->_view = PropertyArrayView<bool>(
262 this->_storage,
263 0,
264 static_cast<int64_t>(numberOfElements));
265 }
266
271
274 : _storage(rhs._storage), _view(this->_storage, 0, rhs.size()) {}
275
278 this->_storage = rhs._storage;
279 this->_view = PropertyArrayView<bool>(this->_storage, 0, rhs.size());
280 return *this;
281 }
282
289 bool operator[](int64_t index) const noexcept { return this->_view[index]; }
290
292 int64_t size() const noexcept { return this->_view.size(); }
293
297 const PropertyArrayView<bool>& view() const { return this->_view; }
298
307 toViewAndExternalBuffer(std::vector<std::byte>& outBuffer) && {
308 outBuffer = std::move(this->_storage);
309 PropertyArrayView<bool> result = std::move(this->_view);
310 this->_view = PropertyArrayView<bool>();
311 return result;
312 }
313
314private:
315 std::vector<std::byte> _storage;
317};
318
326template <> class PropertyArrayView<std::string_view> {
327public:
332 : _values{},
333 _stringOffsets{},
334 _stringOffsetType{PropertyComponentType::None},
335 _size{0} {}
336
346 const std::span<const std::byte>& values,
347 const std::span<const std::byte>& stringOffsets,
348 PropertyComponentType stringOffsetType,
349 int64_t size) noexcept
350 : _values{values},
351 _stringOffsets{stringOffsets},
352 _stringOffsetType{stringOffsetType},
353 _size{size} {}
354
358 std::string_view operator[](int64_t index) const noexcept {
359 const size_t currentOffset = getOffsetFromOffsetsBuffer(
360 static_cast<size_t>(index),
361 _stringOffsets,
362 _stringOffsetType);
363 const size_t nextOffset = getOffsetFromOffsetsBuffer(
364 static_cast<size_t>(index + 1),
365 _stringOffsets,
366 _stringOffsetType);
367 return std::string_view(
368 reinterpret_cast<const char*>(_values.data() + currentOffset),
369 (nextOffset - currentOffset));
370 }
371
375 int64_t size() const noexcept { return _size; }
376
377private:
378 std::span<const std::byte> _values;
379 std::span<const std::byte> _stringOffsets;
380 PropertyComponentType _stringOffsetType;
381 int64_t _size;
382
383 friend class PropertyArrayCopy<std::string_view>;
384};
385
395template <> class PropertyArrayCopy<std::string_view> {
396public:
400 PropertyArrayCopy() : _storage{}, _view() {}
401
407 PropertyArrayCopy(const std::vector<std::string>& values) noexcept
408 : _storage(), _view() {
409 size_t numberOfElements = values.size();
410 size_t totalLength = 0;
411 for (const std::string& value : values) {
412 totalLength += value.size();
413 }
414
415 std::vector<std::byte> stringData(totalLength);
416 std::vector<std::byte> offsetData;
417
418 auto copyDataWithOffsetType = [&]<typename TOffsetType>() {
419 offsetData.resize(sizeof(TOffsetType) * numberOfElements + 1);
420 TOffsetType* pOffset = reinterpret_cast<TOffsetType*>(offsetData.data());
421
422 TOffsetType writeOffset = 0;
423 for (size_t i = 0; i < numberOfElements; i++) {
424 const std::string& value = values[i];
425 std::memcpy(
426 stringData.data() + writeOffset,
427 value.data(),
428 value.size());
429
430 *pOffset = writeOffset;
431 writeOffset += TOffsetType(value.size());
432 pOffset++;
433 }
434
435 *pOffset = writeOffset;
436 };
437
438 PropertyComponentType offsetType;
439 if (totalLength < size_t(std::numeric_limits<uint8_t>::max())) {
440 offsetType = PropertyComponentType::Uint8;
441 copyDataWithOffsetType.template operator()<uint8_t>();
442 } else if (totalLength < size_t(std::numeric_limits<uint16_t>::max())) {
444 copyDataWithOffsetType.template operator()<uint16_t>();
445 } else if (totalLength < size_t(std::numeric_limits<uint32_t>::max())) {
447 copyDataWithOffsetType.template operator()<uint32_t>();
448 } else {
450 copyDataWithOffsetType.template operator()<uint64_t>();
451 }
452
453 this->_storage.resize(stringData.size() + offsetData.size());
454 std::memcpy(this->_storage.data(), stringData.data(), stringData.size());
455 std::memcpy(
456 this->_storage.data() + static_cast<int32_t>(stringData.size()),
457 offsetData.data(),
458 offsetData.size());
459
461 std::span<const std::byte>(this->_storage.data(), stringData.size()),
462 std::span<const std::byte>(
463 this->_storage.data() + static_cast<int32_t>(stringData.size()),
464 offsetData.size()),
465 offsetType,
466 static_cast<int64_t>(numberOfElements));
467 }
468
473
476 : _storage(rhs._storage), _view() {
477 // Reconstruct spans so they point to this copy's data.
478 size_t valueSpanSize = rhs._view._values.size();
479 size_t offsetSpanSize = this->_storage.size() - valueSpanSize;
481 std::span<const std::byte>(this->_storage.data(), valueSpanSize),
482 std::span<const std::byte>(
483 this->_storage.data() + static_cast<int32_t>(valueSpanSize),
484 offsetSpanSize),
485 rhs._view._stringOffsetType,
486 rhs._view.size());
487 }
488
491 this->_storage = rhs._storage;
492 // Reconstruct spans so they point to this copy's data.
493 size_t valueSpanSize = rhs._view._values.size();
494 size_t offsetSpanSize = this->_storage.size() - valueSpanSize;
496 std::span<const std::byte>(this->_storage.data(), valueSpanSize),
497 std::span<const std::byte>(
498 this->_storage.data() + static_cast<int32_t>(valueSpanSize),
499 offsetSpanSize),
500 rhs._view._stringOffsetType,
501 rhs._view.size());
502 return *this;
503 }
504
511 std::string_view operator[](int64_t index) const noexcept {
512 return this->_view[index];
513 }
514
516 int64_t size() const noexcept { return this->_view.size(); }
517
522 return this->_view;
523 }
524
533 toViewAndExternalBuffer(std::vector<std::byte>& outBuffer) && {
534 outBuffer = std::move(this->_storage);
535 // Moving a std::vector should not affect the memory addresses of the heap
536 // data, so the spans are still valid.
537 PropertyArrayView<std::string_view> result = std::move(this->_view);
539 return result;
540 }
541
542private:
543 std::vector<std::byte> _storage;
545};
546
550template <typename T>
552 const PropertyArrayView<T>& lhs,
553 const PropertyArrayView<T>& rhs) {
554 int64_t size = lhs.size();
555 if (size != rhs.size()) {
556 return false;
557 }
558
559 for (int64_t i = 0; i < size; ++i) {
560 if (lhs[i] != rhs[i]) {
561 return false;
562 }
563 }
564
565 return true;
566}
567
570template <typename T>
572 const PropertyArrayView<T>& lhs,
573 const PropertyArrayCopy<T>& rhs) {
574 return lhs == PropertyArrayView(rhs);
575}
576
579template <typename T>
581 const PropertyArrayCopy<T>& lhs,
582 const PropertyArrayView<T>& rhs) {
583 return lhs.view() == rhs;
584}
585
588template <typename T>
590 const PropertyArrayCopy<T>& lhs,
591 const PropertyArrayCopy<T>& rhs) {
592 return lhs.view() == rhs.view();
593}
594
598template <typename T>
600 const PropertyArrayView<T>& lhs,
601 const PropertyArrayView<T>& rhs) {
602 return !(lhs == rhs);
603}
604
608template <typename T>
610 const PropertyArrayView<T>& lhs,
611 const PropertyArrayCopy<T>& rhs) {
612 return !(lhs == rhs);
613}
614
618template <typename T>
620 const PropertyArrayCopy<T>& lhs,
621 const PropertyArrayView<T>& rhs) {
622 return !(lhs == rhs);
623}
624
628template <typename T>
630 const PropertyArrayCopy<T>& lhs,
631 const PropertyArrayCopy<T>& rhs) {
632 return !(lhs == rhs);
633}
634
635} // namespace CesiumGltf
PropertyArrayCopy(PropertyArrayCopy &&)=default
Default move constructor.
const PropertyArrayView< bool > & view() const
Obtains a PropertyArrayView over the contents of this copy.
int64_t size() const noexcept
The number of elements in this array.
PropertyArrayCopy(const std::vector< bool > &values) noexcept
Constructs a bool array copy from a vector.
PropertyArrayCopy & operator=(PropertyArrayCopy &&)=default
Default move assignment operator.
PropertyArrayView< bool > toViewAndExternalBuffer(std::vector< std::byte > &outBuffer) &&
Obtains a buffer and view from the copied data, leaving this PropertyArrayCopy empty.
PropertyArrayCopy(const PropertyArrayCopy &rhs)
Copy constructor.
PropertyArrayCopy()
Constructs an empty array copy.
bool operator[](int64_t index) const noexcept
Returns the ElementType at the given index from this copy.
PropertyArrayCopy & operator=(const PropertyArrayCopy &rhs)
Copy assignment operator.
PropertyArrayCopy()
Constructs an empty array copy.
PropertyArrayCopy(const std::vector< std::string > &values) noexcept
Constructs a string array copy from a vector.
PropertyArrayCopy(PropertyArrayCopy &&)=default
Default move constructor.
PropertyArrayCopy(const PropertyArrayCopy &rhs)
Copy constructor.
PropertyArrayCopy & operator=(const PropertyArrayCopy &rhs)
Copy assignment operator.
int64_t size() const noexcept
The number of elements in this array.
const PropertyArrayView< std::string_view > & view() const
Obtains a PropertyArrayView over the contents of this copy.
PropertyArrayCopy & operator=(PropertyArrayCopy &&)=default
Default move assignment operator.
PropertyArrayView< std::string_view > toViewAndExternalBuffer(std::vector< std::byte > &outBuffer) &&
Obtains a buffer and view from the copied data, leaving this PropertyArrayCopy empty.
std::string_view operator[](int64_t index) const noexcept
Returns the ElementType at the given index from this copy.
A copy of an array element of a PropertyTableProperty or PropertyTextureProperty.
PropertyArrayCopy & operator=(const PropertyArrayCopy &rhs)
Copy assignment operator.
PropertyArrayCopy(const std::vector< ElementType > &values) noexcept
Constructs an array copy from a vector.
auto begin() const
The begin iterator.
auto end() const
The end iterator.
auto begin()
The begin iterator.
PropertyArrayCopy & operator=(PropertyArrayCopy &&)=default
Default move assignment operator.
PropertyArrayCopy(std::vector< std::byte > &&buffer) noexcept
Creates a new PropertyArrayCopy directly from a buffer of bytes, which will be moved into this copy.
PropertyArrayCopy(const PropertyArrayCopy &rhs)
Copy constructor.
auto end()
The end iterator.
int64_t size() const noexcept
The number of elements in this array.
const ElementType & operator[](int64_t index) const noexcept
Returns the ElementType at the given index from this copy.
const PropertyArrayView< ElementType > & view() const
Obtains a PropertyArrayView over the contents of this copy.
PropertyArrayCopy(PropertyArrayCopy &&)=default
Default move constructor.
PropertyArrayCopy()
Constructs an empty array copy.
PropertyArrayView< ElementType > toViewAndExternalBuffer(std::vector< std::byte > &outBuffer) &&
Obtains a buffer and view from the copied data, leaving this PropertyArrayCopy empty.
PropertyArrayView()
Constructs an empty array view.
PropertyArrayView(const std::span< const std::byte > &buffer, int64_t bitOffset, int64_t size) noexcept
Constructs an array view from a buffer.
bool operator[](int64_t index) const noexcept
Obtains the element in the array at the given index.
int64_t size() const noexcept
The number of entries in the array.
std::string_view operator[](int64_t index) const noexcept
Obtains an std::string_view for the element at the given index.
PropertyArrayView(const std::span< const std::byte > &values, const std::span< const std::byte > &stringOffsets, PropertyComponentType stringOffsetType, int64_t size) noexcept
Constructs an array view from buffers and their information.
int64_t size() const noexcept
The number of elements in this array.
PropertyArrayView()
Constructs an empty array view.
A view on an array element of a PropertyTableProperty or PropertyTextureProperty.
auto end()
The end iterator.
const ElementType & operator[](int64_t index) const noexcept
Accesses the element of this array at the given index.
auto end() const
The end iterator.
PropertyArrayView(const std::span< const std::byte > &buffer) noexcept
Constructs an array view from a buffer.
PropertyArrayView()
Constructs an empty array view.
auto begin() const
The begin iterator.
auto begin()
The begin iterator.
int64_t size() const noexcept
The number of elements in this array.
Classes for working with glTF models.
PropertyComponentType
The possible types of a property component.
@ Uint32
A property component equivalent to a uint32_t.
@ Uint16
A property component equivalent to a uint16_t.
@ Uint8
A property component equivalent to a uint8_t.
@ Uint64
A property component equivalent to a uint32_t.
bool operator==(const PropertyArrayView< T > &lhs, const PropertyArrayView< T > &rhs)
Compares two PropertyArrayView instances by comparing their values. If the two arrays aren't the same...
bool operator!=(const PropertyArrayView< T > &lhs, const PropertyArrayView< T > &rhs)
Compares two PropertyArrayView instances and returns the inverse.
std::span< To > reintepretCastSpan(const std::span< From > &from) noexcept
This function converts between span types. This function has the same rules with C++ reintepret_cast ...
Definition SpanHelper.h:13
STL namespace.