Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cpp_generator: use std:array for fixed-size arrays #5

Merged
merged 1 commit into from
May 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 25 additions & 18 deletions bragi/cpp_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ def allocator_argument(self):
return ''
def allocator_parameter(self):
return ''
def array(self):
return 'std::array'
def vector(self):
return 'std::vector'
def string(self):
return 'std::string'
def assert_func(self):
return 'assert'
def includes(self):
return ['<stdint.h>', '<stddef.h>', '<vector>', '<cassert>', '<optional>', '<string>']
return ['<stdint.h>', '<stddef.h>', '<array>', '<vector>', '<cassert>', '<optional>', '<string>']

class FriggTraits:
def needs_allocator(self):
Expand All @@ -24,14 +26,16 @@ def allocator_argument(self):
return 'Allocator allocator = Allocator()'
def allocator_parameter(self):
return 'allocator'
def array(self):
return 'std::array'
def vector(self):
return 'frg::vector'
def string(self):
return 'frg::string'
def assert_func(self):
return 'FRG_ASSERT'
def includes(self):
return ['<stdint.h>', '<stddef.h>', '<frg/vector.hpp>', '<frg/macros.hpp>', '<frg/optional.hpp>', '<frg/string.hpp>']
return ['<stdint.h>', '<stddef.h>', '<array>', '<frg/vector.hpp>', '<frg/macros.hpp>', '<frg/optional.hpp>', '<frg/string.hpp>']

flatten = lambda l: [item for sublist in l for item in sublist]

Expand Down Expand Up @@ -186,6 +190,9 @@ def generate_using(self, using):
return out

def check_needs_allocator(self, t):
if t.identity is TypeIdentity.ARRAY and t.n_elements is not None:
return False

return (t.identity in [TypeIdentity.STRING, TypeIdentity.ARRAY, TypeIdentity.STRUCT]
or t.dynamic) and self.stdlib_traits.needs_allocator()

Expand All @@ -201,7 +208,10 @@ def generate_type(self, t):
elif t.identity is TypeIdentity.STRING:
return f'{self.stdlib_traits.string()}{"<Allocator>" if self.stdlib_traits.needs_allocator() else ""}'
elif t.identity is TypeIdentity.ARRAY:
return f'{self.stdlib_traits.vector()}<{self.generate_type(t.subtype)}{", Allocator" if self.stdlib_traits.needs_allocator() else ""}>'
if t.n_elements is None:
return f'{self.stdlib_traits.vector()}<{self.generate_type(t.subtype)}{", Allocator" if self.stdlib_traits.needs_allocator() else ""}>'
else:
return f'{self.stdlib_traits.array()}<{self.generate_type(t.subtype)}, {t.n_elements}>'
elif t.identity is TypeIdentity.STRUCT:
return f'{t.name}{"<Allocator>" if self.stdlib_traits.needs_allocator() else ""}'
else:
Expand Down Expand Up @@ -562,11 +572,6 @@ def emit_decode_fixed_internal(self, expr, expr_type, array_depth):

out = ''

if self.parent.check_needs_allocator(expr_type.subtype):
out = f'{self.parent.indent}{expr}.resize({expr_type.n_elements}, allocator);\n'
else:
out = f'{self.parent.indent}{expr}.resize({expr_type.n_elements});\n'

out += f'{self.parent.indent}for (size_t i{array_depth} = 0; i{array_depth} < {expr_type.n_elements}; i{array_depth}++) {{\n'
self.parent.enter_indent()
out += self.emit_decode_fixed_internal(f'{expr}[i{array_depth}]', expr_type.subtype, array_depth + 1)
Expand Down Expand Up @@ -642,10 +647,11 @@ def emit_decode_dynamic_internal(self, expr, expr_type, array_depth):
if expr_type.identity is TypeIdentity.ARRAY and expr_type.n_elements:
target_size = expr_type.n_elements

if self.parent.check_needs_allocator(expr_type.subtype):
out += f'{self.parent.indent}{expr}.resize({target_size}, allocator);\n'
else:
out += f'{self.parent.indent}{expr}.resize({target_size});\n'
if not (expr_type.identity is TypeIdentity.ARRAY and expr_type.n_elements is not None):
if self.parent.check_needs_allocator(expr_type.subtype):
out += f'{self.parent.indent}{expr}.resize({target_size}, allocator);\n'
else:
out += f'{self.parent.indent}{expr}.resize({target_size});\n'
out += f'{self.parent.indent}for (size_t i{array_depth} = 0; i{array_depth} < {target_size}; i{array_depth}++)\n'
if target_size != 'size':
self.parent.enter_indent()
Expand Down Expand Up @@ -816,12 +822,13 @@ def emit_accessors(self, members):
self.leave_indent()
out += f'{self.indent}}}\n\n'

out += f'{self.indent}void add_{m.name}({self.generate_type(m.type.subtype)} v) {{\n'
self.enter_indent()
out += f'{self.indent}p_{m.name} = true;\n'
out += f'{self.indent}m_{m.name}.push_back(v);\n'
self.leave_indent()
out += f'{self.indent}}}\n\n'
if m.type.n_elements is None:
out += f'{self.indent}void add_{m.name}({self.generate_type(m.type.subtype)} v) {{\n'
self.enter_indent()
out += f'{self.indent}p_{m.name} = true;\n'
out += f'{self.indent}m_{m.name}.push_back(v);\n'
self.leave_indent()
out += f'{self.indent}}}\n\n'

return out

Expand Down
79 changes: 39 additions & 40 deletions tests/arrays/arrays.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <array>
#include <iostream>

#include "../test-util.hpp"
Expand Down Expand Up @@ -30,7 +31,8 @@ void test1() {

void test2() {
auto t1 = test::make_msg<Test2>();
t1.set_arr(test::make_vector<uint8_t>(0xDE, 0xAD, 0xBE, 0xEF));
auto arr = std::array<uint8_t, 5>{0xDE, 0xAD, 0xBE, 0xEF};
t1.set_arr(arr);

assert(bragi::message_id<Test2> == 2);
assert(bragi::head_size<Test2> == 128);
Expand All @@ -42,7 +44,6 @@ void test2() {
auto t2 = test::parse_with<Test2>(head_buf);
assert(t2);

auto arr = test::make_vector<uint8_t>(0xDE, 0xAD, 0xBE, 0xEF, 0);
assert(t2->arr() == arr);
}

Expand Down Expand Up @@ -77,17 +78,17 @@ void test3() {
void test4() {
auto t1 = test::make_msg<Test4>();

t1.set_arr1(test::make_vector<test::vec_of<uint8_t>>(
test::make_vector<uint8_t>(0xDE, 0xAD, 0xBE, 0xEF),
test::make_vector<uint8_t>(0xCA, 0xFE, 0xBA, 0xBE),
test::make_vector<uint8_t>(0xB1, 0x6B, 0x00, 0xB5)
t1.set_arr1(test::make_vector<std::array<uint8_t, 5>>(
std::array<uint8_t, 5>{0xDE, 0xAD, 0xBE, 0xEF},
std::array<uint8_t, 5>{0xCA, 0xFE, 0xBA, 0xBE},
std::array<uint8_t, 5>{0xB1, 0x6B, 0x00, 0xB5}
));

t1.set_arr2(test::make_vector<test::vec_of<uint8_t>>(
t1.set_arr2(std::array<test::vec_of<uint8_t>, 5>{
test::make_vector<uint8_t>(0xDE, 0xAD, 0xBE, 0xEF),
test::make_vector<uint8_t>(0xCA, 0xFE, 0xBA, 0xBE),
test::make_vector<uint8_t>(0xB1, 0x6B, 0x00, 0xB5)
));
});

assert(bragi::message_id<Test4> == 4);
assert(bragi::head_size<Test4> == 128);
Expand All @@ -99,19 +100,17 @@ void test4() {
auto t2 = test::parse_with<Test4>(head_buf);
assert(t2);

auto arr1 = test::make_vector<test::vec_of<uint8_t>>(
test::make_vector<uint8_t>(0xDE, 0xAD, 0xBE, 0xEF, 0),
test::make_vector<uint8_t>(0xCA, 0xFE, 0xBA, 0xBE, 0),
test::make_vector<uint8_t>(0xB1, 0x6B, 0x00, 0xB5, 0)
auto arr1 = test::make_vector<std::array<uint8_t, 5>>(
std::array<uint8_t, 5>{0xDE, 0xAD, 0xBE, 0xEF},
std::array<uint8_t, 5>{0xCA, 0xFE, 0xBA, 0xBE},
std::array<uint8_t, 5>{0xB1, 0x6B, 0x00, 0xB5}
);

auto arr2 = test::make_vector<test::vec_of<uint8_t>>(
auto arr2 = std::array<test::vec_of<uint8_t>, 5>{
test::make_vector<uint8_t>(0xDE, 0xAD, 0xBE, 0xEF),
test::make_vector<uint8_t>(0xCA, 0xFE, 0xBA, 0xBE),
test::make_vector<uint8_t>(0xB1, 0x6B, 0x00, 0xB5),
test::make_vector<uint8_t>(),
test::make_vector<uint8_t>()
);
test::make_vector<uint8_t>(0xB1, 0x6B, 0x00, 0xB5)
};

assert(t2->arr1() == arr1);
assert(t2->arr2() == arr2);
Expand All @@ -120,11 +119,11 @@ void test4() {
void test5_1() {
auto t1 = test::make_msg<Test5>();

t1.set_arr(test::make_vector<test::vec_of<uint8_t>>(
test::make_vector<uint8_t>(0xDE, 0xAD, 0xBE, 0xEF),
test::make_vector<uint8_t>(0xCA, 0xFE, 0xBA, 0xBE),
test::make_vector<uint8_t>(0xB1, 0x6B, 0x00, 0xB5)
));
t1.set_arr(std::array<std::array<uint8_t, 4>, 4>{
std::array<uint8_t, 4>{0xDE, 0xAD, 0xBE, 0xEF},
std::array<uint8_t, 4>{0xCA, 0xFE, 0xBA, 0xBE},
std::array<uint8_t, 4>{0xB1, 0x6B, 0x00, 0xB5}
});

assert(bragi::message_id<Test5> == 5);
assert(bragi::head_size<Test5> == 128);
Expand All @@ -136,25 +135,25 @@ void test5_1() {
auto t2 = test::parse_with<Test5>(head_buf);
assert(t2);

auto arr = test::make_vector<test::vec_of<uint8_t>>(
test::make_vector<uint8_t>(0xDE, 0xAD, 0xBE, 0xEF),
test::make_vector<uint8_t>(0xCA, 0xFE, 0xBA, 0xBE),
test::make_vector<uint8_t>(0xB1, 0x6B, 0x00, 0xB5),
test::make_vector<uint8_t>(0, 0, 0, 0)
);
auto arr = std::array<std::array<uint8_t, 4>, 4>{
std::array<uint8_t, 4>{0xDE, 0xAD, 0xBE, 0xEF},
std::array<uint8_t, 4>{0xCA, 0xFE, 0xBA, 0xBE},
std::array<uint8_t, 4>{0xB1, 0x6B, 0x00, 0xB5},
std::array<uint8_t, 4>{0, 0, 0, 0},
};

assert(t2->arr() == arr);
}

void test5_2() {
auto t1 = test::make_msg<Test5>();

t1.set_arr(test::make_vector<test::vec_of<uint8_t>>(
test::make_vector<uint8_t>(0xDE, 0xAD, 0xBE, 0xEF),
test::make_vector<uint8_t>(0xCA, 0xFE, 0xBA, 0xBE),
test::make_vector<uint8_t>(0xB1, 0x6B, 0x00, 0xB5),
test::make_vector<uint8_t>(0xDE, 0xAD, 0xBE, 0xEF)
));
t1.set_arr(std::array<std::array<uint8_t, 4>, 4>{
std::array<uint8_t, 4>{0xDE, 0xAD, 0xBE, 0xEF},
std::array<uint8_t, 4>{0xCA, 0xFE, 0xBA, 0xBE},
std::array<uint8_t, 4>{0xB1, 0x6B, 0x00, 0xB5},
std::array<uint8_t, 4>{0xDE, 0xAD, 0xBE, 0xEF}
});

assert(bragi::message_id<Test5> == 5);
assert(bragi::head_size<Test5> == 128);
Expand All @@ -166,12 +165,12 @@ void test5_2() {
auto t2 = test::parse_with<Test5>(head_buf);
assert(t2);

auto arr = test::make_vector<test::vec_of<uint8_t>>(
test::make_vector<uint8_t>(0xDE, 0xAD, 0xBE, 0xEF),
test::make_vector<uint8_t>(0xCA, 0xFE, 0xBA, 0xBE),
test::make_vector<uint8_t>(0xB1, 0x6B, 0x00, 0xB5),
test::make_vector<uint8_t>(0xDE, 0xAD, 0xBE, 0xEF)
);
auto arr = std::array<std::array<uint8_t, 4>, 4>{
std::array<uint8_t, 4>{0xDE, 0xAD, 0xBE, 0xEF},
std::array<uint8_t, 4>{0xCA, 0xFE, 0xBA, 0xBE},
std::array<uint8_t, 4>{0xB1, 0x6B, 0x00, 0xB5},
std::array<uint8_t, 4>{0xDE, 0xAD, 0xBE, 0xEF}
};

assert(t2->arr() == arr);
}
Expand Down
4 changes: 2 additions & 2 deletions tests/enums/enums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ int main() {
t1.set_bar(Bar::E);

t1.set_foos(test::make_vector<Foo>(Foo::D, Foo::A, Foo::F, Foo::B));
t1.set_bars(test::make_vector<uint8_t>(Bar::E, Bar::B, Bar::A, Bar::C));
t1.set_bars(std::array<uint8_t, 4>{Bar::E, Bar::B, Bar::A, Bar::C});

assert(bragi::message_id<Test> == 1);
assert(bragi::head_size<Test> == 128);
Expand Down Expand Up @@ -48,6 +48,6 @@ int main() {
auto foos = test::make_vector<Foo>(Foo::D, Foo::A, Foo::F, Foo::B);
assert(t2->foos() == foos);

auto bars = test::make_vector<uint8_t>(Bar::E, Bar::B, Bar::A, Bar::C);
auto bars = std::array<uint8_t, 4>{Bar::E, Bar::B, Bar::A, Bar::C};
assert(t2->bars() == bars);
}
20 changes: 6 additions & 14 deletions tests/test-util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,8 @@ namespace test {

#ifdef TEST_FRIGG

struct test_allocator {
test_allocator(int) {}

void *allocate(size_t sz) { return operator new(sz); }
void free(void *ptr) { operator delete(ptr); }
void deallocate(void *ptr, size_t sz) { operator delete(ptr, sz); }
};

template <typename T>
using vec_of = frg::vector<T, test_allocator>;
using vec_of = frg::vector<T, frg::stl_allocator>;

#else

Expand All @@ -39,7 +31,7 @@ using vec_of = std::vector<T>;
template <typename T, typename ...Ts>
auto make_vector(Ts ...ts) {
#ifdef TEST_FRIGG
frg::vector<T, test_allocator> vec{test_allocator{1}};
frg::vector<T, frg::stl_allocator> vec{frg::stl_allocator{}};

(vec.push_back(static_cast<T>(ts)), ...);

Expand All @@ -51,7 +43,7 @@ auto make_vector(Ts ...ts) {

auto make_string(const char *str) {
#ifdef TEST_FRIGG
return frg::string<test_allocator>{str, test_allocator{1}};
return frg::string<frg::stl_allocator>{str, frg::stl_allocator{}};
#else
return std::string{str};
#endif
Expand All @@ -60,7 +52,7 @@ auto make_string(const char *str) {
#ifdef TEST_FRIGG
template <template<typename...> typename Msg>
auto make_msg() {
return Msg<test_allocator>{test_allocator{1}};
return Msg<frg::stl_allocator>{frg::stl_allocator{}};
}
#else
template <typename Msg>
Expand All @@ -73,9 +65,9 @@ auto make_msg() {
template <template<typename...> typename Msg, typename ...Ts>
auto parse_with(Ts &&...ts) {
if constexpr (sizeof...(ts) == 2)
return bragi::parse_head_tail<Msg>(std::forward<Ts>(ts)..., test_allocator{1});
return bragi::parse_head_tail<Msg>(std::forward<Ts>(ts)..., frg::stl_allocator{});
else
return bragi::parse_head_only<Msg>(std::forward<Ts>(ts)..., test_allocator{1});
return bragi::parse_head_only<Msg>(std::forward<Ts>(ts)..., frg::stl_allocator{});
}
#else
template <typename Msg, typename ...Ts>
Expand Down
Loading