Skip to content

Commit

Permalink
Merge branch 'main' into fix_log_path
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Dec 5, 2023
2 parents 0d4bb3f + 9566c49 commit 10de98d
Show file tree
Hide file tree
Showing 17 changed files with 844 additions and 43 deletions.
5 changes: 4 additions & 1 deletion include/ylt/struct_pack/calculate_size.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ constexpr size_info inline calculate_one_size(const T &item) {
size_info ret{};
if constexpr (id == type_id::monostate_t) {
}
else if constexpr (id == type_id::user_defined_type) {
ret.total = sp_get_needed_size(item);
}
else if constexpr (detail::varint_t<type, parent_tag>) {
if constexpr (is_enable_fast_varint_coding(parent_tag)) {
// skip it. It has been calculated in parent.
Expand Down Expand Up @@ -105,7 +108,7 @@ constexpr size_info inline calculate_one_size(const T &item) {
if (item) {
if constexpr (is_base_class<typename type::element_type>) {
ret.total += sizeof(uint32_t);
bool is_ok;
bool is_ok = false;
auto index = search_type_by_md5<typename type::element_type>(
item->get_struct_pack_id(), is_ok);
if SP_UNLIKELY (!is_ok) {
Expand Down
190 changes: 181 additions & 9 deletions include/ylt/struct_pack/endian_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
#include <type_traits>

#include "reflection.hpp"
#include "ylt/struct_pack/error_code.hpp"
#include "ylt/struct_pack/marco.h"
#include "ylt/struct_pack/util.h"

namespace struct_pack::detail {
namespace struct_pack {
namespace detail {
#if __cpp_lib_endian >= 201907L
constexpr inline bool is_system_little_endian =
(std::endian::little == std::endian::native);
Expand Down Expand Up @@ -132,7 +134,8 @@ inline uint64_t bswap64(uint64_t raw) {
};

template <std::size_t block_size, typename writer_t>
void write_wrapper(writer_t& writer, const char* SP_RESTRICT data) {
STRUCT_PACK_INLINE void write_wrapper(writer_t& writer,
const char* SP_RESTRICT data) {
if constexpr (is_system_little_endian || block_size == 1) {
writer.write(data, block_size);
}
Expand All @@ -159,14 +162,16 @@ void write_wrapper(writer_t& writer, const char* SP_RESTRICT data) {
}
}
template <typename writer_t>
void write_bytes_array(writer_t& writer, const char* data, std::size_t length) {
STRUCT_PACK_INLINE void write_bytes_array(writer_t& writer, const char* data,
std::size_t length) {
if SP_UNLIKELY (length >= PTRDIFF_MAX)
unreachable();
else
writer.write(data, length);
}
template <std::size_t block_size, typename writer_t, typename T>
void low_bytes_write_wrapper(writer_t& writer, const T& elem) {
STRUCT_PACK_INLINE void low_bytes_write_wrapper(writer_t& writer,
const T& elem) {
static_assert(sizeof(T) >= block_size);
if constexpr (is_system_little_endian) {
const char* data = (const char*)&elem;
Expand Down Expand Up @@ -194,7 +199,7 @@ void low_bytes_write_wrapper(writer_t& writer, const T& elem) {
}
}
template <std::size_t block_size, typename reader_t>
bool read_wrapper(reader_t& reader, char* SP_RESTRICT data) {
STRUCT_PACK_INLINE bool read_wrapper(reader_t& reader, char* SP_RESTRICT data) {
if constexpr (is_system_little_endian || block_size == 1) {
return static_cast<bool>(reader.read(data, block_size));
}
Expand Down Expand Up @@ -225,12 +230,13 @@ bool read_wrapper(reader_t& reader, char* SP_RESTRICT data) {
}
}
template <typename reader_t>
bool read_bytes_array(reader_t& reader, char* SP_RESTRICT data,
std::size_t length) {
STRUCT_PACK_INLINE bool read_bytes_array(reader_t& reader,
char* SP_RESTRICT data,
std::size_t length) {
return static_cast<bool>(reader.read(data, length));
}
template <std::size_t block_size, typename reader_t, typename T>
bool low_bytes_read_wrapper(reader_t& reader, T& elem) {
STRUCT_PACK_INLINE bool low_bytes_read_wrapper(reader_t& reader, T& elem) {
static_assert(sizeof(T) >= block_size);
if constexpr (is_system_little_endian) {
char* data = (char*)&elem;
Expand Down Expand Up @@ -263,4 +269,170 @@ bool low_bytes_read_wrapper(reader_t& reader, T& elem) {
}
}
}
}; // namespace struct_pack::detail
} // namespace detail
template <typename Writer, typename T>
STRUCT_PACK_INLINE void write(Writer& writer, const T& t) {
if constexpr (std::is_fundamental_v<T>) {
detail::write_wrapper<sizeof(T)>(writer, (const char*)&t);
}
else if constexpr (detail::array<T>) {
if constexpr (detail::is_little_endian_copyable<sizeof(t[0])> &&
std::is_fundamental_v<decltype(t[0])>) {
writer_bytes_array(writer, (const char*)&t.data(), sizeof(T));
}
else {
for (auto& e : t) write(writer, e);
}
}
else if constexpr (detail::string<T> || detail::container<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])>) {
writer_bytes_array(writer, (const char*)&t.data(), len * sizeof(t[0]));
}
else {
for (auto& e : t) write(writer, e);
}
}
else {
static_assert(!sizeof(T), "not support type");
}
}
template <typename Writer, typename T>
STRUCT_PACK_INLINE void write(Writer& writer, const T* t, std::size_t length) {
if constexpr (std::is_fundamental_v<T>) {
if constexpr (detail::is_little_endian_copyable<sizeof(T)>) {
write_bytes_array(writer, (const char*)t, sizeof(T) * length);
}
else {
for (std::size_t i = 0; i < length; ++i) write(writer, t[i]);
}
}
else {
static_assert(!sizeof(T), "not support type");
}
}
template <typename T>
STRUCT_PACK_INLINE constexpr std::size_t get_write_size(const T& t) {
if constexpr (std::is_fundamental_v<T>) {
return sizeof(T);
}
else if constexpr (detail::array<T>) {
if constexpr (std::is_fundamental_v<decltype(t[0])>) {
return sizeof(T);
}
else {
std::size_t ret = 0;
for (auto& e : t) ret += get_write_size(e);
return ret;
}
}
else if constexpr (detail::string<T> || detail::container<T>) {
std::size_t ret = 8;
if constexpr (detail::continuous_container<T> &&
detail::is_little_endian_copyable<sizeof(t[0])>) {
ret += t.size() * sizeof(t[0]);
}
else {
for (auto& e : t) ret += write(e);
}
return ret;
}
else {
static_assert(!sizeof(T), "not support type");
}
}
template <typename T>
STRUCT_PACK_INLINE constexpr std::size_t get_write_size(const T* t,
std::size_t length) {
return sizeof(T) * length;
}
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)) {
return struct_pack::errc::no_buffer_space;
}
else {
return {};
}
}
else if constexpr (detail::array<T>) {
if constexpr (std::is_fundamental_v<decltype(t[0])> &&
detail::is_little_endian_copyable<sizeof(t[0])>) {
return read_bytes_array(reader, (char*)&t.data(), sizeof(T));
}
else {
struct_pack::errc ec;
for (auto& e : t) {
ec = read(reader, e);
if SP_UNLIKELY (ec != struct_pack::errc{}) {
return ec;
}
}
return struct_pack::errc{};
}
}
else if constexpr (detail::string<T> || detail::container<T>) {
std::uint64_t sz;
auto ec = read(reader, sz);
if SP_UNLIKELY (ec != struct_pack::errc{}) {
return ec;
}
if constexpr (detail::continuous_container<T> &&
std::is_fundamental_v<decltype(t[0])> &&
detail::is_little_endian_copyable<sizeof(t[0])> &&
checkable_reader_t<Reader>) {
if SP_UNLIKELY (sz > UINT64_MAX / sizeof(t[0]) || sz > SIZE_MAX) {
return struct_pack::errc::invalid_buffer;
}
std::size_t mem_size = sz * sizeof(t[0]);
if SP_UNLIKELY (!reader.check(mem_size)) {
return struct_pack::errc::no_buffer_space;
}
detail::resize(t, mem_size);
return read_bytes_array(reader, (char*)&t.data(), mem_size);
}
else {
for (std::size_t i = 0; i < sz; ++i) {
t.emplace_back();
ec = read(reader, t.back());
if SP_UNLIKELY (ec != struct_pack::errc{}) {
return ec;
}
}
return struct_pack::errc{};
}
}
else {
static_assert(!sizeof(T), "not support type");
}
}
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)) {
return struct_pack::errc::no_buffer_space;
}
else {
return {};
}
}
else {
struct_pack::errc ec{};
for (std::size_t i = 0; i < length; ++i) {
ec = read(reader, t[i]);
if SP_UNLIKELY (ec != struct_pack::errc{}) {
return ec;
}
};
return ec;
}
}
else {
static_assert(!sizeof(T), "not support type");
}
}
}; // namespace struct_pack
7 changes: 6 additions & 1 deletion include/ylt/struct_pack/md5_constexpr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ namespace struct_pack {
template <typename CharType, std::size_t Size>
struct string_literal {
constexpr string_literal() = default;

constexpr string_literal(std::string_view str) : ar{} {
for (size_t i = 0; i < Size; ++i) {
ar[i] = str[i];
}
ar[Size] = '\0';
}
constexpr string_literal(const CharType (&value)[Size + 1]) : ar{} {
for (size_t i = 0; i <= Size; ++i) {
ar[i] = value[i];
Expand Down
4 changes: 4 additions & 0 deletions include/ylt/struct_pack/packer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "calculate_size.hpp"
#include "endian_wrapper.hpp"
#include "reflection.hpp"
#include "ylt/struct_pack/type_id.hpp"
#include "ylt/struct_pack/util.h"
#include "ylt/struct_pack/varint.hpp"
namespace struct_pack::detail {
Expand Down Expand Up @@ -248,6 +249,9 @@ class packer {
else if constexpr (std::is_same_v<type, std::monostate>) {
// do nothing
}
else if constexpr (id == type_id::user_defined_type) {
sp_serialize_to(writer_, item);
}
else if constexpr (detail::varint_t<type, parent_tag>) {
if constexpr (is_enable_fast_varint_coding(parent_tag)) {
// do nothing
Expand Down
Loading

0 comments on commit 10de98d

Please sign in to comment.