Skip to content

Commit

Permalink
[struct_pack][fix] fix bug of struct_pack::write
Browse files Browse the repository at this point in the history
  • Loading branch information
poor-circle committed Dec 25, 2023
1 parent a21a606 commit 7b91b85
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 12 deletions.
21 changes: 14 additions & 7 deletions include/ylt/struct_pack/endian_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,8 @@ STRUCT_PACK_INLINE void write(Writer& writer, const T& t) {
std::uint64_t len = t.size();
detail::write_wrapper<sizeof(std::size_t)>(writer, (char*)&len);
if constexpr (detail::continuous_container<T> &&
detail::is_little_endian_copyable<sizeof(t[0])>) {
detail::is_little_endian_copyable<sizeof(t[0])> &&
std::is_fundamental_v<typename T::value_type>) {
write_bytes_array(writer, (const char*)t.data(), len * sizeof(t[0]));
}
else {
Expand Down Expand Up @@ -353,7 +354,7 @@ STRUCT_PACK_INLINE constexpr std::size_t get_write_size(const T* t,
template <typename Reader, typename T>
STRUCT_PACK_INLINE struct_pack::errc read(Reader& reader, T& t) {
if constexpr (std::is_fundamental_v<T>) {
if (!detail::read_wrapper<sizeof(T)>(reader, (char*)&t)) {
if SP_UNLIKELY (!detail::read_wrapper<sizeof(T)>(reader, (char*)&t)) {
return struct_pack::errc::no_buffer_space;
}
else {
Expand All @@ -364,7 +365,12 @@ STRUCT_PACK_INLINE struct_pack::errc read(Reader& reader, T& t) {
if constexpr (std::is_fundamental_v<
std::remove_reference_t<decltype(t[0])>> &&
detail::is_little_endian_copyable<sizeof(t[0])>) {
return read_bytes_array(reader, (char*)t.data(), sizeof(T));
if SP_UNLIKELY (!read_bytes_array(reader, (char*)t.data(), sizeof(T))) {
return struct_pack::errc::no_buffer_space;
}
else {
return {};
}
}
else {
struct_pack::errc ec;
Expand Down Expand Up @@ -395,15 +401,16 @@ STRUCT_PACK_INLINE struct_pack::errc read(Reader& reader, T& t) {
if SP_UNLIKELY (!reader.check(mem_size)) {
return struct_pack::errc::no_buffer_space;
}
detail::resize(t, mem_size);
if (!read_bytes_array(reader, (char*)t.data(), mem_size)) {
detail::resize(t, sz);
if SP_UNLIKELY (!read_bytes_array(reader, (char*)t.data(), mem_size)) {
return struct_pack::errc::no_buffer_space;
}
return struct_pack::errc{};
}
else {
t.clear();
for (std::size_t i = 0; i < sz; ++i) {
t.emplace_back();
t.push_back(typename T::value_type{});
ec = read(reader, t.back());
if SP_UNLIKELY (ec != struct_pack::errc{}) {
return ec;
Expand All @@ -420,7 +427,7 @@ template <typename Reader, typename T>
struct_pack::errc read(Reader& reader, T* t, std::size_t length) {
if constexpr (std::is_fundamental_v<T>) {
if constexpr (detail::is_little_endian_copyable<sizeof(T)>) {
if (!read_bytes_array(reader, (char*)t, sizeof(T) * length)) {
if SP_UNLIKELY (!read_bytes_array(reader, (char*)t, sizeof(T) * length)) {
return struct_pack::errc::no_buffer_space;
}
else {
Expand Down
53 changes: 48 additions & 5 deletions src/struct_pack/tests/test_user_defined_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,80 @@

#include "doctest.h"
#include "ylt/struct_pack.hpp"
#include "ylt/struct_pack/endian_wrapper.hpp"
#include "ylt/struct_pack/error_code.hpp"
#include "ylt/struct_pack/type_id.hpp"
namespace my_name_space {

struct array2D {
std::string name = "Hello";
std::vector<std::vector<int>> values = {{-1, 2, 3}};
std::array<float, 3> values2 = {1.1, 2.3, 4.5};
unsigned int x;
unsigned int y;
float* p;
array2D(unsigned int x, unsigned int y) : x(x), y(y) {
p = (float*)calloc(1ull * x * y, sizeof(float));
}
array2D(const array2D&) = delete;
array2D(array2D&& o) : x(o.x), y(o.y), p(o.p) { o.p = nullptr; };
array2D(array2D&& o)
: x(o.x),
y(o.y),
p(o.p),
values(std::move(o.values)),
values2(o.values2) {
o.p = nullptr;
};
array2D& operator=(const array2D&) = delete;
array2D& operator=(array2D&& o) {
x = o.x;
y = o.y;
p = o.p;
values = o.values;
values2 = o.values2;
o.p = nullptr;
return *this;
}
float& operator()(std::size_t i, std::size_t j) { return p[i * y + j]; }
bool operator==(const array2D& o) const {
return x == o.x && y == o.y &&
memcmp(p, o.p, 1ull * x * y * sizeof(float)) == 0;
memcmp(p, o.p, 1ull * x * y * sizeof(float)) == 0 &&
values == o.values && values2 == o.values2;
}
array2D() : x(0), y(0), p(nullptr) {}
~array2D() { free(p); }
};

std::size_t sp_get_needed_size(const array2D& ar) {
return 2 * struct_pack::get_write_size(ar.x) +
return struct_pack::get_write_size(ar.name) +
struct_pack::get_write_size(ar.values) +
struct_pack::get_write_size(ar.values2) +
2 * struct_pack::get_write_size(ar.x) +
struct_pack::get_write_size(ar.p, 1ull * ar.x * ar.y);
}
template <typename Writer>
void sp_serialize_to(Writer& writer, const array2D& ar) {
struct_pack::write(writer, ar.name);
struct_pack::write(writer, ar.values);
struct_pack::write(writer, ar.values2);
struct_pack::write(writer, ar.x);
struct_pack::write(writer, ar.y);
struct_pack::write(writer, ar.p, 1ull * ar.x * ar.y);
}

template <typename Reader>
struct_pack::errc sp_deserialize_to(Reader& reader, array2D& ar) {
if (auto ec = struct_pack::read(reader, ar.name); ec != struct_pack::errc{}) {
return ec;
}
if (auto ec = struct_pack::read(reader, ar.values);
ec != struct_pack::errc{}) {
return ec;
}
if (auto ec = struct_pack::read(reader, ar.values2);
ec != struct_pack::errc{}) {
return ec;
}
if (auto ec = struct_pack::read(reader, ar.x); ec != struct_pack::errc{}) {
return ec;
}
Expand All @@ -69,6 +100,17 @@ struct_pack::errc sp_deserialize_to(Reader& reader, array2D& ar) {

template <typename Reader>
struct_pack::errc sp_deserialize_to_with_skip(Reader& reader, array2D& ar) {
if (auto ec = struct_pack::read(reader, ar.name); ec != struct_pack::errc{}) {
return ec;
}
if (auto ec = struct_pack::read(reader, ar.values);
ec != struct_pack::errc{}) {
return ec;
}
if (auto ec = struct_pack::read(reader, ar.values2);
ec != struct_pack::errc{}) {
return ec;
}
if (auto ec = struct_pack::read(reader, ar.x); ec != struct_pack::errc{}) {
return ec;
}
Expand All @@ -92,7 +134,7 @@ TEST_CASE("test user-defined_type") {
auto result = struct_pack::deserialize<my_name_space::array2D>(buffer);
CHECK(result.has_value());
auto& ar2 = result.value();
CHECK(ar == result.value());
CHECK(ar == ar2);
}

TEST_CASE("test user-defined_type nested") {
Expand All @@ -104,7 +146,8 @@ TEST_CASE("test user-defined_type nested") {
auto buffer = struct_pack::serialize(ar);
auto result = struct_pack::deserialize<decltype(ar)>(buffer);
CHECK(result.has_value());
CHECK(ar == result);
auto& ar2 = result.value();
CHECK(ar == ar2);
}

TEST_CASE("test user-defined_type get_field") {
Expand Down

0 comments on commit 7b91b85

Please sign in to comment.