Improve SLK
Summary: SLK now correctly handles different CPU architectures (BIG/little endian). Also, more string encoding functions have been added. Reviewers: buda Reviewed By: buda Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D2806
This commit is contained in:
parent
1513a455de
commit
aaf0c1ca08
@ -10,12 +10,15 @@
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "slk/streams.hpp"
|
||||
#include "utils/cast.hpp"
|
||||
#include "utils/endian.hpp"
|
||||
#include "utils/exceptions.hpp"
|
||||
|
||||
// The namespace name stands for SaveLoadKit. It should be not mistaken for the
|
||||
@ -90,10 +93,11 @@ void Load(
|
||||
|
||||
// Implementation of serialization for primitive types.
|
||||
|
||||
#define MAKE_PRIMITIVE_SAVE(primitive_type) \
|
||||
inline void Save(primitive_type obj, Builder *builder) { \
|
||||
builder->Save(reinterpret_cast<const uint8_t *>(&obj), \
|
||||
sizeof(primitive_type)); \
|
||||
#define MAKE_PRIMITIVE_SAVE(primitive_type) \
|
||||
inline void Save(primitive_type obj, Builder *builder) { \
|
||||
primitive_type obj_encoded = utils::HostToLittleEndian(obj); \
|
||||
builder->Save(reinterpret_cast<const uint8_t *>(&obj_encoded), \
|
||||
sizeof(primitive_type)); \
|
||||
}
|
||||
|
||||
MAKE_PRIMITIVE_SAVE(bool)
|
||||
@ -106,14 +110,15 @@ MAKE_PRIMITIVE_SAVE(int32_t)
|
||||
MAKE_PRIMITIVE_SAVE(uint32_t)
|
||||
MAKE_PRIMITIVE_SAVE(int64_t)
|
||||
MAKE_PRIMITIVE_SAVE(uint64_t)
|
||||
MAKE_PRIMITIVE_SAVE(float)
|
||||
MAKE_PRIMITIVE_SAVE(double)
|
||||
|
||||
#undef MAKE_PRIMITIVE_SAVE
|
||||
|
||||
#define MAKE_PRIMITIVE_LOAD(primitive_type) \
|
||||
inline void Load(primitive_type *obj, Reader *reader) { \
|
||||
reader->Load(reinterpret_cast<uint8_t *>(obj), sizeof(primitive_type)); \
|
||||
#define MAKE_PRIMITIVE_LOAD(primitive_type) \
|
||||
inline void Load(primitive_type *obj, Reader *reader) { \
|
||||
primitive_type obj_encoded; \
|
||||
reader->Load(reinterpret_cast<uint8_t *>(&obj_encoded), \
|
||||
sizeof(primitive_type)); \
|
||||
*obj = utils::LittleEndianToHost(obj_encoded); \
|
||||
}
|
||||
|
||||
MAKE_PRIMITIVE_LOAD(bool)
|
||||
@ -126,11 +131,29 @@ MAKE_PRIMITIVE_LOAD(int32_t)
|
||||
MAKE_PRIMITIVE_LOAD(uint32_t)
|
||||
MAKE_PRIMITIVE_LOAD(int64_t)
|
||||
MAKE_PRIMITIVE_LOAD(uint64_t)
|
||||
MAKE_PRIMITIVE_LOAD(float)
|
||||
MAKE_PRIMITIVE_LOAD(double)
|
||||
|
||||
#undef MAKE_PRIMITIVE_LOAD
|
||||
|
||||
inline void Save(float obj, Builder *builder) {
|
||||
slk::Save(utils::MemcpyCast<uint32_t>(obj), builder);
|
||||
}
|
||||
|
||||
inline void Save(double obj, Builder *builder) {
|
||||
slk::Save(utils::MemcpyCast<uint64_t>(obj), builder);
|
||||
}
|
||||
|
||||
inline void Load(float *obj, Reader *reader) {
|
||||
uint32_t obj_encoded;
|
||||
slk::Load(&obj_encoded, reader);
|
||||
*obj = utils::MemcpyCast<float>(obj_encoded);
|
||||
}
|
||||
|
||||
inline void Load(double *obj, Reader *reader) {
|
||||
uint64_t obj_encoded;
|
||||
slk::Load(&obj_encoded, reader);
|
||||
*obj = utils::MemcpyCast<double>(obj_encoded);
|
||||
}
|
||||
|
||||
// Implementation of serialization of complex types.
|
||||
|
||||
inline void Save(const std::string &obj, Builder *builder) {
|
||||
@ -139,6 +162,18 @@ inline void Save(const std::string &obj, Builder *builder) {
|
||||
builder->Save(reinterpret_cast<const uint8_t *>(obj.data()), size);
|
||||
}
|
||||
|
||||
inline void Save(const char *obj, Builder *builder) {
|
||||
uint64_t size = strlen(obj);
|
||||
Save(size, builder);
|
||||
builder->Save(reinterpret_cast<const uint8_t *>(obj), size);
|
||||
}
|
||||
|
||||
inline void Save(const std::string_view &obj, Builder *builder) {
|
||||
uint64_t size = obj.size();
|
||||
Save(size, builder);
|
||||
builder->Save(reinterpret_cast<const uint8_t *>(obj.data()), size);
|
||||
}
|
||||
|
||||
inline void Load(std::string *obj, Reader *reader) {
|
||||
uint64_t size = 0;
|
||||
Load(&size, reader);
|
||||
|
@ -6,9 +6,11 @@
|
||||
|
||||
namespace utils {
|
||||
|
||||
inline uint8_t HostToLittleEndian(uint8_t value) { return value; }
|
||||
inline uint16_t HostToLittleEndian(uint16_t value) { return htole16(value); }
|
||||
inline uint32_t HostToLittleEndian(uint32_t value) { return htole32(value); }
|
||||
inline uint64_t HostToLittleEndian(uint64_t value) { return htole64(value); }
|
||||
inline int8_t HostToLittleEndian(int8_t value) { return value; }
|
||||
inline int16_t HostToLittleEndian(int16_t value) {
|
||||
return MemcpyCast<int16_t>(htole16(MemcpyCast<uint16_t>(value)));
|
||||
}
|
||||
@ -19,9 +21,11 @@ inline int64_t HostToLittleEndian(int64_t value) {
|
||||
return MemcpyCast<int64_t>(htole64(MemcpyCast<uint64_t>(value)));
|
||||
}
|
||||
|
||||
inline uint8_t LittleEndianToHost(uint8_t value) { return value; }
|
||||
inline uint16_t LittleEndianToHost(uint16_t value) { return le16toh(value); }
|
||||
inline uint32_t LittleEndianToHost(uint32_t value) { return le32toh(value); }
|
||||
inline uint64_t LittleEndianToHost(uint64_t value) { return le64toh(value); }
|
||||
inline int8_t LittleEndianToHost(int8_t value) { return value; }
|
||||
inline int16_t LittleEndianToHost(int16_t value) {
|
||||
return MemcpyCast<int16_t>(le16toh(MemcpyCast<uint16_t>(value)));
|
||||
}
|
||||
@ -32,9 +36,11 @@ inline int64_t LittleEndianToHost(int64_t value) {
|
||||
return MemcpyCast<int64_t>(le64toh(MemcpyCast<uint64_t>(value)));
|
||||
}
|
||||
|
||||
inline uint8_t HostToBigEndian(uint8_t value) { return value; }
|
||||
inline uint16_t HostToBigEndian(uint16_t value) { return htobe16(value); }
|
||||
inline uint32_t HostToBigEndian(uint32_t value) { return htobe32(value); }
|
||||
inline uint64_t HostToBigEndian(uint64_t value) { return htobe64(value); }
|
||||
inline int8_t HostToBigEndian(int8_t value) { return value; }
|
||||
inline int16_t HostToBigEndian(int16_t value) {
|
||||
return MemcpyCast<int16_t>(htobe16(MemcpyCast<uint16_t>(value)));
|
||||
}
|
||||
@ -45,9 +51,11 @@ inline int64_t HostToBigEndian(int64_t value) {
|
||||
return MemcpyCast<int64_t>(htobe64(MemcpyCast<uint64_t>(value)));
|
||||
}
|
||||
|
||||
inline uint8_t BigEndianToHost(uint8_t value) { return value; }
|
||||
inline uint16_t BigEndianToHost(uint16_t value) { return be16toh(value); }
|
||||
inline uint32_t BigEndianToHost(uint32_t value) { return be32toh(value); }
|
||||
inline uint64_t BigEndianToHost(uint64_t value) { return be64toh(value); }
|
||||
inline int8_t BigEndianToHost(int8_t value) { return value; }
|
||||
inline int16_t BigEndianToHost(int16_t value) {
|
||||
return MemcpyCast<int16_t>(be16toh(MemcpyCast<uint16_t>(value)));
|
||||
}
|
||||
|
@ -44,6 +44,18 @@ TEST(SlkCore, String) {
|
||||
ASSERT_EQ(loopback.size(), sizeof(uint64_t) + original.size());
|
||||
}
|
||||
|
||||
TEST(SlkCore, ConstStringLiteral) {
|
||||
const char *original = "hello world";
|
||||
slk::Loopback loopback;
|
||||
auto builder = loopback.GetBuilder();
|
||||
slk::Save(original, builder);
|
||||
std::string decoded;
|
||||
auto reader = loopback.GetReader();
|
||||
slk::Load(&decoded, reader);
|
||||
ASSERT_EQ(original, decoded);
|
||||
ASSERT_EQ(loopback.size(), sizeof(uint64_t) + strlen(original));
|
||||
}
|
||||
|
||||
TEST(SlkCore, VectorPrimitive) {
|
||||
std::vector<int> original{1, 2, 3, 4, 5};
|
||||
slk::Loopback loopback;
|
||||
|
Loading…
Reference in New Issue
Block a user