rename StructMapping to StructLayout
This commit is contained in:
parent
d0bc679815
commit
bcd6f40ddb
@ -1,4 +1,4 @@
|
|||||||
#include "StructMapper.hpp"
|
#include "StructLayout.hpp"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -13,7 +13,7 @@ using namespace data;
|
|||||||
static_assert(sizeof(float) == sizeof(int32_t));
|
static_assert(sizeof(float) == sizeof(int32_t));
|
||||||
static_assert(sizeof(double) == sizeof(int64_t));
|
static_assert(sizeof(double) == sizeof(int64_t));
|
||||||
|
|
||||||
StructMapping StructMapping::create(const std::vector<Field>& fields) {
|
StructLayout StructLayout::create(const std::vector<Field>& fields) {
|
||||||
std::vector<Field> builtFields = fields;
|
std::vector<Field> builtFields = fields;
|
||||||
std::unordered_map<std::string, int> indices;
|
std::unordered_map<std::string, int> indices;
|
||||||
|
|
||||||
@ -32,11 +32,11 @@ StructMapping StructMapping::create(const std::vector<Field>& fields) {
|
|||||||
indices[field.name] = i;
|
indices[field.name] = i;
|
||||||
offset += field.size;
|
offset += field.size;
|
||||||
}
|
}
|
||||||
return StructMapping(
|
return StructLayout(
|
||||||
offset, std::move(builtFields), std::move(indices));
|
offset, std::move(builtFields), std::move(indices));
|
||||||
}
|
}
|
||||||
|
|
||||||
const Field& StructMapping::requreField(const std::string& name) const {
|
const Field& StructLayout::requreField(const std::string& name) const {
|
||||||
auto found = indices.find(name);
|
auto found = indices.find(name);
|
||||||
if (found == indices.end()) {
|
if (found == indices.end()) {
|
||||||
throw std::runtime_error("field '"+name+"' does not exist");
|
throw std::runtime_error("field '"+name+"' does not exist");
|
||||||
@ -52,7 +52,7 @@ static void set_int(ubyte* dst, integer_t value) {
|
|||||||
*reinterpret_cast<T*>(dst) = out_value;
|
*reinterpret_cast<T*>(dst) = out_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StructMapping::setInteger(
|
void StructLayout::setInteger(
|
||||||
ubyte* dst, integer_t value, const std::string& name, int index
|
ubyte* dst, integer_t value, const std::string& name, int index
|
||||||
) {
|
) {
|
||||||
const auto& field = requreField(name);
|
const auto& field = requreField(name);
|
||||||
@ -76,7 +76,7 @@ void StructMapping::setInteger(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StructMapping::setNumber(
|
void StructLayout::setNumber(
|
||||||
ubyte* dst, number_t value, const std::string& name, int index
|
ubyte* dst, number_t value, const std::string& name, int index
|
||||||
) {
|
) {
|
||||||
const auto& field = requreField(name);
|
const auto& field = requreField(name);
|
||||||
@ -105,7 +105,7 @@ void StructMapping::setNumber(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t StructMapping::setChars(
|
size_t StructLayout::setChars(
|
||||||
ubyte* dst, std::string_view value, const std::string& name
|
ubyte* dst, std::string_view value, const std::string& name
|
||||||
) {
|
) {
|
||||||
const auto& field = requreField(name);
|
const auto& field = requreField(name);
|
||||||
@ -118,7 +118,7 @@ size_t StructMapping::setChars(
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t StructMapping::setUnicode(
|
size_t StructLayout::setUnicode(
|
||||||
ubyte* dst, std::string_view value, const std::string& name
|
ubyte* dst, std::string_view value, const std::string& name
|
||||||
) {
|
) {
|
||||||
const auto& field = requreField(name);
|
const auto& field = requreField(name);
|
||||||
@ -137,7 +137,7 @@ static T get_int(const ubyte* src) {
|
|||||||
return dataio::le2h(*reinterpret_cast<const T*>(src));
|
return dataio::le2h(*reinterpret_cast<const T*>(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
integer_t StructMapping::getInteger(
|
integer_t StructLayout::getInteger(
|
||||||
const ubyte* src, const std::string& name, int index
|
const ubyte* src, const std::string& name, int index
|
||||||
) const {
|
) const {
|
||||||
const auto& field = requreField(name);
|
const auto& field = requreField(name);
|
||||||
@ -157,7 +157,7 @@ integer_t StructMapping::getInteger(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
number_t StructMapping::getNumber(
|
number_t StructLayout::getNumber(
|
||||||
const ubyte* src, const std::string& name, int index
|
const ubyte* src, const std::string& name, int index
|
||||||
) const {
|
) const {
|
||||||
const auto& field = requreField(name);
|
const auto& field = requreField(name);
|
||||||
@ -190,7 +190,7 @@ number_t StructMapping::getNumber(
|
|||||||
throw std::runtime_error("type error");
|
throw std::runtime_error("type error");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view StructMapping::getChars(
|
std::string_view StructLayout::getChars(
|
||||||
const ubyte* src, const std::string& name
|
const ubyte* src, const std::string& name
|
||||||
) const {
|
) const {
|
||||||
const auto& field = requreField(name);
|
const auto& field = requreField(name);
|
||||||
@ -30,12 +30,12 @@ namespace data {
|
|||||||
int size;
|
int size;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StructMapping {
|
class StructLayout {
|
||||||
int totalSize;
|
int totalSize;
|
||||||
std::vector<Field> fields;
|
std::vector<Field> fields;
|
||||||
std::unordered_map<std::string, int> indices;
|
std::unordered_map<std::string, int> indices;
|
||||||
public:
|
public:
|
||||||
StructMapping(
|
StructLayout(
|
||||||
int totalSize,
|
int totalSize,
|
||||||
std::vector<Field> fields,
|
std::vector<Field> fields,
|
||||||
std::unordered_map<std::string, int> indices
|
std::unordered_map<std::string, int> indices
|
||||||
@ -47,6 +47,7 @@ namespace data {
|
|||||||
/// @brief Get field by name. Returns nullptr if field not found.
|
/// @brief Get field by name. Returns nullptr if field not found.
|
||||||
/// @param name field name
|
/// @param name field name
|
||||||
/// @return nullable field pointer
|
/// @return nullable field pointer
|
||||||
|
[[nodiscard]]
|
||||||
const Field* getField(const std::string& name) const {
|
const Field* getField(const std::string& name) const {
|
||||||
auto found = indices.find(name);
|
auto found = indices.find(name);
|
||||||
if (found == indices.end()) {
|
if (found == indices.end()) {
|
||||||
@ -128,18 +129,19 @@ namespace data {
|
|||||||
size_t setUnicode(ubyte* dst, std::string_view value, const std::string& name);
|
size_t setUnicode(ubyte* dst, std::string_view value, const std::string& name);
|
||||||
|
|
||||||
/// @return total structure size (bytes)
|
/// @return total structure size (bytes)
|
||||||
int size() const {
|
[[nodiscard]] size_t size() const {
|
||||||
return totalSize;
|
return totalSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static StructMapping create(const std::vector<Field>& fields);
|
[[nodiscard]]
|
||||||
|
static StructLayout create(const std::vector<Field>& fields);
|
||||||
};
|
};
|
||||||
|
|
||||||
class StructAccess {
|
class StructAccess {
|
||||||
const StructMapping& mapping;
|
const StructLayout& mapping;
|
||||||
uint8_t* buffer;
|
uint8_t* buffer;
|
||||||
public:
|
public:
|
||||||
StructAccess(const StructMapping& mapping, uint8_t* buffer)
|
StructAccess(const StructLayout& mapping, uint8_t* buffer)
|
||||||
: mapping(mapping), buffer(buffer) {
|
: mapping(mapping), buffer(buffer) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -22,7 +22,8 @@ namespace util {
|
|||||||
|
|
||||||
/// @brief Find current entry address by index
|
/// @brief Find current entry address by index
|
||||||
/// @param index entry index
|
/// @param index entry index
|
||||||
/// @return nullptr if entry does not exists
|
/// @return temporary raw pointer or nullptr if entry does not exists
|
||||||
|
/// @attention pointer becomes invalid after allocate(...) or free(...)
|
||||||
uint8_t* find(Tindex index) {
|
uint8_t* find(Tindex index) {
|
||||||
auto data = buffer.data();
|
auto data = buffer.data();
|
||||||
for (size_t i = 0; i < entriesCount; i++) {
|
for (size_t i = 0; i < entriesCount; i++) {
|
||||||
@ -60,7 +61,7 @@ namespace util {
|
|||||||
/// @param index entry index
|
/// @param index entry index
|
||||||
/// @param size entry size
|
/// @param size entry size
|
||||||
/// @return temporary entry pointer
|
/// @return temporary entry pointer
|
||||||
/// (invalid after next allocate(...) or free(...))
|
/// @attention pointer becomes invalid after allocate(...) or free(...)
|
||||||
uint8_t* allocate(Tindex index, Tsize size) {
|
uint8_t* allocate(Tindex index, Tsize size) {
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
throw std::runtime_error("size is 0");
|
throw std::runtime_error("size is 0");
|
||||||
|
|||||||
41
test/data/StructLayout.cpp
Normal file
41
test/data/StructLayout.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#include "data/StructLayout.hpp"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
using namespace data;
|
||||||
|
|
||||||
|
TEST(StructLayout, ReadWrite) {
|
||||||
|
ubyte buffer[16] {};
|
||||||
|
|
||||||
|
std::vector<Field> fields {
|
||||||
|
Field {FieldType::I8, "a", 1},
|
||||||
|
Field {FieldType::CHAR, "s", 4},
|
||||||
|
Field {FieldType::F32, "f", 1},
|
||||||
|
};
|
||||||
|
auto layout = StructLayout::create(fields);
|
||||||
|
EXPECT_EQ(layout.size(), 9);
|
||||||
|
|
||||||
|
layout.setInteger(buffer, 42, "a");
|
||||||
|
EXPECT_EQ(layout.getInteger(buffer, "a"), 42);
|
||||||
|
|
||||||
|
layout.setNumber(buffer, 3.141592f, "f");
|
||||||
|
EXPECT_FLOAT_EQ(layout.getNumber(buffer, "f"), 3.141592f);
|
||||||
|
|
||||||
|
layout.setChars(buffer, "hello", "s");
|
||||||
|
EXPECT_EQ(layout.getChars(buffer, "s"), "hell");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(StructLayout, Unicode) {
|
||||||
|
ubyte buffer[8] {};
|
||||||
|
std::vector<Field> fields {
|
||||||
|
Field {FieldType::CHAR, "text", 5},
|
||||||
|
};
|
||||||
|
auto layout = StructLayout::create(fields);
|
||||||
|
EXPECT_EQ(layout.size(), 5);
|
||||||
|
|
||||||
|
layout.setUnicode(buffer, u8"テキストデモ", "text");
|
||||||
|
EXPECT_EQ(layout.getChars(buffer, "text"), std::string(u8"テ"));
|
||||||
|
|
||||||
|
layout.setUnicode(buffer, u8"пример", "text");
|
||||||
|
EXPECT_EQ(layout.getChars(buffer, "text"), std::string(u8"пр"));
|
||||||
|
}
|
||||||
@ -1,41 +0,0 @@
|
|||||||
#include "data/StructMapper.hpp"
|
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
using namespace data;
|
|
||||||
|
|
||||||
TEST(StructMapper, ReadWrite) {
|
|
||||||
ubyte buffer[16] {};
|
|
||||||
|
|
||||||
std::vector<Field> fields {
|
|
||||||
Field {FieldType::I8, "a", 1},
|
|
||||||
Field {FieldType::CHAR, "s", 4},
|
|
||||||
Field {FieldType::F32, "f", 1},
|
|
||||||
};
|
|
||||||
auto mapping = StructMapping::create(fields);
|
|
||||||
EXPECT_EQ(mapping.size(), 9);
|
|
||||||
|
|
||||||
mapping.setInteger(buffer, 42, "a");
|
|
||||||
EXPECT_EQ(mapping.getInteger(buffer, "a"), 42);
|
|
||||||
|
|
||||||
mapping.setNumber(buffer, 3.141592f, "f");
|
|
||||||
EXPECT_FLOAT_EQ(mapping.getNumber(buffer, "f"), 3.141592f);
|
|
||||||
|
|
||||||
mapping.setChars(buffer, "hello", "s");
|
|
||||||
EXPECT_EQ(mapping.getChars(buffer, "s"), "hell");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StructMapper, Unicode) {
|
|
||||||
ubyte buffer[8] {};
|
|
||||||
std::vector<Field> fields {
|
|
||||||
Field {FieldType::CHAR, "text", 5},
|
|
||||||
};
|
|
||||||
auto mapping = StructMapping::create(fields);
|
|
||||||
EXPECT_EQ(mapping.size(), 5);
|
|
||||||
|
|
||||||
mapping.setUnicode(buffer, u8"テキストデモ", "text");
|
|
||||||
EXPECT_EQ(mapping.getChars(buffer, "text"), std::string(u8"テ"));
|
|
||||||
|
|
||||||
mapping.setUnicode(buffer, u8"пример", "text");
|
|
||||||
EXPECT_EQ(mapping.getChars(buffer, "text"), std::string(u8"пр"));
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user