#ifndef BASE_BIG_ENDIAN_H_
#define BASE_BIG_ENDIAN_H_
template <typename T>
inline void ReadBigEndian(const char buf[], T* out) {
*out = buf[0];
for (size_t i = 1; i < sizeof(T); ++i) {
*out <<= 8;
// Must cast to uint8_t to avoid clobbering by sign extension.
*out |= static_cast<uint8_t>(buf[i]);
}
}
template <typename T>
inline void WriteBigEndian(char buf[], T val) {
for (size_t i = 0; i < sizeof(T); ++i) {
buf[sizeof(T) - i - 1] = static_cast<char>(val & 0xFF);
val >>= 8;
}
}
class BigEndianReader {
public:
BigEndianReader(const char* buf, size_t len);
const char* ptr() const { return ptr_; }
int remaining() const { return end_ - ptr_; }
bool Skip(size_t len);
bool ReadBytes(void* out, size_t len);
bool ReadU8(uint8_t* value);
bool ReadU16(uint16_t* value);
bool ReadU32(uint32_t* value);
bool ReadU64(uint64_t* value);
private:
// Hidden to promote type safety.
template <typename T>
bool Read(T* v);
const char* ptr_;
const char* end_;
};
class BigEndianWriter {
public:
BigEndianWriter(char* buf, size_t len);
char* ptr() const { return ptr_; }
int remaining() const { return end_ - ptr_; }
bool Skip(size_t len);
bool WriteBytes(const void* buf, size_t len);
bool WriteU8(uint8_t value);
bool WriteU16(uint16_t value);
bool WriteU32(uint32_t value);
bool WriteU64(uint64_t value);
private:
// Hidden to promote type safety.
template <typename T>
bool Write(T v);
char* ptr_;
char* end_;
};
#endif // BASE_BIG_ENDIAN_H_
====================================================================
#include "big_endian.h"
#include <cstdlib>
#include <cstring>
BigEndianReader::BigEndianReader(const char* buf, size_t len) : ptr_(buf), end_(ptr_ + len) {}
bool BigEndianReader::Skip(size_t len) {
if (ptr_ + len > end_)
return false;
ptr_ += len;
return true;
}
bool BigEndianReader::ReadBytes(void* out, size_t len) {
if (ptr_ + len > end_)
return false;
memcpy(out, ptr_, len);
ptr_ += len;
return true;
}
template <typename T>
bool BigEndianReader::Read(T* value) {
if (ptr_ + sizeof(T) > end_)
return false;
ReadBigEndian<T>(ptr_, value);
ptr_ += sizeof(T);
return true;
}
bool BigEndianReader::ReadU8(uint8_t* value) {
return Read(value);
}
bool BigEndianReader::ReadU16(uint16_t* value) {
return Read(value);
}
bool BigEndianReader::ReadU32(uint32_t* value) {
return Read(value);
}
bool BigEndianReader::ReadU64(uint64_t* value) {
return Read(value);
}
BigEndianWriter::BigEndianWriter(char* buf, size_t len) : ptr_(buf), end_(ptr_ + len) {}
bool BigEndianWriter::Skip(size_t len) {
if (ptr_ + len > end_)
return false;
ptr_ += len;
return true;
}
bool BigEndianWriter::WriteBytes(const void* buf, size_t len) {
if (ptr_ + len > end_)
return false;
memcpy(ptr_, buf, len);
ptr_ += len;
return true;
}
template <typename T>
bool BigEndianWriter::Write(T value) {
if (ptr_ + sizeof(T) > end_)
return false;
WriteBigEndian<T>(ptr_, value);
ptr_ += sizeof(T);
return true;
}
bool BigEndianWriter::WriteU8(uint8_t value) {
return Write(value);
}
bool BigEndianWriter::WriteU16(uint16_t value) {
return Write(value);
}
bool BigEndianWriter::WriteU32(uint32_t value) {
return Write(value);
}
bool BigEndianWriter::WriteU64(uint64_t value) {
return Write(value);
}