Fix compilation error with fixed size array and FT_POINTER (#630)
Wrong order of conditions in generator caused the fixed size constraint
to be ignored in data type declaration. Fixed and added unit test coverage.
diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py
index fbedb86..5a94746 100755
--- a/generator/nanopb_generator.py
+++ b/generator/nanopb_generator.py
@@ -716,16 +716,20 @@
result += ' pb_callback_t cb_' + var_name + ';\n'
result += ' pb_size_t ' + var_name + '_count;\n'
- if self.pbtype in ['MESSAGE', 'MSG_W_CB']:
- # Use struct definition, so recursive submessages are possible
- result += ' struct %s *%s;' % (Globals.naming_style.struct_name(self.ctype), var_name)
+ if self.rules == 'FIXARRAY' and self.pbtype in ['STRING', 'BYTES']:
+ # Pointer to fixed size array of pointers
+ result += ' %s* (*%s)%s;' % (type_name, var_name, self.array_decl)
elif self.pbtype == 'FIXED_LENGTH_BYTES' or self.rules == 'FIXARRAY':
- # Pointer to fixed size array
+ # Pointer to fixed size array of items
result += ' %s (*%s)%s;' % (type_name, var_name, self.array_decl)
- elif self.rules in ['REPEATED', 'FIXARRAY'] and self.pbtype in ['STRING', 'BYTES']:
+ elif self.rules == 'REPEATED' and self.pbtype in ['STRING', 'BYTES']:
# String/bytes arrays need to be defined as pointers to pointers
result += ' %s **%s;' % (type_name, var_name)
+ elif self.pbtype in ['MESSAGE', 'MSG_W_CB']:
+ # Use struct definition, so recursive submessages are possible
+ result += ' struct %s *%s;' % (Globals.naming_style.struct_name(self.ctype), var_name)
else:
+ # Normal case, just a pointer to single item
result += ' %s *%s;' % (type_name, var_name)
elif self.allocation == 'CALLBACK':
result += ' %s %s;' % (self.callback_datatype, var_name)
@@ -758,6 +762,8 @@
'''Get list of type names used by this field.'''
if self.allocation == 'STATIC':
return [str(self.ctype)]
+ elif self.allocation == 'POINTER' and self.rules == 'FIXARRAY':
+ return [str(self.ctype)]
else:
return []
diff --git a/tests/fixed_count/SConscript b/tests/fixed_count/SConscript
index 3cecb12..31380ad 100644
--- a/tests/fixed_count/SConscript
+++ b/tests/fixed_count/SConscript
@@ -1,14 +1,15 @@
# Test that fixed count option works.
-Import("env")
+Import("malloc_env")
-env.NanopbProto("fixed_count")
-env.Object("fixed_count.pb.c")
+malloc_env.NanopbProto("fixed_count")
+malloc_env.Object("fixed_count.pb.c")
-p = env.Program(["fixed_count_unittests.c",
+p = malloc_env.Program(["fixed_count_unittests.c",
"fixed_count.pb.c",
- "$COMMON/pb_encode.o",
- "$COMMON/pb_decode.o",
- "$COMMON/pb_common.o"])
+ "$COMMON/pb_encode_with_malloc.o",
+ "$COMMON/pb_decode_with_malloc.o",
+ "$COMMON/pb_common_with_malloc.o",
+ "$COMMON/malloc_wrappers.o"])
-env.RunTest(p)
+malloc_env.RunTest(p)
diff --git a/tests/fixed_count/fixed_count.proto b/tests/fixed_count/fixed_count.proto
index e96d1ec..29fadd2 100644
--- a/tests/fixed_count/fixed_count.proto
+++ b/tests/fixed_count/fixed_count.proto
@@ -19,3 +19,12 @@
repeated Message2 data1 = 1 [(nanopb).max_count = 2, (nanopb).fixed_count = true];
repeated Message2 data2 = 2 [(nanopb).max_count = 2, (nanopb).fixed_count = true];
}
+
+message SubMessage {
+ required int32 a = 1;
+}
+
+message Message4 {
+ repeated SubMessage submsgs = 1 [(nanopb).type = FT_POINTER, (nanopb).max_count = 5, (nanopb).fixed_count = true];
+ repeated string strings = 2 [(nanopb).type = FT_POINTER, (nanopb).max_count = 4, (nanopb).fixed_count = true];
+}
diff --git a/tests/fixed_count/fixed_count_unittests.c b/tests/fixed_count/fixed_count_unittests.c
index b039c9b..f1c7c51 100644
--- a/tests/fixed_count/fixed_count_unittests.c
+++ b/tests/fixed_count/fixed_count_unittests.c
@@ -2,6 +2,7 @@
#include <string.h>
#include <pb_decode.h>
#include <pb_encode.h>
+#include <malloc_wrappers.h>
#include "unittests.h"
#include "fixed_count.pb.h"
@@ -134,6 +135,54 @@
TEST(memcmp(&msg_b, &msg_a, sizeof(msg_a)) == 0);
}
+ {
+ pb_byte_t buffer[256];
+ Message4 msg_a = Message4_init_zero;
+ Message4 msg_b = Message4_init_zero;
+
+ pb_ostream_t ostream;
+ pb_istream_t istream;
+ size_t message_length;
+
+ COMMENT("Test encode and decode with pointer type fixarray");
+
+ SubMessage submsgs[pb_arraysize(Message4, submsgs[0])] = {SubMessage_init_zero};
+ submsgs[0].a = 1;
+ submsgs[1].a = 5;
+ submsgs[2].a = 999;
+
+ char a[5] = "a";
+ char b[5] = "b";
+ char abc[5] = "abc";
+ char *strings[pb_arraysize(Message4, strings[0])] = {a, b, abc};
+
+ msg_a.submsgs = &submsgs;
+ msg_a.strings = &strings;
+
+ ostream = pb_ostream_from_buffer(buffer, Message3_size);
+ TEST(pb_encode(&ostream, Message4_fields, &msg_a));
+ message_length = ostream.bytes_written;
+
+ TEST(get_alloc_count() == 0);
+
+ istream = pb_istream_from_buffer(buffer, message_length);
+ TEST(pb_decode(&istream, Message4_fields, &msg_b));
+
+ TEST(istream.bytes_left == 0);
+
+ TEST((*msg_b.submsgs)[0].a == 1);
+ TEST((*msg_b.submsgs)[1].a == 5);
+ TEST((*msg_b.submsgs)[2].a == 999);
+
+ TEST(strcmp((*msg_b.strings)[0], "a") == 0);
+ TEST(strcmp((*msg_b.strings)[1], "b") == 0);
+ TEST(strcmp((*msg_b.strings)[2], "abc") == 0);
+
+ pb_release(Message4_fields, &msg_b);
+
+ TEST(get_alloc_count() == 0);
+ }
+
if (status != 0)
fprintf(stdout, "\n\nSome tests FAILED!\n");