75 lines
2.3 KiB
C++
75 lines
2.3 KiB
C++
// mars::stream — byte-level helpers shared by the reader and writer.
|
|
// Everything in the Streamable format is little-endian; these helpers do the
|
|
// byte shuffling explicitly so the code is host-endian independent.
|
|
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace mars::stream {
|
|
|
|
using Bytes = std::vector<uint8_t>;
|
|
|
|
constexpr uint32_t kBeginMark = 0xBEEFBEEFu; // opens a complex (framed) value
|
|
constexpr uint32_t kEndMark = 0x41104110u; // closes it (= ~kBeginMark)
|
|
|
|
inline uint32_t pad4(uint32_t n) { return (n + 3u) & ~3u; }
|
|
|
|
inline uint32_t rd_u32(const uint8_t* p) {
|
|
return uint32_t(p[0]) | (uint32_t(p[1]) << 8) | (uint32_t(p[2]) << 16) | (uint32_t(p[3]) << 24);
|
|
}
|
|
inline int32_t rd_i32(const uint8_t* p) { return int32_t(rd_u32(p)); }
|
|
inline uint64_t rd_u64(const uint8_t* p) { return uint64_t(rd_u32(p)) | (uint64_t(rd_u32(p + 4)) << 32); }
|
|
inline int64_t rd_i64(const uint8_t* p) { return int64_t(rd_u64(p)); }
|
|
inline float rd_f32(const uint8_t* p) {
|
|
uint32_t u = rd_u32(p);
|
|
float f;
|
|
std::memcpy(&f, &u, 4);
|
|
return f;
|
|
}
|
|
inline uint32_t f32_bits(float f) {
|
|
uint32_t u;
|
|
std::memcpy(&u, &f, 4);
|
|
return u;
|
|
}
|
|
inline float bits_f32(uint32_t u) {
|
|
float f;
|
|
std::memcpy(&f, &u, 4);
|
|
return f;
|
|
}
|
|
|
|
inline void put_u32(Bytes& b, uint32_t v) {
|
|
b.push_back(uint8_t(v));
|
|
b.push_back(uint8_t(v >> 8));
|
|
b.push_back(uint8_t(v >> 16));
|
|
b.push_back(uint8_t(v >> 24));
|
|
}
|
|
inline void put_i32(Bytes& b, int32_t v) { put_u32(b, uint32_t(v)); }
|
|
inline void put_u64(Bytes& b, uint64_t v) {
|
|
put_u32(b, uint32_t(v));
|
|
put_u32(b, uint32_t(v >> 32));
|
|
}
|
|
inline void put_f32(Bytes& b, float f) { put_u32(b, f32_bits(f)); }
|
|
inline void put_bytes(Bytes& b, const void* p, size_t n) {
|
|
const uint8_t* s = static_cast<const uint8_t*>(p);
|
|
b.insert(b.end(), s, s + n);
|
|
}
|
|
inline void put_pad(Bytes& b, size_t to_boundary_of_item_start) {
|
|
// append NUL bytes until b.size() - start is a multiple of 4
|
|
while ((b.size() - to_boundary_of_item_start) & 3u) b.push_back(0);
|
|
}
|
|
|
|
inline std::string hex(const uint8_t* p, size_t n) {
|
|
static const char* d = "0123456789abcdef";
|
|
std::string s;
|
|
s.reserve(n * 2);
|
|
for (size_t i = 0; i < n; ++i) {
|
|
s.push_back(d[p[i] >> 4]);
|
|
s.push_back(d[p[i] & 15]);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
} // namespace mars::stream
|