Compare commits

...

11 Commits

Author SHA1 Message Date
Petteri Aimonen
09ec60cadf Publishing nanopb-0.1.8 2012-12-13 21:29:57 +02:00
Petteri Aimonen
871e5be9dd Fix small error in field callback documentation.
Update issue 44
Status: FixedInGit
2012-12-06 11:13:53 +02:00
Jens Steinhauser
068de05c51 Complete initialization of pb_istream_t.
Because PB_RETURN_ERROR checks if the 'errmsg' member is NULL before
assigning to it, error messages would get lost.
2012-11-27 19:55:21 +02:00
Steffen Siering
1f8fb1f1ed Use TESTS variable to define dependencies for run_unittests 2012-11-16 09:59:04 +02:00
Petteri Aimonen
434dcbb2ee Select compilation options based on $(CC) in tests/Makefile.
Makes 'make CC=clang' work.

Based on patch submitted by Steffen Siering.

Update issue 40:
Status: FixedInGit
2012-11-16 09:51:23 +02:00
Petteri Aimonen
59788e2aab Rename test_compiles.c to test_multiple_files.c 2012-11-16 09:33:11 +02:00
Steffen Siering
cc29958d34 Fix STATIC_ASSERT macro when using multiple .proto files.
The __COUNTER__ macro (used for generating unique names) is at least supported
by gcc, clang and Visual Studio. With this change test_compiles.c is
compilable, since no more typedefs are redefined.

Compilers/Preprocessors not supporting __COUNTER__ error's are still possible
which are hopfully handled by the usage of __LINE__ in most sittuations.

Added unit test for the problem.
2012-11-16 09:24:39 +02:00
Petteri Aimonen
0abb764b18 Fix naming of nested Enums with short names 2012-11-14 00:43:51 +02:00
Petteri Aimonen
02ecee2de8 Fix naming of enums when long_names=false.
Modify test case to check that options.pb.o compiles.

Update issue 42
Status: FixedInGit

Update issue 43
Status: FixedInGit
2012-11-14 00:36:16 +02:00
Petteri Aimonen
332a9ee95c Fix changelog 2012-11-11 11:20:34 +02:00
Petteri Aimonen
fc6f56b2bd Setting version to 0.1.8-dev 2012-11-11 11:19:17 +02:00
10 changed files with 112 additions and 23 deletions

View File

@@ -1,4 +1,10 @@
nanopb-0.1.7 (not yet released) nanopb-0.1.8
Fix bugs in the enum short names introduced in 0.1.7 (issues 42, 43)
Fix STATIC_ASSERT macro when using multiple .proto files. (issue 41)
Fix missing initialization of istream.errmsg
Make tests/Makefile work for non-gcc compilers (issue 40)
nanopb-0.1.7
Remove "skip" mode from pb_istream_t callbacks. Example implementation had a bug. (issue 37) Remove "skip" mode from pb_istream_t callbacks. Example implementation had a bug. (issue 37)
Add option to use shorter names for enum values (issue 38) Add option to use shorter names for enum values (issue 38)
Improve options support in generator (issues 12, 30) Improve options support in generator (issues 12, 30)

View File

@@ -381,7 +381,7 @@ Remove the data for a field from the stream, without actually decoding it::
For decoding numeric (including enumerated and boolean) values, use `pb_decode_varint`_, `pb_decode_svarint`_, `pb_decode_fixed32`_ and `pb_decode_fixed64`_. They take a pointer to a 32- or 64-bit C variable, which you may then cast to smaller datatype for storage. For decoding numeric (including enumerated and boolean) values, use `pb_decode_varint`_, `pb_decode_svarint`_, `pb_decode_fixed32`_ and `pb_decode_fixed64`_. They take a pointer to a 32- or 64-bit C variable, which you may then cast to smaller datatype for storage.
For decoding strings and bytes fields, the length has already been decoded. You can therefore check the total length in *stream->state* and read the data using `pb_read`_. For decoding strings and bytes fields, the length has already been decoded. You can therefore check the total length in *stream->bytes_left* and read the data using `pb_read`_.
Finally, for decoding submessages in a callback, simply use `pb_decode`_ and pass it the *SubMessage_fields* descriptor array. Finally, for decoding submessages in a callback, simply use `pb_decode`_ and pass it the *SubMessage_fields* descriptor array.

View File

@@ -1,5 +1,5 @@
'''Generate header file for nanopb from a ProtoBuf FileDescriptorSet.''' '''Generate header file for nanopb from a ProtoBuf FileDescriptorSet.'''
nanopb_version = "nanopb-0.1.7" nanopb_version = "nanopb-0.1.8"
try: try:
import google.protobuf.descriptor_pb2 as descriptor import google.protobuf.descriptor_pb2 as descriptor
@@ -73,6 +73,9 @@ class Names:
else: else:
raise ValueError("Name parts should be of type str") raise ValueError("Name parts should be of type str")
def __eq__(self, other):
return isinstance(other, Names) and self.parts == other.parts
def names_from_type_name(type_name): def names_from_type_name(type_name):
'''Parse Names() from FieldDescriptorProto type_name''' '''Parse Names() from FieldDescriptorProto type_name'''
if type_name[0] != '.': if type_name[0] != '.':
@@ -83,12 +86,15 @@ class Enum:
def __init__(self, names, desc, enum_options): def __init__(self, names, desc, enum_options):
'''desc is EnumDescriptorProto''' '''desc is EnumDescriptorProto'''
if enum_options.long_names: self.options = enum_options
self.names = names + desc.name self.names = names + desc.name
else:
self.names = names
self.values = [(self.names + x.name, x.number) for x in desc.value] if enum_options.long_names:
self.values = [(self.names + x.name, x.number) for x in desc.value]
else:
self.values = [(names + x.name, x.number) for x in desc.value]
self.value_longnames = [self.names + x.name for x in desc.value]
def __str__(self): def __str__(self):
result = 'typedef enum _%s {\n' % self.names result = 'typedef enum _%s {\n' % self.names
@@ -389,7 +395,17 @@ def parse_file(fdesc, file_options):
message_options = get_nanopb_suboptions(message, file_options) message_options = get_nanopb_suboptions(message, file_options)
messages.append(Message(names, message, message_options)) messages.append(Message(names, message, message_options))
for enum in message.enum_type: for enum in message.enum_type:
enums.append(Enum(names, enum, message_options)) enum_options = get_nanopb_suboptions(enum, message_options)
enums.append(Enum(names, enum, enum_options))
# Fix field default values where enum short names are used.
for enum in enums:
if not enum.options.long_names:
for message in messages:
for field in message.fields:
if field.default in enum.value_longnames:
idx = enum.value_longnames.index(field.default)
field.default = enum.values[idx][0]
return enums, messages return enums, messages
@@ -477,7 +493,9 @@ def generate_header(dependencies, headername, enums, messages):
worst = 0 worst = 0
worst_field = '' worst_field = ''
checks = [] checks = []
checks_msgnames = []
for msg in messages: for msg in messages:
checks_msgnames.append(msg.name)
for field in msg.fields: for field in msg.fields:
status = field.largest_field_value() status = field.largest_field_value()
if isinstance(status, (str, unicode)): if isinstance(status, (str, unicode)):
@@ -495,7 +513,8 @@ def generate_header(dependencies, headername, enums, messages):
yield '#error Field descriptor for %s is too large. Define PB_FIELD_16BIT to fix this.\n' % worst_field yield '#error Field descriptor for %s is too large. Define PB_FIELD_16BIT to fix this.\n' % worst_field
else: else:
assertion = ' && '.join(str(c) + ' < 256' for c in checks) assertion = ' && '.join(str(c) + ' < 256' for c in checks)
yield 'STATIC_ASSERT((%s), YOU_MUST_DEFINE_PB_FIELD_16BIT)\n' % assertion msgs = '_'.join(str(n) for n in checks_msgnames)
yield 'STATIC_ASSERT((%s), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_%s)\n'%(assertion,msgs)
yield '#endif\n\n' yield '#endif\n\n'
if worst > 65535 or checks: if worst > 65535 or checks:
@@ -504,7 +523,8 @@ def generate_header(dependencies, headername, enums, messages):
yield '#error Field descriptor for %s is too large. Define PB_FIELD_32BIT to fix this.\n' % worst_field yield '#error Field descriptor for %s is too large. Define PB_FIELD_32BIT to fix this.\n' % worst_field
else: else:
assertion = ' && '.join(str(c) + ' < 65536' for c in checks) assertion = ' && '.join(str(c) + ' < 65536' for c in checks)
yield 'STATIC_ASSERT((%s), YOU_MUST_DEFINE_PB_FIELD_32BIT)\n' % assertion msgs = '_'.join(str(n) for n in checks_msgnames)
yield 'STATIC_ASSERT((%s), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_%s)\n'%(assertion,msgs)
yield '#endif\n' yield '#endif\n'
yield '\n#ifdef __cplusplus\n' yield '\n#ifdef __cplusplus\n'

10
pb.h
View File

@@ -6,7 +6,7 @@
* see pb_encode.h or pb_decode.h * see pb_encode.h or pb_decode.h
*/ */
#define NANOPB_VERSION nanopb-0.1.7 #define NANOPB_VERSION nanopb-0.1.8
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
@@ -24,9 +24,13 @@
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
#endif #endif
/* Compile-time assertion, used for checking compatible compilation options. */ /* Compile-time assertion, used for checking compatible compilation options.
* If this fails on your compiler for some reason, use #define STATIC_ASSERT
* to disable it. */
#ifndef STATIC_ASSERT #ifndef STATIC_ASSERT
#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1]; #define STATIC_ASSERT(COND,MSG) typedef char STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1];
#define STATIC_ASSERT_MSG(MSG, LINE, COUNTER) STATIC_ASSERT_MSG_(MSG, LINE, COUNTER)
#define STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) static_assertion_##MSG##LINE##COUNTER
#endif #endif
/* Number of required fields to keep track of /* Number of required fields to keep track of

View File

@@ -80,6 +80,9 @@ pb_istream_t pb_istream_from_buffer(uint8_t *buf, size_t bufsize)
stream.callback = &buf_read; stream.callback = &buf_read;
stream.state = buf; stream.state = buf;
stream.bytes_left = bufsize; stream.bytes_left = bufsize;
#ifndef PB_NO_ERRMSG
stream.errmsg = NULL;
#endif
return stream; return stream;
} }

View File

@@ -1,15 +1,30 @@
CFLAGS=-ansi -Wall -Werror -I .. -g -O0 --coverage CFLAGS=-ansi -Wall -Werror -I .. -g -O0
LDFLAGS=--coverage DEPS=../pb_decode.h ../pb_encode.h ../pb.h person.pb.h \
DEPS=../pb_decode.h ../pb_encode.h ../pb.h person.pb.h callbacks.pb.h unittests.h unittestproto.pb.h alltypes.pb.h missing_fields.pb.h callbacks2.pb.h callbacks.pb.h unittests.h unittestproto.pb.h \
TESTS=test_decode1 test_encode1 decode_unittests encode_unittests test_no_messages alltypes.pb.h missing_fields.pb.h
TESTS= decode_unittests encode_unittests \
test_decode1 test_decode2 test_decode3 \
test_encode1 test_encode2 test_encode3 \
test_decode_callbacks test_encode_callbacks \
test_missing_fields test_no_messages \
test_multiple_files test_cxxcompile test_options
# More strict checks for the core part of nanopb # More strict checks for the core part of nanopb
CFLAGS_CORE=-pedantic -Wextra -Wcast-qual -Wlogical-op -Wconversion CC_VERSION=$(shell $(CC) -v 2>&1)
CFLAGS_CORE=
ifneq (,$(findstring gcc,$(CC_VERSION)))
CFLAGS_CORE=-pedantic -Wextra -Wcast-qual -Wlogical-op -Wconversion
CFLAGS+=--coverage
LDFLAGS+=--coverage
endif
ifneq (,$(findstring clang,$(CC_VERSION)))
CFLAGS_CORE=-pedantic -Wextra -Wcast-qual -Wconversion
endif
all: breakpoints $(TESTS) run_unittests all: breakpoints $(TESTS) run_unittests
clean: clean:
rm -f $(TESTS) person.pb* alltypes.pb* *.o *.gcda *.gcno rm -f $(TESTS) person.pb* alltypes.pb* *.o *.gcda *.gcno *.pb.h *.pb.c
%.pb.o: %.pb.c %.pb.h %.pb.o: %.pb.c %.pb.h
$(CC) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $< $(CC) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $<
@@ -35,6 +50,7 @@ test_decode3: test_decode3.o pb_decode.o alltypes.pb.o
test_encode1: test_encode1.o pb_encode.o person.pb.o test_encode1: test_encode1.o pb_encode.o person.pb.o
test_encode2: test_encode2.o pb_encode.o person.pb.o test_encode2: test_encode2.o pb_encode.o person.pb.o
test_encode3: test_encode3.o pb_encode.o alltypes.pb.o test_encode3: test_encode3.o pb_encode.o alltypes.pb.o
test_multiple_files: test_multiple_files.o pb_encode.o callbacks2.pb.o callbacks.pb.o
test_decode_callbacks: test_decode_callbacks.o pb_decode.o callbacks.pb.o test_decode_callbacks: test_decode_callbacks.o pb_decode.o callbacks.pb.o
test_encode_callbacks: test_encode_callbacks.o pb_encode.o callbacks.pb.o test_encode_callbacks: test_encode_callbacks.o pb_encode.o callbacks.pb.o
test_missing_fields: test_missing_fields.o pb_encode.o pb_decode.o missing_fields.pb.o test_missing_fields: test_missing_fields.o pb_encode.o pb_decode.o missing_fields.pb.o
@@ -55,7 +71,7 @@ coverage: run_unittests
gcov pb_encode.gcda gcov pb_encode.gcda
gcov pb_decode.gcda gcov pb_decode.gcda
run_unittests: decode_unittests encode_unittests test_cxxcompile test_encode1 test_encode2 test_encode3 test_decode1 test_decode2 test_decode3 test_encode_callbacks test_decode_callbacks test_missing_fields test_options run_unittests: $(TESTS)
rm -f *.gcda rm -f *.gcda
./decode_unittests > /dev/null ./decode_unittests > /dev/null
@@ -82,7 +98,7 @@ run_unittests: decode_unittests encode_unittests test_cxxcompile test_encode1 te
./test_missing_fields ./test_missing_fields
test_options: options.pb.h options.expected test_options: options.pb.h options.expected options.pb.o
cat options.expected | while read -r p; do \ cat options.expected | while read -r p; do \
if ! grep -q "$$p" $<; then \ if ! grep -q "$$p" $<; then \
echo Expected: "$$p"; \ echo Expected: "$$p"; \

9
tests/callbacks2.proto Normal file
View File

@@ -0,0 +1,9 @@
// Test if including generated header file for this file + implicit include of
// callbacks.pb.h still compiles. Used with test_compiles.c.
import "callbacks.proto";
message Callback2Message {
required TestMessage tstmsg = 1;
required SubMessage submsg = 2;
}

View File

@@ -2,4 +2,5 @@ char filesize\[20\];
char msgsize\[30\]; char msgsize\[30\];
char fieldsize\[40\]; char fieldsize\[40\];
pb_callback_t int32_callback; pb_callback_t int32_callback;
[^_]EnumValue1 = 1 \sEnumValue1 = 1
Message5_EnumValue1

View File

@@ -36,4 +36,21 @@ enum Enum1
{ {
option (nanopb_enumopt).long_names = false; option (nanopb_enumopt).long_names = false;
EnumValue1 = 1; EnumValue1 = 1;
EnumValue2 = 2;
}
message EnumTest
{
required Enum1 field = 1 [default = EnumValue2];
}
// Short enum names inside message
message Message5
{
enum Enum2
{
option (nanopb_enumopt).long_names = false;
EnumValue1 = 1;
}
required Enum2 field = 1 [default = EnumValue1];
} }

View File

@@ -0,0 +1,13 @@
/*
* Tests if still compile if typedefs are redfefined in STATIC_ASSERTS when
* proto file includes another poto file
*/
#include <stdio.h>
#include <pb_encode.h>
#include "callbacks2.pb.h"
int main()
{
return 0;
}