// 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 #include #include #include namespace mars::stream { using Bytes = std::vector; 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(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