File cdr_types.hpp
File List > astutedds > cdr > cdr_types.hpp
Go to the documentation of this file
#ifndef ASTUTEDDS_CDR_TYPES_HPP
#define ASTUTEDDS_CDR_TYPES_HPP
#include <bit>
#include <cstdint>
#include <span>
#include <vector>
#include <stdexcept>
#ifdef _MSC_VER
#include <cstdlib>
#endif
namespace astutedds::cdr {
// CDR Encoding Version (7.4.3.4.2)
enum class EncodingKind : uint16_t {
CDR_BE = 0x0000, // CDR Big Endian
CDR_LE = 0x0001, // CDR Little Endian
PL_CDR_BE = 0x0002, // Parameter List CDR Big Endian
PL_CDR_LE = 0x0003, // Parameter List CDR Little Endian
// XCDR2 / CDR2 encapsulations (DDS-XTypes 1.3, Table 34)
CDR2_BE = 0x0006, // PLAIN_CDR2 Big Endian (FINAL types)
CDR2_LE = 0x0007, // PLAIN_CDR2 Little Endian (FINAL types)
XCDR2_BE = 0x0006, // Alias for PLAIN_CDR2 Big Endian
XCDR2_LE = 0x0007, // Alias for PLAIN_CDR2 Little Endian
D_CDR2_BE = 0x0008, // Delimited XCDR2 Big Endian (APPENDABLE types)
D_CDR2_LE = 0x0009, // Delimited XCDR2 Little Endian (APPENDABLE types)
PL_CDR2_BE = 0x000A, // Parameter List XCDR2 Big Endian (MUTABLE types)
PL_CDR2_LE = 0x000B, // Parameter List XCDR2 Little Endian (MUTABLE types)
XML = 0x0016 // XML encoding
};
// Extensibility Kind (7.2.2.4)
enum class ExtensibilityKind : uint8_t {
FINAL = 0,
APPENDABLE = 1,
MUTABLE = 2
};
// Encapsulation Header (7.4.3.4.1)
struct EncapsulationHeader {
EncodingKind encoding{EncodingKind::CDR_LE};
uint16_t options{0};
};
// DHEADER for delimited (XCDR2) encoding (7.4.3.4.3)
struct DHEADER {
uint32_t size{0}; // Size of the serialized object in bytes
};
// EMHEADER for mutable members (7.4.3.4.4)
struct EMHEADER {
bool must_understand{false};
bool length_code{false}; // 0 = 4-byte length, 1 = 8-byte length
uint32_t member_id{0};
uint32_t member_length{0};
};
// Type support for compile-time alignment calculations
template<typename T>
constexpr size_t alignment_of() {
return alignof(T);
}
// Alignment utilities for CDR encoding
constexpr size_t align_offset(size_t offset, size_t alignment) {
return (offset + alignment - 1) & ~(alignment - 1);
}
// CDR Stream buffer wrapper
class CDRBuffer {
public:
explicit CDRBuffer(std::vector<uint8_t>& data) : data_(data) {}
std::span<uint8_t> span() { return data_; }
std::span<const uint8_t> span() const { return data_; }
size_t size() const { return data_.size(); }
void resize(size_t new_size) { data_.resize(new_size); }
uint8_t* data() { return data_.data(); }
const uint8_t* data() const { return data_.data(); }
private:
std::vector<uint8_t>& data_;
};
// ---------------------------------------------------------------------------
// Encapsulation header helpers
// ---------------------------------------------------------------------------
inline EncodingKind detect_encoding(const std::vector<uint8_t> &buf)
{
if (buf.size() < 2)
return EncodingKind::CDR_LE; // safe fallback
return static_cast<EncodingKind>((static_cast<uint16_t>(buf[0]) << 8) | buf[1]);
}
inline bool is_xcdr1(EncodingKind kind)
{
return kind == EncodingKind::CDR_BE || kind == EncodingKind::CDR_LE ||
kind == EncodingKind::PL_CDR_BE || kind == EncodingKind::PL_CDR_LE;
}
// Endianness detection and conversion
constexpr bool is_little_endian() {
return std::endian::native == std::endian::little;
}
template<typename T>
T swap_endian(T value) {
if constexpr (sizeof(T) == 1) {
return value;
} else if constexpr (sizeof(T) == 2) {
#if defined(_MSC_VER)
return static_cast<T>(_byteswap_ushort(static_cast<uint16_t>(value)));
#else
return static_cast<T>(__builtin_bswap16(static_cast<uint16_t>(value)));
#endif
} else if constexpr (sizeof(T) == 4) {
#if defined(_MSC_VER)
return static_cast<T>(_byteswap_ulong(static_cast<uint32_t>(value)));
#else
return static_cast<T>(__builtin_bswap32(static_cast<uint32_t>(value)));
#endif
} else if constexpr (sizeof(T) == 8) {
#if defined(_MSC_VER)
return static_cast<T>(_byteswap_uint64(static_cast<uint64_t>(value)));
#else
return static_cast<T>(__builtin_bswap64(static_cast<uint64_t>(value)));
#endif
}
}
} // namespace astutedds::cdr
#endif // ASTUTEDDS_CDR_TYPES_HPP