add StructLayout::convert (WIP)
This commit is contained in:
parent
5afbad1bd6
commit
caa5e1b03b
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdexcept>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "util/data_io.hpp"
|
#include "util/data_io.hpp"
|
||||||
@ -36,6 +35,35 @@ StructLayout StructLayout::create(const std::vector<Field>& fields) {
|
|||||||
offset, std::move(builtFields), std::move(indices));
|
offset, std::move(builtFields), std::move(indices));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline constexpr bool is_integer_type(FieldType type) {
|
||||||
|
return (type >= FieldType::I8 && type <= FieldType::I64) ||
|
||||||
|
type == FieldType::CHAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline constexpr bool is_floating_point_type(FieldType type) {
|
||||||
|
return type == FieldType::F32 || type == FieldType::F64;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline constexpr bool is_numeric_type(FieldType type) {
|
||||||
|
return is_floating_point_type(type) || is_integer_type(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StructLayout::convert(
|
||||||
|
const StructLayout& srcLayout,
|
||||||
|
const ubyte* src,
|
||||||
|
ubyte* dst,
|
||||||
|
bool allowDataLoss
|
||||||
|
) const {
|
||||||
|
for (const Field& field : fields) {
|
||||||
|
auto srcField = srcLayout.getField(field.name);
|
||||||
|
if (srcField == nullptr) {
|
||||||
|
std::memset(dst + field.offset, 0, field.size);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// TODO: implement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const Field& StructLayout::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()) {
|
||||||
@ -54,7 +82,7 @@ static void set_int(ubyte* dst, integer_t value) {
|
|||||||
|
|
||||||
void StructLayout::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 {
|
||||||
const auto& field = requreField(name);
|
const auto& field = requreField(name);
|
||||||
if (index < 0 || index >= field.elements) {
|
if (index < 0 || index >= field.elements) {
|
||||||
throw std::out_of_range(
|
throw std::out_of_range(
|
||||||
@ -78,7 +106,7 @@ void StructLayout::setInteger(
|
|||||||
|
|
||||||
void StructLayout::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 {
|
||||||
const auto& field = requreField(name);
|
const auto& field = requreField(name);
|
||||||
if (index < 0 || index >= field.elements) {
|
if (index < 0 || index >= field.elements) {
|
||||||
throw std::out_of_range(
|
throw std::out_of_range(
|
||||||
@ -107,7 +135,7 @@ void StructLayout::setNumber(
|
|||||||
|
|
||||||
size_t StructLayout::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 {
|
||||||
const auto& field = requreField(name);
|
const auto& field = requreField(name);
|
||||||
if (field.type != FieldType::CHAR) {
|
if (field.type != FieldType::CHAR) {
|
||||||
throw std::runtime_error("'char' field type required");
|
throw std::runtime_error("'char' field type required");
|
||||||
@ -120,7 +148,7 @@ size_t StructLayout::setChars(
|
|||||||
|
|
||||||
size_t StructLayout::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 {
|
||||||
const auto& field = requreField(name);
|
const auto& field = requreField(name);
|
||||||
if (field.type != FieldType::CHAR) {
|
if (field.type != FieldType::CHAR) {
|
||||||
throw std::runtime_error("'char' field type required");
|
throw std::runtime_error("'char' field type required");
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <stdexcept>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
@ -19,6 +20,11 @@ namespace data {
|
|||||||
return sizes[static_cast<int>(type)];
|
return sizes[static_cast<int>(type)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class dataloss_error : public std::runtime_error {
|
||||||
|
public:
|
||||||
|
dataloss_error(const std::string& message) : std::runtime_error(message) {}
|
||||||
|
};
|
||||||
|
|
||||||
struct Field {
|
struct Field {
|
||||||
FieldType type;
|
FieldType type;
|
||||||
std::string name;
|
std::string name;
|
||||||
@ -99,7 +105,7 @@ namespace data {
|
|||||||
/// @param value value
|
/// @param value value
|
||||||
/// @param name field name
|
/// @param name field name
|
||||||
/// @param index array index
|
/// @param index array index
|
||||||
void setInteger(ubyte* dst, integer_t value, const std::string& name, int index=0);
|
void setInteger(ubyte* dst, integer_t value, const std::string& name, int index=0) const;
|
||||||
|
|
||||||
/// @brief Set field numeric value.
|
/// @brief Set field numeric value.
|
||||||
/// Types: (f32, f64)
|
/// Types: (f32, f64)
|
||||||
@ -109,7 +115,7 @@ namespace data {
|
|||||||
/// @param value value
|
/// @param value value
|
||||||
/// @param name field name
|
/// @param name field name
|
||||||
/// @param index array index
|
/// @param index array index
|
||||||
void setNumber(ubyte* dst, number_t value, const std::string& name, int index=0);
|
void setNumber(ubyte* dst, number_t value, const std::string& name, int index=0) const;
|
||||||
|
|
||||||
/// @brief Replace chars array to given ASCII string
|
/// @brief Replace chars array to given ASCII string
|
||||||
/// @throws std::runtime_exception - field not found
|
/// @throws std::runtime_exception - field not found
|
||||||
@ -118,7 +124,7 @@ namespace data {
|
|||||||
/// @param value ASCII string
|
/// @param value ASCII string
|
||||||
/// @param name field name
|
/// @param name field name
|
||||||
/// @return number of written string chars
|
/// @return number of written string chars
|
||||||
size_t setChars(ubyte* dst, std::string_view value, const std::string& name);
|
size_t setChars(ubyte* dst, std::string_view value, const std::string& name) const;
|
||||||
|
|
||||||
/// @brief Unicode-safe version of setChars
|
/// @brief Unicode-safe version of setChars
|
||||||
/// @throws std::runtime_exception - field not found
|
/// @throws std::runtime_exception - field not found
|
||||||
@ -126,23 +132,31 @@ namespace data {
|
|||||||
/// @param value utf-8 string
|
/// @param value utf-8 string
|
||||||
/// @param name field name
|
/// @param name field name
|
||||||
/// @return number of written string chars
|
/// @return number of written string chars
|
||||||
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) const;
|
||||||
|
|
||||||
/// @return total structure size (bytes)
|
/// @return total structure size (bytes)
|
||||||
[[nodiscard]] size_t size() const {
|
[[nodiscard]] size_t size() const {
|
||||||
return totalSize;
|
return totalSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Convert structure data from srcLayout to this layout.
|
||||||
|
/// @param srcLayout source structure layout
|
||||||
|
/// @param src source data
|
||||||
|
/// @param dst destination buffer
|
||||||
|
/// (size must be enough to store converted structure)
|
||||||
|
/// @param allowDataLoss allow to drop fields that are not present in
|
||||||
|
/// this layout or have incompatible types
|
||||||
|
/// @throws data::dataloss_error - data loss detected and allowDataLoss
|
||||||
|
/// is set to false
|
||||||
|
void convert(
|
||||||
|
const StructLayout& srcLayout,
|
||||||
|
const ubyte* src,
|
||||||
|
ubyte* dst,
|
||||||
|
bool allowDataLoss) const;
|
||||||
|
|
||||||
|
/// TODO: add checkCompatibility method
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
static StructLayout create(const std::vector<Field>& fields);
|
static StructLayout create(const std::vector<Field>& fields);
|
||||||
};
|
};
|
||||||
|
|
||||||
class StructAccess {
|
|
||||||
const StructLayout& mapping;
|
|
||||||
uint8_t* buffer;
|
|
||||||
public:
|
|
||||||
StructAccess(const StructLayout& mapping, uint8_t* buffer)
|
|
||||||
: mapping(mapping), buffer(buffer) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,3 +39,7 @@ TEST(StructLayout, Unicode) {
|
|||||||
layout.setUnicode(buffer, u8"пример", "text");
|
layout.setUnicode(buffer, u8"пример", "text");
|
||||||
EXPECT_EQ(layout.getChars(buffer, "text"), std::string(u8"пр"));
|
EXPECT_EQ(layout.getChars(buffer, "text"), std::string(u8"пр"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(StructLayout, Convert) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user