add StructLayout::convert (WIP)
This commit is contained in:
parent
5afbad1bd6
commit
caa5e1b03b
@ -2,7 +2,6 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <string.h>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
#include "util/data_io.hpp"
|
||||
@ -36,6 +35,35 @@ StructLayout StructLayout::create(const std::vector<Field>& fields) {
|
||||
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 {
|
||||
auto found = indices.find(name);
|
||||
if (found == indices.end()) {
|
||||
@ -54,7 +82,7 @@ static void set_int(ubyte* dst, integer_t value) {
|
||||
|
||||
void StructLayout::setInteger(
|
||||
ubyte* dst, integer_t value, const std::string& name, int index
|
||||
) {
|
||||
) const {
|
||||
const auto& field = requreField(name);
|
||||
if (index < 0 || index >= field.elements) {
|
||||
throw std::out_of_range(
|
||||
@ -78,7 +106,7 @@ void StructLayout::setInteger(
|
||||
|
||||
void StructLayout::setNumber(
|
||||
ubyte* dst, number_t value, const std::string& name, int index
|
||||
) {
|
||||
) const {
|
||||
const auto& field = requreField(name);
|
||||
if (index < 0 || index >= field.elements) {
|
||||
throw std::out_of_range(
|
||||
@ -107,7 +135,7 @@ void StructLayout::setNumber(
|
||||
|
||||
size_t StructLayout::setChars(
|
||||
ubyte* dst, std::string_view value, const std::string& name
|
||||
) {
|
||||
) const {
|
||||
const auto& field = requreField(name);
|
||||
if (field.type != FieldType::CHAR) {
|
||||
throw std::runtime_error("'char' field type required");
|
||||
@ -120,7 +148,7 @@ size_t StructLayout::setChars(
|
||||
|
||||
size_t StructLayout::setUnicode(
|
||||
ubyte* dst, std::string_view value, const std::string& name
|
||||
) {
|
||||
) const {
|
||||
const auto& field = requreField(name);
|
||||
if (field.type != FieldType::CHAR) {
|
||||
throw std::runtime_error("'char' field type required");
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "typedefs.hpp"
|
||||
@ -19,6 +20,11 @@ namespace data {
|
||||
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 {
|
||||
FieldType type;
|
||||
std::string name;
|
||||
@ -99,7 +105,7 @@ namespace data {
|
||||
/// @param value value
|
||||
/// @param name field name
|
||||
/// @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.
|
||||
/// Types: (f32, f64)
|
||||
@ -109,7 +115,7 @@ namespace data {
|
||||
/// @param value value
|
||||
/// @param name field name
|
||||
/// @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
|
||||
/// @throws std::runtime_exception - field not found
|
||||
@ -118,7 +124,7 @@ namespace data {
|
||||
/// @param value ASCII string
|
||||
/// @param name field name
|
||||
/// @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
|
||||
/// @throws std::runtime_exception - field not found
|
||||
@ -126,23 +132,31 @@ namespace data {
|
||||
/// @param value utf-8 string
|
||||
/// @param name field name
|
||||
/// @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)
|
||||
[[nodiscard]] size_t size() const {
|
||||
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]]
|
||||
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");
|
||||
EXPECT_EQ(layout.getChars(buffer, "text"), std::string(u8"пр"));
|
||||
}
|
||||
|
||||
TEST(StructLayout, Convert) {
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user