172 #include <string_view>
173 #include <type_traits>
174 #include <unordered_map>
177 #include "../base/bytes.h"
178 #include "../base/quantize.h"
200 enum Type : uint8_t {
228 using KeyMap = std::unordered_map<std::string, uint16_t>;
233 using KeyList = std::vector<Key>;
256 explicit Vector3f(
float _x,
float _y,
float _z) noexcept;
289 explicit Vector3d(
double _x,
double _y,
double _z) noexcept;
347 bool operator<<(const Bytes& bytes) noexcept;
355 bool operator>>(Bytes& bytes) const noexcept;
363 [[nodiscard]] static
bool check_valid(const Bytes& bytes) noexcept;
370 [[nodiscard]]
bool is_valid() const noexcept;
378 bool shallow_copy(const
PointCloud& target) noexcept;
386 bool deep_copy(const
PointCloud& target) noexcept;
410 [[nodiscard]] KeyMap get_key_map(KeyList* key_list =
nullptr) const noexcept;
417 [[nodiscard]] KeyList get_key_list() const noexcept;
424 [[nodiscard]]
size_t size() const noexcept;
431 [[nodiscard]]
size_t pack_size() const noexcept;
438 [[nodiscard]]
bool is_owner() const noexcept;
445 [[nodiscard]] uint16_t get_extent() const noexcept;
452 [[nodiscard]]
bool get_vertical() const noexcept;
464 void set_vertical(
bool vertical) noexcept;
471 [[nodiscard]] uint8_t get_downsample() const noexcept;
485 bool downsample(uint8_t level) noexcept;
492 [[nodiscard]] uint64_t get_protocol_size_num() const noexcept;
499 [[nodiscard]] uint64_t get_protocol_type_num() const noexcept;
506 [[nodiscard]] std::
string get_protocol_size_str() const noexcept;
514 [[nodiscard]] std::
string get_protocol_name_str() const noexcept;
521 [[nodiscard]] std::
string get_protocol_type_str() const noexcept;
528 [[nodiscard]] const uint8_t* get_internal_data() const noexcept;
535 [[nodiscard]]
size_t get_reserved_size() const noexcept;
546 bool get_value_v3f(
float& x,
float& y,
float& z,
size_t loop_index) const noexcept;
555 bool get_value_v3f(
Vector3f& v3f,
size_t loop_index) const noexcept;
563 [[nodiscard]]
Vector3f get_value_v3f(
size_t loop_index) const noexcept;
574 bool get_value_v3d(
double& x,
double& y,
double& z,
size_t loop_index) const noexcept;
583 bool get_value_v3d(
Vector3d& v3d,
size_t loop_index) const noexcept;
591 [[nodiscard]]
Vector3d get_value_v3d(
size_t loop_index) const noexcept;
602 template <typename T>
603 bool get_value(T& t,
size_t loop_index, uint16_t offset) const noexcept;
613 template <typename T>
614 [[nodiscard]] T get_value(
size_t loop_index, uint16_t offset) const noexcept;
626 template <typename T>
627 bool get_value(T& t,
size_t loop_index, KeyMap& key_map, std::string_view key) const noexcept;
638 template <typename T>
639 [[nodiscard]] T get_value(
size_t loop_index, KeyMap& key_map, std::string_view key) const noexcept;
649 [[nodiscard]]
double get_value_for_double_float(
size_t loop_index, uint16_t offset, uint8_t type) const noexcept;
660 [[nodiscard]]
double get_value_for_double_float(
size_t loop_index, KeyMap& key_map, std::string_view key,
661 uint8_t type) const noexcept;
671 [[nodiscard]] std::
string get_value_for_print(
size_t loop_index, uint16_t offset, uint8_t type) const noexcept;
682 [[nodiscard]] std::
string get_value_for_print(
size_t loop_index, KeyMap& key_map, std::string_view key,
683 uint8_t type) const noexcept;
702 bool create(
size_t size, uint64_t size_num, uint64_t type_num, std::string_view key_str, uint16_t extent = 0,
703 bool vertical = false) noexcept;
715 template <typename... T>
716 bool create(
size_t _size, const std::vector<std::
string>& keys = {}, uint16_t extent = 0,
717 bool vertical =
false) noexcept;
729 template <
typename... T>
730 bool create_v3f(
size_t _size,
const std::vector<std::string>& keys = {}, uint16_t extent = 0,
731 bool vertical =
false) noexcept;
743 template <
typename... T>
744 bool create_v3d(
size_t _size,
const std::vector<std::string>& keys = {}, uint16_t extent = 0,
745 bool vertical =
false) noexcept;
754 bool fill_packed_data(
const uint8_t* src_data,
size_t _size) noexcept;
763 template <
typename... T>
764 bool push_value(T... args) noexcept;
777 template <
typename... T>
778 bool push_value_v3f(
float x,
float y,
float z, T... args) noexcept;
789 template <
typename... T>
790 bool push_value_v3f(
Vector3f v3f, T... args) noexcept;
803 template <
typename... T>
804 bool push_value_v3d(
double x,
double y,
double z, T... args) noexcept;
815 template <
typename... T>
816 bool push_value_v3d(
Vector3d v3d, T... args) noexcept;
828 bool resize(
size_t size) noexcept;
842 template <
typename... T>
843 bool set_value(
size_t loop_index, T... args) noexcept;
857 template <
typename... T>
858 bool set_value_v3f(
size_t loop_index,
float x,
float y,
float z, T... args) noexcept;
870 template <
typename... T>
871 bool set_value_v3f(
size_t loop_index,
Vector3f v3f, T... args) noexcept;
885 template <
typename... T>
886 bool set_value_v3d(
size_t loop_index,
double x,
double y,
double z, T... args) noexcept;
898 template <
typename... T>
899 bool set_value_v3d(
size_t loop_index,
Vector3d v3d, T... args) noexcept;
912 void clear(
bool force =
false) noexcept;
924 uint32_t& get_reserved() noexcept {
return reserved_buf_; }
936 uint32_t& get_reserved2() noexcept {
return reserved_buf2_; }
948 uint8_t& get_reserved3() noexcept {
return reserved_buf3_; }
952 static constexpr
bool kZerocopyTypes{
true};
956 uint64_t size_num{0};
957 uint64_t type_num{0};
960 Protocol() noexcept = default;
962 template <typename... T>
963 static uint64_t get_size_num() noexcept;
965 template <typename... T>
966 static uint64_t get_type_num() noexcept;
968 template <typename T>
969 static constexpr uint8_t get_type() noexcept;
971 constexpr uint64_t get_pack_size() const noexcept;
973 static
bool check_valid(uint64_t _size_num, std::string_view _names) noexcept;
975 static std::
string get_names(const std::vector<std::
string>& keys) noexcept;
977 KeyList get_key_list() const noexcept;
979 std::
string get_size_for_print() const noexcept;
981 std::
string get_type_for_print() const noexcept;
984 template <typename T>
985 static
bool xyz_in_extent(T x, T y, T z, uint16_t extent) noexcept;
987 bool compress_protocol_xyz() noexcept;
990 uint8_t* data_{
nullptr};
993 uint32_t reserved_buf_{0};
994 uint32_t reserved_buf2_{0};
995 uint16_t pack_size_{0};
997 uint8_t downsample_{0};
998 uint8_t reserved_buf3_{0};
999 bool vertical_{
false};
1000 bool is_owner_{
false};
1003 static constexpr uint32_t kMagicNumberBegin{0x98B7F16A};
1004 static constexpr uint32_t kMagicNumberEnd{0x98B7F16F};
1011 template <
typename T>
1012 inline bool PointCloud::get_value(T& t,
size_t loop_index, uint16_t offset)
const noexcept {
1013 static_assert(std::is_fundamental_v<T>,
"T must be fundamental.");
1015 if VUNLIKELY (!data_ || loop_index >= size_ || offset > pack_size_) {
1016 std::memset(&t, 0,
sizeof(T));
1020 if (extent_ != 0 && offset <
sizeof(int16_t) * 3) {
1021 if constexpr (std::is_same_v<T, float> || std::is_same_v<T, double>) {
1024 if VUNLIKELY (
sizeof(value) >
static_cast<size_t>(pack_size_ - offset)) {
1029 const size_t p = (loop_index * pack_size_) + offset;
1030 std::memcpy(&value, data_ + p,
sizeof(value));
1031 t = Quantize::decode<T>(extent_, value);
1037 if VUNLIKELY (
sizeof(T) >
static_cast<size_t>(pack_size_ - offset)) {
1038 std::memset(&t, 0,
sizeof(T));
1042 const size_t p = (loop_index * pack_size_) + offset;
1043 std::memcpy(&t, data_ + p,
sizeof(T));
1048 template <
typename T>
1049 inline T PointCloud::get_value(
size_t loop_index, uint16_t offset)
const noexcept {
1050 static_assert(std::is_fundamental_v<T>,
"T must be fundamental.");
1054 get_value(t, loop_index, offset);
1059 template <
typename T>
1060 inline bool PointCloud::get_value(T& t,
size_t loop_index, KeyMap& key_map, std::string_view key)
const noexcept {
1061 static_assert(std::is_fundamental_v<T>,
"T must be fundamental.");
1063 const std::string lookup(key);
1064 auto iter = key_map.find(lookup);
1067 std::memset(&t, 0,
sizeof(T));
1071 return get_value<T>(t, loop_index, iter->second);
1074 template <
typename T>
1075 inline T PointCloud::get_value(
size_t loop_index, KeyMap& key_map, std::string_view key)
const noexcept {
1076 static_assert(std::is_fundamental_v<T>,
"T must be fundamental.");
1080 get_value(t, loop_index, key_map, key);
1085 template <
typename... T>
1086 inline bool PointCloud::create(
size_t size,
const std::vector<std::string>& keys, uint16_t extent,
1087 bool vertical) noexcept {
1088 static_assert((std::is_fundamental_v<T> && ...),
"All types must be fundamental.");
1090 static_assert(
sizeof...(T) >= 3 &&
sizeof...(T) <= 16,
"The number of keys ranges is [3 ~ 16].");
1092 static_assert(((Protocol::get_type<T>() !=
kUnknownType) && ...),
1093 "All field types must map to a supported PointCloud::Type.");
1095 if VUNLIKELY (
sizeof...(T) != keys.size()) {
1099 uint64_t size_num = Protocol::get_size_num<T...>();
1105 std::string key_str = Protocol::get_names(keys);
1111 uint64_t type_num = Protocol::get_type_num<T...>();
1113 Protocol new_protocol{};
1114 new_protocol.size_num = size_num;
1115 std::memset(new_protocol.names, 0,
sizeof(new_protocol.names));
1116 std::memcpy(new_protocol.names, key_str.c_str(), key_str.size());
1117 new_protocol.type_num = type_num;
1121 protocol_probe.protocol_ = new_protocol;
1123 if VUNLIKELY (!protocol_probe.compress_protocol_xyz()) {
1127 new_protocol = protocol_probe.protocol_;
1130 const size_t new_pack_size = new_protocol.get_pack_size();
1132 if VUNLIKELY (new_pack_size != 0 && size > std::numeric_limits<size_t>::max() / new_pack_size) {
1136 if (is_owner_ && data_ && capacity_ != 0) {
1146 protocol_ = new_protocol;
1148 vertical_ = vertical;
1151 pack_size_ = new_pack_size;
1152 capacity_ = size * pack_size_;
1168 template <
typename... T>
1169 inline bool PointCloud::create_v3f(
size_t _size,
const std::vector<std::string>& keys, uint16_t extent,
1170 bool vertical) noexcept {
1171 std::vector<std::string> target_keys{
"x",
"y",
"z"};
1173 target_keys.insert(target_keys.end(), keys.begin(), keys.end());
1175 return create<float, float, float, T...>(_size, target_keys, extent, vertical);
1178 template <
typename... T>
1179 inline bool PointCloud::create_v3d(
size_t _size,
const std::vector<std::string>& keys, uint16_t extent,
1180 bool vertical) noexcept {
1181 std::vector<std::string> target_keys{
"x",
"y",
"z"};
1183 target_keys.insert(target_keys.end(), keys.begin(), keys.end());
1185 return create<double, double, double, T...>(_size, target_keys, extent, vertical);
1188 inline bool PointCloud::fill_packed_data(
const uint8_t* src_data,
size_t _size) noexcept {
1189 bool is_fill_success =
false;
1191 if VUNLIKELY (_size == 0 || !src_data) {
1192 is_fill_success =
false;
1193 }
else if VUNLIKELY (!is_owner_ || !data_ || pack_size_ == 0 || capacity_ == 0) {
1194 is_fill_success =
false;
1195 }
else if VUNLIKELY (_size > std::numeric_limits<size_t>::max() / pack_size_ || _size * pack_size_ > capacity_) {
1196 is_fill_success =
false;
1198 std::memcpy(data_, src_data, _size * pack_size_);
1200 index_ = _size * pack_size_;
1201 is_fill_success =
true;
1204 return is_fill_success;
1207 template <
typename... T>
1208 inline bool PointCloud::push_value(T... args) noexcept {
1209 static_assert((std::is_fundamental_v<T> && ...),
"All types must be fundamental.");
1211 static_assert(
sizeof...(T) >= 3 &&
sizeof...(T) <= 16,
"The number of keys ranges is [3 ~ 16].");
1213 if VUNLIKELY (!is_owner_ || !data_ || pack_size_ == 0 || capacity_ == 0) {
1217 if VUNLIKELY (size_ * pack_size_ >= capacity_) {
1221 constexpr
size_t kTargetPackSize = (
sizeof(T) + ...);
1223 if VUNLIKELY (kTargetPackSize != pack_size_) {
1227 auto* target_ptr = data_ + index_;
1231 std::memcpy(target_ptr, &args,
sizeof(args));
1232 target_ptr +=
sizeof(args);
1236 index_ += pack_size_;
1242 template <
typename... T>
1243 inline bool PointCloud::push_value_v3f(
float x,
float y,
float z, T... args) noexcept {
1245 if VUNLIKELY (!xyz_in_extent(x, y, z, extent_)) {
1249 auto qx = Quantize::encode<int16_t>(extent_, x);
1250 auto qy = Quantize::encode<int16_t>(extent_, y);
1251 auto qz = Quantize::encode<int16_t>(extent_, z);
1253 return push_value(qx, qy, qz, args...);
1256 return push_value(x, y, z, args...);
1259 template <
typename... T>
1260 inline bool PointCloud::push_value_v3f(
Vector3f v3f, T... args) noexcept {
1261 return push_value_v3f(v3f.x, v3f.y, v3f.z, args...);
1264 template <
typename... T>
1265 inline bool PointCloud::push_value_v3d(
double x,
double y,
double z, T... args) noexcept {
1267 if VUNLIKELY (!xyz_in_extent(x, y, z, extent_)) {
1271 auto qx = Quantize::encode<int16_t>(extent_, x);
1272 auto qy = Quantize::encode<int16_t>(extent_, y);
1273 auto qz = Quantize::encode<int16_t>(extent_, z);
1275 return push_value(qx, qy, qz, args...);
1278 return push_value(x, y, z, args...);
1281 template <
typename... T>
1282 inline bool PointCloud::push_value_v3d(
Vector3d v3d, T... args) noexcept {
1283 return push_value_v3d(v3d.x, v3d.y, v3d.z, args...);
1286 inline bool PointCloud::resize(
size_t size) noexcept {
1287 if VUNLIKELY (!is_owner_ || !data_ || pack_size_ == 0 || capacity_ == 0) {
1291 if VUNLIKELY (size > std::numeric_limits<size_t>::max() / pack_size_) {
1295 if VUNLIKELY (size * pack_size_ > capacity_) {
1300 index_ = size_ * pack_size_;
1305 template <
typename... T>
1306 bool PointCloud::set_value(
size_t loop_index, T... args) noexcept {
1307 static_assert((std::is_fundamental_v<T> && ...),
"All types must be fundamental.");
1309 static_assert(
sizeof...(T) >= 3 &&
sizeof...(T) <= 16,
"The number of keys ranges is [3 ~ 16].");
1311 if VUNLIKELY (!is_owner_ || !data_ || pack_size_ == 0 || capacity_ == 0) {
1315 if VUNLIKELY (loop_index >= size_ || size_ * pack_size_ > capacity_) {
1319 if VUNLIKELY (index_ != size_ * pack_size_) {
1320 std::cerr <<
"[PointCloud::set_value] Invalid buffer state: "
1321 <<
"The current buffer size does not match the capacity. "
1322 <<
"Please call resize(size) before using set_value()." << std::endl;
1326 constexpr
size_t kTargetPackSize = (
sizeof(T) + ...);
1328 if VUNLIKELY (kTargetPackSize != pack_size_) {
1332 auto* target_ptr = data_ + (loop_index * pack_size_);
1336 std::memcpy(target_ptr, &args,
sizeof(args));
1337 target_ptr +=
sizeof(args);
1344 template <
typename... T>
1345 inline bool PointCloud::set_value_v3f(
size_t loop_index,
float x,
float y,
float z, T... args) noexcept {
1347 if VUNLIKELY (!xyz_in_extent(x, y, z, extent_)) {
1351 auto qx = Quantize::encode<int16_t>(extent_, x);
1352 auto qy = Quantize::encode<int16_t>(extent_, y);
1353 auto qz = Quantize::encode<int16_t>(extent_, z);
1355 return set_value(loop_index, qx, qy, qz, args...);
1358 return set_value(loop_index, x, y, z, args...);
1361 template <
typename... T>
1362 inline bool PointCloud::set_value_v3f(
size_t loop_index,
Vector3f v3f, T... args) noexcept {
1363 return set_value_v3f(loop_index, v3f.x, v3f.y, v3f.z, args...);
1366 template <
typename... T>
1367 inline bool PointCloud::set_value_v3d(
size_t loop_index,
double x,
double y,
double z, T... args) noexcept {
1369 if VUNLIKELY (!xyz_in_extent(x, y, z, extent_)) {
1373 auto qx = Quantize::encode<int16_t>(extent_, x);
1374 auto qy = Quantize::encode<int16_t>(extent_, y);
1375 auto qz = Quantize::encode<int16_t>(extent_, z);
1377 return set_value(loop_index, qx, qy, qz, args...);
1380 return set_value(loop_index, x, y, z, args...);
1383 template <
typename... T>
1384 inline bool PointCloud::set_value_v3d(
size_t loop_index,
Vector3d v3d, T... args) noexcept {
1385 return set_value_v3d(loop_index, v3d.x, v3d.y, v3d.z, args...);
1388 template <
typename... T>
1389 inline uint64_t PointCloud::Protocol::get_size_num() noexcept {
1390 uint64_t target_num = 0;
1392 uint64_t key_shift =
sizeof...(T) * 4;
1397 target_num |= (
static_cast<uint64_t
>(
sizeof(type)) & 0xF) << key_shift;
1404 template <
typename... T>
1405 inline uint64_t PointCloud::Protocol::get_type_num() noexcept {
1406 uint64_t target_num = 0;
1408 uint64_t key_shift =
sizeof...(T) * 4;
1413 target_num |= (
static_cast<uint64_t
>(get_type<decltype(type)>()) & 0xF) << key_shift;
1420 template <
typename T>
1421 inline constexpr uint8_t PointCloud::Protocol::get_type() noexcept {
1422 if constexpr (std::is_same_v<T, bool>) {
1424 }
else if constexpr (std::is_same_v<T, int8_t>) {
1426 }
else if constexpr (std::is_same_v<T, uint8_t>) {
1428 }
else if constexpr (std::is_same_v<T, int16_t>) {
1430 }
else if constexpr (std::is_same_v<T, uint16_t>) {
1432 }
else if constexpr (std::is_same_v<T, int32_t>) {
1434 }
else if constexpr (std::is_same_v<T, uint32_t>) {
1436 }
else if constexpr (std::is_same_v<T, int64_t>) {
1438 }
else if constexpr (std::is_same_v<T, uint64_t>) {
1440 }
else if constexpr (std::is_same_v<T, float>) {
1442 }
else if constexpr (std::is_same_v<T, double>) {
1449 inline constexpr uint64_t PointCloud::Protocol::get_pack_size() const noexcept {
1452 auto target_num = size_num;
1454 while (target_num > 0) {
1455 sum += target_num & 0xF;
1462 template <
typename T>
1463 inline bool PointCloud::xyz_in_extent(T x, T y, T z, uint16_t extent) noexcept {
1464 return x > -extent && x < extent && y > -extent && y < extent && z > -extent && z < extent;
static uint8_t * bytes_malloc(size_t size) noexcept
Allocates a raw aligned byte buffer through the global memory pool.
static void bytes_free(uint8_t *ptr, size_t size) noexcept
Returns a buffer previously obtained from bytes_malloc to the pool.
#define VUNLIKELY(...)
Short alias for VLINK_UNLIKELY.
Definition: macros.h:289
#define VLIKELY(...)
Short alias for VLINK_LIKELY.
Definition: macros.h:284
constexpr bool is_valid() noexcept
Definition: name_detector.h:382
@ kUnknownType
Unsupported type; is_supported() returns false.
Definition: serializer.h:155
size_t get_serialized_size(const T &src) noexcept
Returns a serialised-size hint for src with explicit codec tag.
Definition: serializer-inl.h:263
VLINK_EXPORT std::ostream & operator<<(std::ostream &ostream, const BasePtr &status) noexcept
Writes the human-readable description of status to ostream.
struct VLINK_EXPORT_AND_ALIGNED(8) AudioFrame final
Definition: audio_frame.h:140
Definition: point_cloud.h:196
256-byte POD container holding a schema-described array of N-field point records.