update byte_utils
This commit is contained in:
parent
3d3679c8b1
commit
0b3bb36188
@ -4,6 +4,8 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "util/data_io.hpp"
|
||||||
|
|
||||||
void ByteBuilder::put(ubyte b) {
|
void ByteBuilder::put(ubyte b) {
|
||||||
buffer.push_back(b);
|
buffer.push_back(b);
|
||||||
}
|
}
|
||||||
@ -30,28 +32,24 @@ void ByteBuilder::put(const ubyte* arr, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ByteBuilder::putInt16(int16_t val) {
|
void ByteBuilder::putInt16(int16_t val) {
|
||||||
buffer.push_back(static_cast<ubyte>(val >> 0 & 255));
|
size_t size = buffer.size();
|
||||||
buffer.push_back(static_cast<ubyte>(val >> 8 & 255));
|
buffer.resize(buffer.size() + sizeof(int16_t));
|
||||||
|
val = dataio::h2le(val);
|
||||||
|
std::memcpy(buffer.data()+size, &val, sizeof(int16_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ByteBuilder::putInt32(int32_t val) {
|
void ByteBuilder::putInt32(int32_t val) {
|
||||||
buffer.reserve(buffer.size() + 4);
|
size_t size = buffer.size();
|
||||||
buffer.push_back(static_cast<ubyte>(val >> 0 & 255));
|
buffer.resize(buffer.size() + sizeof(int32_t));
|
||||||
buffer.push_back(static_cast<ubyte>(val >> 8 & 255));
|
val = dataio::h2le(val);
|
||||||
buffer.push_back(static_cast<ubyte>(val >> 16 & 255));
|
std::memcpy(buffer.data()+size, &val, sizeof(int32_t));
|
||||||
buffer.push_back(static_cast<ubyte>(val >> 24 & 255));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ByteBuilder::putInt64(int64_t val) {
|
void ByteBuilder::putInt64(int64_t val) {
|
||||||
buffer.reserve(buffer.size() + 8);
|
size_t size = buffer.size();
|
||||||
buffer.push_back(static_cast<ubyte>(val >> 0 & 255));
|
buffer.resize(buffer.size() + sizeof(int64_t));
|
||||||
buffer.push_back(static_cast<ubyte>(val >> 8 & 255));
|
val = dataio::h2le(val);
|
||||||
buffer.push_back(static_cast<ubyte>(val >> 16 & 255));
|
std::memcpy(buffer.data()+size, &val, sizeof(int64_t));
|
||||||
buffer.push_back(static_cast<ubyte>(val >> 24 & 255));
|
|
||||||
buffer.push_back(static_cast<ubyte>(val >> 32 & 255));
|
|
||||||
buffer.push_back(static_cast<ubyte>(val >> 40 & 255));
|
|
||||||
buffer.push_back(static_cast<ubyte>(val >> 48 & 255));
|
|
||||||
buffer.push_back(static_cast<ubyte>(val >> 56 & 255));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ByteBuilder::putFloat32(float val) {
|
void ByteBuilder::putFloat32(float val) {
|
||||||
@ -71,27 +69,18 @@ void ByteBuilder::set(size_t position, ubyte val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ByteBuilder::setInt16(size_t position, int16_t val) {
|
void ByteBuilder::setInt16(size_t position, int16_t val) {
|
||||||
buffer[position++] = val >> 0 & 255;
|
val = dataio::h2le(val);
|
||||||
buffer[position] = val >> 8 & 255;
|
std::memcpy(buffer.data()+position, &val, sizeof(int16_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ByteBuilder::setInt32(size_t position, int32_t val) {
|
void ByteBuilder::setInt32(size_t position, int32_t val) {
|
||||||
buffer[position++] = val >> 0 & 255;
|
val = dataio::h2le(val);
|
||||||
buffer[position++] = val >> 8 & 255;
|
std::memcpy(buffer.data()+position, &val, sizeof(int32_t));
|
||||||
buffer[position++] = val >> 16 & 255;
|
|
||||||
buffer[position] = val >> 24 & 255;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ByteBuilder::setInt64(size_t position, int64_t val) {
|
void ByteBuilder::setInt64(size_t position, int64_t val) {
|
||||||
buffer[position++] = val >> 0 & 255;
|
val = dataio::h2le(val);
|
||||||
buffer[position++] = val >> 8 & 255;
|
std::memcpy(buffer.data()+position, &val, sizeof(int64_t));
|
||||||
buffer[position++] = val >> 16 & 255;
|
|
||||||
buffer[position++] = val >> 24 & 255;
|
|
||||||
|
|
||||||
buffer[position++] = val >> 32 & 255;
|
|
||||||
buffer[position++] = val >> 40 & 255;
|
|
||||||
buffer[position++] = val >> 48 & 255;
|
|
||||||
buffer[position] = val >> 56 & 255;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ubyte> ByteBuilder::build() {
|
std::vector<ubyte> ByteBuilder::build() {
|
||||||
@ -111,7 +100,7 @@ void ByteReader::checkMagic(const char* data, size_t size) {
|
|||||||
throw std::runtime_error("invalid magic number");
|
throw std::runtime_error("invalid magic number");
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
if (this->data[pos + i] != (ubyte)data[i]) {
|
if (this->data[pos + i] != static_cast<ubyte>(data[i])) {
|
||||||
throw std::runtime_error("invalid magic number");
|
throw std::runtime_error("invalid magic number");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,38 +122,33 @@ ubyte ByteReader::peek() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int16_t ByteReader::getInt16() {
|
int16_t ByteReader::getInt16() {
|
||||||
if (pos + 2 > size) {
|
if (pos + sizeof(int16_t) > size) {
|
||||||
throw std::runtime_error("buffer underflow");
|
throw std::runtime_error("buffer underflow");
|
||||||
}
|
}
|
||||||
pos += 2;
|
int16_t value;
|
||||||
return (static_cast<int16_t>(data[pos - 1]) << 8) |
|
std::memcpy(&value, data + pos, sizeof(int16_t));
|
||||||
(static_cast<int16_t>(data[pos - 2]));
|
pos += sizeof(int16_t);
|
||||||
|
return dataio::le2h(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ByteReader::getInt32() {
|
int32_t ByteReader::getInt32() {
|
||||||
if (pos + 4 > size) {
|
if (pos + sizeof(int32_t) > size) {
|
||||||
throw std::runtime_error("buffer underflow");
|
throw std::runtime_error("buffer underflow");
|
||||||
}
|
}
|
||||||
pos += 4;
|
int32_t value;
|
||||||
return (static_cast<int32_t>(data[pos - 1]) << 24) |
|
std::memcpy(&value, data + pos, sizeof(int32_t));
|
||||||
(static_cast<int32_t>(data[pos - 2]) << 16) |
|
pos += sizeof(int32_t);
|
||||||
(static_cast<int32_t>(data[pos - 3]) << 8) |
|
return dataio::le2h(value);
|
||||||
(static_cast<int32_t>(data[pos - 4]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t ByteReader::getInt64() {
|
int64_t ByteReader::getInt64() {
|
||||||
if (pos + 8 > size) {
|
if (pos + sizeof(int64_t) > size) {
|
||||||
throw std::runtime_error("buffer underflow");
|
throw std::runtime_error("buffer underflow");
|
||||||
}
|
}
|
||||||
pos += 8;
|
int64_t value;
|
||||||
return (static_cast<int64_t>(data[pos - 1]) << 56) |
|
std::memcpy(&value, data + pos, sizeof(int64_t));
|
||||||
(static_cast<int64_t>(data[pos - 2]) << 48) |
|
pos += sizeof(int64_t);
|
||||||
(static_cast<int64_t>(data[pos - 3]) << 40) |
|
return dataio::le2h(value);
|
||||||
(static_cast<int64_t>(data[pos - 4]) << 32) |
|
|
||||||
(static_cast<int64_t>(data[pos - 5]) << 24) |
|
|
||||||
(static_cast<int64_t>(data[pos - 6]) << 16) |
|
|
||||||
(static_cast<int64_t>(data[pos - 7]) << 8) |
|
|
||||||
(static_cast<int64_t>(data[pos - 8]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float ByteReader::getFloat32() {
|
float ByteReader::getFloat32() {
|
||||||
@ -183,7 +167,7 @@ double ByteReader::getFloat64() {
|
|||||||
|
|
||||||
const char* ByteReader::getCString() {
|
const char* ByteReader::getCString() {
|
||||||
const char* cstr = reinterpret_cast<const char*>(data + pos);
|
const char* cstr = reinterpret_cast<const char*>(data + pos);
|
||||||
pos += strlen(cstr) + 1;
|
pos += std::strlen(cstr) + 1;
|
||||||
return cstr;
|
return cstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,28 +5,27 @@
|
|||||||
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
|
|
||||||
/* byteorder: little-endian */
|
|
||||||
class ByteBuilder {
|
class ByteBuilder {
|
||||||
std::vector<ubyte> buffer;
|
std::vector<ubyte> buffer;
|
||||||
public:
|
public:
|
||||||
/* Write one byte (8 bit unsigned integer) */
|
/// @brief Write one byte (8 bit unsigned integer)
|
||||||
void put(ubyte b);
|
void put(ubyte b);
|
||||||
/* Write c-string (bytes array terminated with '\00') */
|
/// @brief Write c-string (bytes array terminated with '\00')
|
||||||
void putCStr(const char* str);
|
void putCStr(const char* str);
|
||||||
/* Write signed 16 bit integer */
|
/// @brief Write signed 16 bit little-endian integer
|
||||||
void putInt16(int16_t val);
|
void putInt16(int16_t val);
|
||||||
/* Write signed 32 bit integer */
|
/// @brief Write signed 32 bit integer
|
||||||
void putInt32(int32_t val);
|
void putInt32(int32_t val);
|
||||||
/* Write signed 64 bit integer */
|
/// @brief Write signed 64 bit integer
|
||||||
void putInt64(int64_t val);
|
void putInt64(int64_t val);
|
||||||
/* Write 32 bit floating-point number */
|
/// @brief Write 32 bit floating-point number
|
||||||
void putFloat32(float val);
|
void putFloat32(float val);
|
||||||
/* Write 64 bit floating-point number */
|
/// @brief Write 64 bit floating-point number
|
||||||
void putFloat64(double val);
|
void putFloat64(double val);
|
||||||
|
|
||||||
/* Write string (uint32 length + bytes) */
|
/// @brief Write string (uint32 length + bytes)
|
||||||
void put(const std::string& s);
|
void put(const std::string& s);
|
||||||
/* Write sequence of bytes without any header */
|
/// @brief Write sequence of bytes without any header
|
||||||
void put(const ubyte* arr, size_t size);
|
void put(const ubyte* arr, size_t size);
|
||||||
|
|
||||||
void set(size_t position, ubyte val);
|
void set(size_t position, ubyte val);
|
||||||
@ -44,7 +43,6 @@ public:
|
|||||||
std::vector<ubyte> build();
|
std::vector<ubyte> build();
|
||||||
};
|
};
|
||||||
|
|
||||||
/// byteorder: little-endian
|
|
||||||
class ByteReader {
|
class ByteReader {
|
||||||
const ubyte* data;
|
const ubyte* data;
|
||||||
size_t size;
|
size_t size;
|
||||||
@ -58,11 +56,11 @@ public:
|
|||||||
ubyte get();
|
ubyte get();
|
||||||
/// @brief Read one byte (unsigned 8 bit integer) without pointer move
|
/// @brief Read one byte (unsigned 8 bit integer) without pointer move
|
||||||
ubyte peek();
|
ubyte peek();
|
||||||
/// @brief Read signed 16 bit integer
|
/// @brief Read signed 16 bit little-endian integer
|
||||||
int16_t getInt16();
|
int16_t getInt16();
|
||||||
/// @brief Read signed 32 bit integer
|
/// @brief Read signed 32 bit little-endian integer
|
||||||
int32_t getInt32();
|
int32_t getInt32();
|
||||||
/// @brief Read signed 64 bit integer
|
/// @brief Read signed 64 bit little-endian integer
|
||||||
int64_t getInt64();
|
int64_t getInt64();
|
||||||
/// @brief Read 32 bit floating-point number
|
/// @brief Read 32 bit floating-point number
|
||||||
float getFloat32();
|
float getFloat32();
|
||||||
|
|||||||
@ -18,7 +18,7 @@ namespace util {
|
|||||||
|
|
||||||
Buffer(const T* src, size_t length)
|
Buffer(const T* src, size_t length)
|
||||||
: ptr(std::make_unique<T[]>(length)), length(length) {
|
: ptr(std::make_unique<T[]>(length)), length(length) {
|
||||||
std::memcpy(ptr, src, length);
|
std::memcpy(ptr.get(), src, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator[](long long index) {
|
T& operator[](long long index) {
|
||||||
|
|||||||
@ -41,6 +41,15 @@ namespace dataio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Convert hardware byte-order to big-endian
|
||||||
|
/// @tparam T value type
|
||||||
|
/// @param value source integer
|
||||||
|
/// @return big-endian integer
|
||||||
|
template <typename T>
|
||||||
|
T h2be(T value){
|
||||||
|
return be2h(value);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Convert little-endian to hardware byte-order
|
/// @brief Convert little-endian to hardware byte-order
|
||||||
/// @tparam T value type
|
/// @tparam T value type
|
||||||
/// @param value source integer
|
/// @param value source integer
|
||||||
@ -54,6 +63,15 @@ namespace dataio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Convert hardware byte-order to little-endian
|
||||||
|
/// @tparam T value type
|
||||||
|
/// @param value source integer
|
||||||
|
/// @return little-endian integer
|
||||||
|
template <typename T>
|
||||||
|
T h2le(T value){
|
||||||
|
return le2h(value);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Read big-endian 16 bit signed integer from bytes
|
/// @brief Read big-endian 16 bit signed integer from bytes
|
||||||
inline int16_t read_int16_big(const ubyte* src, size_t offset) {
|
inline int16_t read_int16_big(const ubyte* src, size_t offset) {
|
||||||
return (src[offset] << 8) | (src[offset + 1]);
|
return (src[offset] << 8) | (src[offset + 1]);
|
||||||
|
|||||||
20
test/coders/byte_utils.cpp
Normal file
20
test/coders/byte_utils.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "coders/byte_utils.hpp"
|
||||||
|
|
||||||
|
TEST(byte_utils, BytesBuildAndRead) {
|
||||||
|
ByteBuilder builder;
|
||||||
|
builder.putCStr("MAGIC.#");
|
||||||
|
builder.put(50);
|
||||||
|
builder.putInt16(1980);
|
||||||
|
builder.putInt32(123456789);
|
||||||
|
builder.putInt64(98765432123456789LL);
|
||||||
|
auto data = builder.build();
|
||||||
|
|
||||||
|
ByteReader reader(data.data(), data.size());
|
||||||
|
reader.checkMagic("MAGIC.#", 8);
|
||||||
|
EXPECT_EQ(reader.get(), 50);
|
||||||
|
EXPECT_EQ(reader.getInt16(), 1980);
|
||||||
|
EXPECT_EQ(reader.getInt32(), 123456789);
|
||||||
|
EXPECT_EQ(reader.getInt64(), 98765432123456789LL);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user