Skip to content

Commit

Permalink
Merge pull request #282 from qicosmos/prepare_for_reflection
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored May 24, 2024
2 parents 2e78fe7 + 787c254 commit c1a8563
Show file tree
Hide file tree
Showing 10 changed files with 612 additions and 269 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/linux-gcc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler libprotobuf-dev

- name: configure cmake
run: CXX=g++ CC=gcc cmake -B ${{ github.workspace }}/build -DCMAKE_BUILD_TYPE=${{ matrix.mode }} -DHAS_PROTOBUF=ON -DCMAKE_CXX_STANDARD=${{ matrix.cpp_version }}
run: CXX=g++ CC=gcc cmake -B ${{ github.workspace }}/build -DCMAKE_BUILD_TYPE=${{ matrix.mode }} -DCMAKE_CXX_STANDARD=${{ matrix.cpp_version }}

- name: build project
run: cmake --build ${{ github.workspace }}/build --config ${{ matrix.mode }}
Expand Down
8 changes: 5 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -ldl")
set(IGUANA_DIR ${CMAKE_CURRENT_SOURCE_DIR})

if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD 17)
endif()

if(NOT CMAKE_BUILD_TYPE)
Expand Down Expand Up @@ -106,8 +106,9 @@ add_executable(test_nothrow ${TEST_NOTHROW})
add_executable(test_util ${TEST_UTIL})
add_executable(test_pb ${TEST_PB})

option(HAS_PROTOBUF "import protobuf" OFF)
if(HAS_PROTOBUF)
find_package(Protobuf QUIET)
if(Protobuf_FOUND)
add_definitions(-DSTRUCT_PB_WITH_PROTO)
find_package(Protobuf REQUIRED)
if(Protobuf_FOUND)
message(STATUS "Found Protobuf: ${Protobuf_VERSION}")
Expand All @@ -128,6 +129,7 @@ if(HAS_PROTOBUF)
target_link_libraries(pb_benchmark ${Protobuf_LIBRARIES})
add_executable(test_proto ${PROTO_SRCS} ${TEST_PROTO})
target_link_libraries(test_proto ${Protobuf_LIBRARIES})
add_test(NAME test_proto COMMAND test_proto)
endif()

# unit test
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ qq 交流群 701594518

[中文版](lang/iguana%20使用文档.md)

[struct_pb](lang/struct_pb_intro.md)

### Motivation ###
Serialize an object to any other format data with compile-time reflection, such as json, xml, binary, table and so on.
This library is designed to unify and simplify serialization in a portable cross-platform manner. This library is also easy to extend, and you can serialize any format of data with the library.
Expand Down
57 changes: 21 additions & 36 deletions benchmark/pb_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ class ScopedTimer {

void bench(int Count) {
// init the benchmark data
stpb::BaseTypeMsg base_type_st{{},
std::numeric_limits<int32_t>::max(),
stpb::BaseTypeMsg base_type_st{std::numeric_limits<int32_t>::max(),
std::numeric_limits<int64_t>::max(),
std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint64_t>::max(),
Expand All @@ -41,8 +40,7 @@ void bench(int Count) {
pb::BaseTypeMsg base_type_msg;
SetBaseTypeMsg(base_type_st, base_type_msg);

stpb::IguanaTypeMsg iguana_type_st{{},
{std::numeric_limits<int32_t>::max()},
stpb::IguanaTypeMsg iguana_type_st{{std::numeric_limits<int32_t>::max()},
{std::numeric_limits<int64_t>::max()},
{std::numeric_limits<uint32_t>::max()},
{std::numeric_limits<uint64_t>::max()},
Expand All @@ -52,7 +50,6 @@ void bench(int Count) {
SetIguanaTypeMsg(iguana_type_st, iguana_type_msg);

stpb::RepeatBaseTypeMsg re_base_type_st{
{},
{std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::min()},
{std::numeric_limits<uint64_t>::max(),
Expand All @@ -69,39 +66,31 @@ void bench(int Count) {
SetRepeatBaseTypeMsg(re_base_type_st, re_base_type_msg);

stpb::RepeatIguanaTypeMsg re_iguana_type_st{
{},
{{0}, {1}, {3}},
{{4}, {5}, {6}},
{{7}, {8}, {9}},
{{10}, {11}, {12}},
{{13}, {14}, {15}},
{},
{{0}, {1}, {3}}, {{4}, {5}, {6}}, {{7}, {8}, {9}},
{{10}, {11}, {12}}, {{13}, {14}, {15}}, {},
};
pb::RepeatIguanaTypeMsg re_iguana_type_msg;
SetRepeatIguanaTypeMsg(re_iguana_type_st, re_iguana_type_msg);

stpb::NestedMsg nest_st{
{},
/* base_msg */
{{}, 100, 200, 300, 400, 31.4f, 62.8, false, "World", stpb::Enum::BAZ},
{100, 200, 300, 400, 31.4f, 62.8, false, "World", stpb::Enum::BAZ},
/* repeat_base_msg */
{{{}, 1, 2, 3, 4, 5.5f, 6.6, true, "Hello", stpb::Enum::FOO},
{{}, 7, 8, 9, 10, 11.11f, 12.12, false, "Hi", stpb::Enum::BAR}},
/* iguana_type_msg */ {{}, {100}, {200}, {300}, {400}, {31}, {32}},
{{1, 2, 3, 4, 5.5f, 6.6, true, "Hello", stpb::Enum::FOO},
{7, 8, 9, 10, 11.11f, 12.12, false, "Hi", stpb::Enum::BAR}},
/* iguana_type_msg */ {{100}, {200}, {300}, {400}, {31}, {32}},
/* repeat_iguna_msg */
{{}, {{1}, {2}, {3}}, {{4}, {5}, {6}}, {{7}, {8}, {9}}},
{{{1}, {2}, {3}}, {{4}, {5}, {6}}, {{7}, {8}, {9}}},
/* repeat_repeat_base_msg */
{{{},
{1, 2, 3},
{{{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
{10, 11, 12},
{13.1, 14.2, 15.3},
{16.4, 17.5, 18.6},
{"a", "b", "c"},
{stpb::Enum::FOO, stpb::Enum::BAR, stpb::Enum::BAZ}},
{{},
{19, 20, 21},
{{19, 20, 21},
{22, 23, 24},
{25, 26, 27},
{28, 29, 30},
Expand All @@ -117,13 +106,12 @@ void bench(int Count) {
map_st.sfix64_str_map.emplace(iguana::sfixed64_t{20}, "twenty");

map_st.str_iguana_type_msg_map.emplace(
"first", stpb::IguanaTypeMsg{{}, {10}, {20}, {30}, {40}, {50}, {60}});
"first", stpb::IguanaTypeMsg{{10}, {20}, {30}, {40}, {50}, {60}});
map_st.str_iguana_type_msg_map.emplace(
"second", stpb::IguanaTypeMsg{{}, {11}, {21}, {31}, {41}, {51}, {61}});
"second", stpb::IguanaTypeMsg{{11}, {21}, {31}, {41}, {51}, {61}});

map_st.int_repeat_base_msg_map.emplace(
1, stpb::RepeatBaseTypeMsg{{},
{1, 2},
1, stpb::RepeatBaseTypeMsg{{1, 2},
{3, 4},
{5, 6},
{7, 8},
Expand All @@ -132,8 +120,7 @@ void bench(int Count) {
{"one", "two"},
{stpb::Enum::FOO, stpb::Enum::BAR}});
map_st.int_repeat_base_msg_map.emplace(
2, stpb::RepeatBaseTypeMsg{{},
{2, 3},
2, stpb::RepeatBaseTypeMsg{{2, 3},
{4, 5},
{6, 7},
{8, 9},
Expand All @@ -144,9 +131,9 @@ void bench(int Count) {
pb::MapMsg map_msg{};
SetMapMsg(map_st, map_msg);

stpb::BaseTypeMsg baseTypeMsg{{}, 100, 200, 300, 400,
31.4f, 62.8, false, "World", stpb::Enum::BAZ};
stpb::BaseOneofMsg base_one_of_st{{}, 123, baseTypeMsg, 456.78};
stpb::BaseTypeMsg baseTypeMsg{
100, 200, 300, 400, 31.4f, 62.8, false, "World", stpb::Enum::BAZ};
stpb::BaseOneofMsg base_one_of_st{123, baseTypeMsg, 456.78};
pb::BaseOneofMsg base_one_of_msg;
SetBaseOneofMsg(base_one_of_st, base_one_of_msg);

Expand Down Expand Up @@ -319,12 +306,10 @@ void bench2(int Count) {
std::string pb_str;
pb_simple.SerializeToString(&pb_str);

stpb::simple_t simple{0,
std::numeric_limits<int32_t>::max(),
stpb::simple_t simple{std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max(),
std::numeric_limits<int64_t>::max(),
std::numeric_limits<int64_t>::max(),
temp};
std::numeric_limits<int64_t>::max(), temp};
std::string sp_str;
iguana::to_pb(simple, sp_str);

Expand Down Expand Up @@ -405,7 +390,7 @@ void bench3(int Count) {
}

void bench4(int Count) {
stpb::bench_int32 st_num{0, 10, 20, 31, 42};
stpb::bench_int32 st_num{10, 20, 31, 42};
mygame::bench_int32 pb_num;
pb_num.set_a(10);
pb_num.set_b(20);
Expand Down
3 changes: 0 additions & 3 deletions iguana/pb_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@

namespace iguana {

template <typename T>
IGUANA_INLINE void from_pb(T& t, std::string_view pb_str);

namespace detail {

template <typename T>
Expand Down
75 changes: 69 additions & 6 deletions iguana/pb_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,30 @@ enum class WireType : uint32_t {
Unknown
};

template <typename T, typename Stream>
IGUANA_INLINE void to_pb(T& t, Stream& out);

template <typename T>
IGUANA_INLINE void from_pb(T& t, std::string_view pb_str);

struct pb_base {
size_t cache_size;
virtual void to_pb(std::string& str) {}
virtual void from_pb(std::string_view str) {}

size_t cache_size = 0;
virtual ~pb_base() {}
};

template <typename T>
struct pb_base_impl : public pb_base {
void to_pb(std::string& str) override {
iguana::to_pb(*(static_cast<T*>(this)), str);
}

void from_pb(std::string_view str) override {
iguana::from_pb(*(static_cast<T*>(this)), str);
}
virtual ~pb_base_impl() {}
};

template <typename T>
Expand Down Expand Up @@ -253,13 +275,55 @@ IGUANA_INLINE size_t variant_uint32_size(uint32_t value) {
return static_cast<size_t>((log2value * 9 + 73) / 64);
}

IGUANA_INLINE int Log2FloorNonZero_Portable(uint32_t n) {
if (n == 0)
return -1;
int log = 0;
uint32_t value = n;
for (int i = 4; i >= 0; --i) {
int shift = (1 << i);
uint32_t x = value >> shift;
if (x != 0) {
value = x;
log += shift;
}
}
assert(value == 1);
return log;
}

IGUANA_INLINE uint32_t Log2FloorNonZero(uint32_t n) {
#if defined(__GNUC__)
return 31 ^ static_cast<uint32_t>(__builtin_clz(n));
#elif defined(_MSC_VER)
unsigned long where;
_BitScanReverse(&where, n);
return where;
#else
return Log2FloorNonZero_Portable(n);
#endif
}

IGUANA_INLINE int Log2FloorNonZero64_Portable(uint64_t n) {
const uint32_t topbits = static_cast<uint32_t>(n >> 32);
if (topbits == 0) {
// Top bits are zero, so scan in bottom bits
return static_cast<int>(Log2FloorNonZero(static_cast<uint32_t>(n)));
}
else {
return 32 + static_cast<int>(Log2FloorNonZero(topbits));
}
}

IGUANA_INLINE uint32_t log2_floor_uint64(uint64_t n) {
#if defined(__GNUC__)
return 63 ^ static_cast<uint32_t>(__builtin_clzll(n));
#else
#elif defined(_MSC_VER) && defined(_M_X64)
unsigned long where;
_BitScanReverse64(&where, n);
return where;
#else
return Log2FloorNonZero64_Portable(n);
#endif
}

Expand Down Expand Up @@ -383,11 +447,10 @@ IGUANA_INLINE size_t pb_key_value_size(Type&& t) {
using T = std::remove_const_t<std::remove_reference_t<Type>>;
if constexpr (is_reflection_v<T> || is_custom_reflection_v<T>) {
size_t len = 0;
constexpr auto tuple = get_members_tuple<T>();
static constexpr auto tuple = get_members_tuple<T>();
constexpr size_t SIZE = std::tuple_size_v<std::decay_t<decltype(tuple)>>;
for_each_n(
[&len, &t](auto i) IGUANA__INLINE_LAMBDA {
constexpr auto tuple = get_members_tuple<T>();
using field_type =
std::tuple_element_t<decltype(i)::value,
std::decay_t<decltype(tuple)>>;
Expand All @@ -412,7 +475,7 @@ IGUANA_INLINE size_t pb_key_value_size(Type&& t) {
},
std::make_index_sequence<SIZE>{});
static_assert(inherits_from_pb_base_v<T>,
"must be inherited from iguana::pb_base");
"must be inherited from iguana::pb_base_impl");
t.cache_size = len;

if constexpr (key_size == 0) {
Expand Down Expand Up @@ -493,7 +556,7 @@ IGUANA_INLINE size_t pb_value_size(T&& t) {
using value_type = std::remove_const_t<std::remove_reference_t<T>>;
if constexpr (is_reflection_v<value_type>) {
static_assert(inherits_from_pb_base_v<std::decay_t<T>>,
"must be inherited from iguana::pb_base");
"must be inherited from iguana::pb_base_impl");
return t.cache_size;
}
else if constexpr (is_sequence_container<value_type>::value) {
Expand Down
Loading

0 comments on commit c1a8563

Please sign in to comment.