#ifndef BASE_BIG_ENDIAN_H_
#define BASE_BIG_ENDIAN_H_
#include <stddef.h>
#include <stdint.h>
#include <type_traits>
#include "base/base_export.h"
#include "base/containers/span.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/string_piece.h"
namespace base {
template <typename T>
inline void ReadBigEndian(const uint8_t buf[], T* out) {
static_assert(std::is_integral<T>::value, "T has to be an integral type.");
typename std::make_unsigned<T>::type unsigned_result = buf[0];
for (size_t i = 1; i < sizeof(T); ++i) {
unsigned_result <<= 8;
unsigned_result |= buf[i];
}
*out = unsigned_result;
}
template<typename T>
inline void WriteBigEndian(char buf[], T val) {
static_assert(std::is_integral<T>::value, "T has to be an integral type.");
auto unsigned_val = static_cast<typename std::make_unsigned<T>::type>(val);
for (size_t i = 0; i < sizeof(T); ++i) {
buf[sizeof(T) - i - 1] = static_cast<char>(unsigned_val & 0xFF);
unsigned_val >>= 8;
}
}
template <>
inline void ReadBigEndian<uint8_t>(const uint8_t buf[], uint8_t* out) {
*out = buf[0];
}
template <>
inline void WriteBigEndian<uint8_t>(char buf[], uint8_t val) {
buf[0] = static_cast<char>(val);
}
template <>
inline void ReadBigEndian<int8_t>(const uint8_t buf[], int8_t* out) {
*out = static_cast<int8_t>(buf[0]);
}
template <>
inline void WriteBigEndian<int8_t>(char buf[], int8_t val) {
buf[0] = static_cast<char>(val);
}
class BASE_EXPORT BigEndianReader {
public:
static BigEndianReader FromStringPiece(base::StringPiece string_piece);
BigEndianReader(const uint8_t* buf, size_t len);
explicit BigEndianReader(base::span<const uint8_t> buf);
const uint8_t* ptr() const { return ptr_; }
size_t remaining() const { return static_cast<size_t>(end_ - ptr_); }
bool Skip(size_t len);
bool ReadBytes(void* out, size_t len);
bool ReadPiece(base::StringPiece* out, size_t len);
bool ReadSpan(base::span<const uint8_t>* out, size_t len);
bool ReadU8(uint8_t* value);
bool ReadU16(uint16_t* value);
bool ReadU32(uint32_t* value);
bool ReadU64(uint64_t* value);
bool ReadU8LengthPrefixed(base::StringPiece* out);
bool ReadU16LengthPrefixed(base::StringPiece* out);
private:
template<typename T>
bool Read(T* v);
template <typename T>
bool ReadLengthPrefixed(base::StringPiece* out);
const uint8_t* ptr_;
const uint8_t* end_;
};
class BASE_EXPORT BigEndianWriter {
public:
BigEndianWriter(char* buf, size_t len);
char* ptr() const { return ptr_; }
size_t remaining() const { return static_cast<size_t>(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:
template<typename T>
bool Write(T v);
raw_ptr<char, DanglingUntriaged | AllowPtrArithmetic> ptr_;
raw_ptr<char, DanglingUntriaged | AllowPtrArithmetic> end_;
};
}
#endif