sots-engine/src/mars/stream/bytes.h

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