Compare commits

..

10 Commits

Author SHA1 Message Date
Petteri Aimonen
6d74c66ada Publishing nanopb-0.2.7 2014-04-07 20:30:42 +03:00
Petteri Aimonen
c998ffe117 Update changelog 2014-04-07 20:30:12 +03:00
Petteri Aimonen
a8de6acf2d Add rule for building coverage summary using lcov.
Also modified a few tests to be more compatible with coverage information,
so that they use the same pb_encode/decode.c instead of making a copy.
2014-04-05 13:26:37 +03:00
Petteri Aimonen
7880f308ea Fix unused parameter warning when building without errmsg. 2014-04-05 13:25:44 +03:00
Petteri Aimonen
b63e582bdb Add a convenience function pb_get_encoded_size()
There is minimal size penalty from this, and it is probably much more
intuitive to use than PB_OSTREAM_SIZING itself.

This has been suggested before also, but I ended up refusing it back
them. Reconsidering it now, I see that an intuitive API is much better
than any amount of documentation explaining a non-intuitive API.

Update issue 16
Status: FixedInGit
2014-04-05 11:26:39 +03:00
Petteri Aimonen
e5b855fec5 Add a 'found' field to pb_extension_t.
Update issue 112
Status: FixedInGit
2014-04-05 11:11:05 +03:00
Petteri Aimonen
70dee34da6 Add some missing 'static' specifiers
Update issue 91
Status: FixedInGit
2014-04-02 21:08:15 +03:00
Petteri Aimonen
99434724d0 Fix splint warnings, add splint test case 2014-04-02 21:07:30 +03:00
Petteri Aimonen
6c90e824c4 Fix compile error when default value given for extension field.
Update issue 111
Status: FixedInGit
2014-04-01 16:47:53 +03:00
Petteri Aimonen
f4949119ad Add stdlib.h to pb_syshdr.h for dynamic allocation 2014-03-18 16:13:54 +02:00
19 changed files with 187 additions and 57 deletions

View File

@@ -1,3 +1,11 @@
nanopb-0.2.7 (2014-04-07)
Fix bug with default values for extension fields (issue 111)
Fix some MISRA-C warnings (issue 91)
Implemented optional malloc() support (issue 80)
Changed pointer-type bytes field datatype
Add a "found" field to pb_extension_t (issue 112)
Add convenience function pb_get_encoded_size() (issue 16)
nanopb-0.2.6 (2014-02-15) nanopb-0.2.6 (2014-02-15)
Fix generator error with bytes callback fields (issue 99) Fix generator error with bytes callback fields (issue 99)
Fix warnings about large integer constants (issue 102) Fix warnings about large integer constants (issue 102)

View File

@@ -24,10 +24,6 @@ __BIG_ENDIAN__ Set this if your platform stores integers and
floats in big-endian format. Mixed-endian floats in big-endian format. Mixed-endian
systems (different layout for ints and floats) systems (different layout for ints and floats)
are currently not supported. are currently not supported.
NANOPB_INTERNALS Set this to expose the field encoder functions
that are hidden since nanopb-0.1.3. Starting
with nanopb-0.2.4, this flag does nothing. Use
the newer functions that have better interface.
PB_ENABLE_MALLOC Set this to enable dynamic allocation support PB_ENABLE_MALLOC Set this to enable dynamic allocation support
in the decoder. in the decoder.
PB_MAX_REQUIRED_FIELDS Maximum number of required fields to check for PB_MAX_REQUIRED_FIELDS Maximum number of required fields to check for

View File

@@ -53,6 +53,16 @@ typedef int bool;
#endif #endif
/* stdlib.h subset */
#ifdef PB_ENABLE_MALLOC
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#else
void *realloc(void *ptr, size_t size);
void free(void *ptr);
#endif
#endif
/* string.h subset */ /* string.h subset */
#ifdef HAVE_STRING_H #ifdef HAVE_STRING_H
#include <string.h> #include <string.h>

View File

@@ -1,7 +1,7 @@
#!/usr/bin/python #!/usr/bin/python
'''Generate header file for nanopb from a ProtoBuf FileDescriptorSet.''' '''Generate header file for nanopb from a ProtoBuf FileDescriptorSet.'''
nanopb_version = "nanopb-0.2.7-dev" nanopb_version = "nanopb-0.2.7"
import sys import sys
@@ -351,6 +351,8 @@ class Field:
result += '0)' result += '0)'
elif self.pbtype in ['BYTES', 'STRING'] and self.allocation != 'STATIC': elif self.pbtype in ['BYTES', 'STRING'] and self.allocation != 'STATIC':
result += '0)' # Arbitrary size default values not implemented result += '0)' # Arbitrary size default values not implemented
elif self.rules == 'OPTEXT':
result += '0)' # Default value for extensions is not implemented
else: else:
result += '&%s_default)' % (self.struct_name + self.name) result += '&%s_default)' % (self.struct_name + self.name)

12
pb.h
View File

@@ -46,7 +46,7 @@
/* Version of the nanopb library. Just in case you want to check it in /* Version of the nanopb library. Just in case you want to check it in
* your own program. */ * your own program. */
#define NANOPB_VERSION nanopb-0.2.7-dev #define NANOPB_VERSION nanopb-0.2.7
/* Include all the system headers needed by nanopb. You will need the /* Include all the system headers needed by nanopb. You will need the
* definitions of the following: * definitions of the following:
@@ -341,6 +341,10 @@ struct _pb_extension_t {
* If this extension does not match a field, the next handler is * If this extension does not match a field, the next handler is
* automatically called. */ * automatically called. */
pb_extension_t *next; pb_extension_t *next;
/* The decoder sets this to true if the extension was found.
* Ignored for encoding. */
bool found;
}; };
/* Memory allocation functions to use. You can define pb_realloc and /* Memory allocation functions to use. You can define pb_realloc and
@@ -496,7 +500,11 @@ struct _pb_extension_t {
* messages if not used. * messages if not used.
*/ */
#ifdef PB_NO_ERRMSG #ifdef PB_NO_ERRMSG
#define PB_RETURN_ERROR(stream,msg) return false #define PB_RETURN_ERROR(stream,msg) \
do {\
UNUSED(stream); \
return false; \
} while(0)
#define PB_GET_ERROR(stream) "(errmsg disabled)" #define PB_GET_ERROR(stream) "(errmsg disabled)"
#else #else
#define PB_RETURN_ERROR(stream,msg) \ #define PB_RETURN_ERROR(stream,msg) \

View File

@@ -13,7 +13,6 @@
#define checkreturn __attribute__((warn_unused_result)) #define checkreturn __attribute__((warn_unused_result))
#endif #endif
#define NANOPB_INTERNALS
#include "pb.h" #include "pb.h"
#include "pb_decode.h" #include "pb_decode.h"
@@ -130,7 +129,7 @@ bool checkreturn pb_read(pb_istream_t *stream, uint8_t *buf, size_t count)
* This is an optimization for the varint decoding. */ * This is an optimization for the varint decoding. */
static bool checkreturn pb_readbyte(pb_istream_t *stream, uint8_t *buf) static bool checkreturn pb_readbyte(pb_istream_t *stream, uint8_t *buf)
{ {
if (!stream->bytes_left) if (stream->bytes_left == 0)
PB_RETURN_ERROR(stream, "end-of-stream"); PB_RETURN_ERROR(stream, "end-of-stream");
#ifndef PB_BUFFER_ONLY #ifndef PB_BUFFER_ONLY
@@ -174,7 +173,7 @@ static bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest)
if (!pb_readbyte(stream, &byte)) if (!pb_readbyte(stream, &byte))
return false; return false;
if (!(byte & 0x80)) if ((byte & 0x80) == 0)
{ {
/* Quick case, 1 byte value */ /* Quick case, 1 byte value */
result = byte; result = byte;
@@ -397,7 +396,7 @@ static bool checkreturn pb_field_find(pb_field_iterator_t *iter, uint32_t tag)
{ {
return true; return true;
} }
pb_field_next(iter); (void)pb_field_next(iter);
} while (iter->field_index != start); } while (iter->field_index != start);
return false; return false;
@@ -435,7 +434,7 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t
if (!pb_make_string_substream(stream, &substream)) if (!pb_make_string_substream(stream, &substream))
return false; return false;
while (substream.bytes_left && *size < iter->pos->array_size) while (substream.bytes_left > 0 && *size < iter->pos->array_size)
{ {
void *pItem = (uint8_t*)iter->pData + iter->pos->data_size * (*size); void *pItem = (uint8_t*)iter->pData + iter->pos->data_size * (*size);
if (!func(&substream, iter->pos, pItem)) if (!func(&substream, iter->pos, pItem))
@@ -671,7 +670,6 @@ static bool checkreturn default_extension_decoder(pb_istream_t *stream,
{ {
const pb_field_t *field = (const pb_field_t*)extension->type->arg; const pb_field_t *field = (const pb_field_t*)extension->type->arg;
pb_field_iterator_t iter; pb_field_iterator_t iter;
bool dummy;
if (field->tag != tag) if (field->tag != tag)
return true; return true;
@@ -682,7 +680,7 @@ static bool checkreturn default_extension_decoder(pb_istream_t *stream,
iter.required_field_index = 0; iter.required_field_index = 0;
iter.dest_struct = extension->dest; iter.dest_struct = extension->dest;
iter.pData = extension->dest; iter.pData = extension->dest;
iter.pSize = &dummy; iter.pSize = &extension->found;
return decode_field(stream, wire_type, &iter); return decode_field(stream, wire_type, &iter);
} }
@@ -695,7 +693,7 @@ static bool checkreturn decode_extension(pb_istream_t *stream,
pb_extension_t *extension = *(pb_extension_t* const *)iter->pData; pb_extension_t *extension = *(pb_extension_t* const *)iter->pData;
size_t pos = stream->bytes_left; size_t pos = stream->bytes_left;
while (extension && pos == stream->bytes_left) while (extension != NULL && pos == stream->bytes_left)
{ {
bool status; bool status;
if (extension->type->decode) if (extension->type->decode)
@@ -722,7 +720,7 @@ static bool checkreturn find_extension_field(pb_field_iterator_t *iter)
do { do {
if (PB_LTYPE(iter->pos->type) == PB_LTYPE_EXTENSION) if (PB_LTYPE(iter->pos->type) == PB_LTYPE_EXTENSION)
return true; return true;
pb_field_next(iter); (void)pb_field_next(iter);
} while (iter->field_index != start); } while (iter->field_index != start);
return false; return false;
@@ -798,7 +796,7 @@ static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_str
bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
{ {
uint8_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 7) / 8] = {0}; /* Used to check for required fields */ uint8_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 7) / 8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint32_t extension_range_start = 0; uint32_t extension_range_start = 0;
pb_field_iterator_t iter; pb_field_iterator_t iter;
@@ -874,7 +872,7 @@ bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[
} while (pb_field_next(&iter)); } while (pb_field_next(&iter));
/* Fixup if last field was also required. */ /* Fixup if last field was also required. */
if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag) if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag != 0)
req_field_count++; req_field_count++;
/* Check the whole bytes */ /* Check the whole bytes */
@@ -1033,7 +1031,7 @@ bool pb_decode_fixed64(pb_istream_t *stream, void *dest)
#endif #endif
} }
bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest) static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest)
{ {
uint64_t value; uint64_t value;
if (!pb_decode_varint(stream, &value)) if (!pb_decode_varint(stream, &value))
@@ -1051,7 +1049,7 @@ bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, vo
return true; return true;
} }
bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest) static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
{ {
uint64_t value; uint64_t value;
if (!pb_decode_varint(stream, &value)) if (!pb_decode_varint(stream, &value))
@@ -1067,7 +1065,7 @@ bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, v
return true; return true;
} }
bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest) static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
{ {
int64_t value; int64_t value;
if (!pb_decode_svarint(stream, &value)) if (!pb_decode_svarint(stream, &value))
@@ -1083,19 +1081,19 @@ bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, v
return true; return true;
} }
bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest) static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest)
{ {
UNUSED(field); UNUSED(field);
return pb_decode_fixed32(stream, dest); return pb_decode_fixed32(stream, dest);
} }
bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest) static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest)
{ {
UNUSED(field); UNUSED(field);
return pb_decode_fixed64(stream, dest); return pb_decode_fixed64(stream, dest);
} }
bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest)
{ {
uint32_t size; uint32_t size;
pb_bytes_array_t *bdest; pb_bytes_array_t *bdest;
@@ -1124,7 +1122,7 @@ bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, voi
return pb_read(stream, bdest->bytes, size); return pb_read(stream, bdest->bytes, size);
} }
bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest) static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest)
{ {
uint32_t size; uint32_t size;
size_t alloc_size; size_t alloc_size;
@@ -1156,7 +1154,7 @@ bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, vo
return status; return status;
} }
bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest) static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest)
{ {
bool status; bool status;
pb_istream_t substream; pb_istream_t substream;

View File

@@ -3,7 +3,6 @@
* 2011 Petteri Aimonen <jpa@kapsi.fi> * 2011 Petteri Aimonen <jpa@kapsi.fi>
*/ */
#define NANOPB_INTERNALS
#include "pb.h" #include "pb.h"
#include "pb_encode.h" #include "pb_encode.h"
@@ -379,6 +378,17 @@ bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const
return pb_encode_submessage(stream, fields, src_struct); return pb_encode_submessage(stream, fields, src_struct);
} }
bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct)
{
pb_ostream_t stream = PB_OSTREAM_SIZING;
if (!pb_encode(&stream, fields, src_struct))
return false;
*size = stream.bytes_written;
return true;
}
/******************** /********************
* Helper functions * * Helper functions *
********************/ ********************/
@@ -405,9 +415,9 @@ bool checkreturn pb_encode_svarint(pb_ostream_t *stream, int64_t value)
{ {
uint64_t zigzagged; uint64_t zigzagged;
if (value < 0) if (value < 0)
zigzagged = (uint64_t)(~(value << 1)); zigzagged = ~((uint64_t)value << 1);
else else
zigzagged = (uint64_t)(value << 1); zigzagged = (uint64_t)value << 1;
return pb_encode_varint(stream, zigzagged); return pb_encode_varint(stream, zigzagged);
} }
@@ -448,7 +458,7 @@ bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value)
bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number) bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number)
{ {
uint64_t tag = wiretype | (field_number << 3); uint64_t tag = ((uint64_t)field_number << 3) | wiretype;
return pb_encode_varint(stream, tag); return pb_encode_varint(stream, tag);
} }
@@ -544,7 +554,7 @@ bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fie
/* Field encoders */ /* Field encoders */
bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src) static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
{ {
int64_t value = 0; int64_t value = 0;
@@ -562,7 +572,7 @@ bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, co
return pb_encode_varint(stream, (uint64_t)value); return pb_encode_varint(stream, (uint64_t)value);
} }
bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
{ {
uint64_t value = 0; uint64_t value = 0;
@@ -576,7 +586,7 @@ bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, c
return pb_encode_varint(stream, value); return pb_encode_varint(stream, value);
} }
bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
{ {
int64_t value = 0; int64_t value = 0;
@@ -590,19 +600,19 @@ bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, c
return pb_encode_svarint(stream, value); return pb_encode_svarint(stream, value);
} }
bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src) static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src)
{ {
UNUSED(field); UNUSED(field);
return pb_encode_fixed64(stream, src); return pb_encode_fixed64(stream, src);
} }
bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src) static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src)
{ {
UNUSED(field); UNUSED(field);
return pb_encode_fixed32(stream, src); return pb_encode_fixed32(stream, src);
} }
bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src)
{ {
const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)src; const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)src;
@@ -621,7 +631,7 @@ bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, con
return pb_encode_string(stream, bytes->bytes, bytes->size); return pb_encode_string(stream, bytes->bytes, bytes->size);
} }
bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src) static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src)
{ {
/* strnlen() is not always available, so just use a loop */ /* strnlen() is not always available, so just use a loop */
size_t size = 0; size_t size = 0;
@@ -647,7 +657,7 @@ bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, co
return pb_encode_string(stream, (const uint8_t*)src, size); return pb_encode_string(stream, (const uint8_t*)src, size);
} }
bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src) static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src)
{ {
if (field->ptr == NULL) if (field->ptr == NULL)
PB_RETURN_ERROR(stream, "invalid field descriptor"); PB_RETURN_ERROR(stream, "invalid field descriptor");

View File

@@ -71,6 +71,10 @@ bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_
*/ */
bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
/* Encode the message to get the size of the encoded data, but do not store
* the data. */
bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct);
/************************************** /**************************************
* Functions for manipulating streams * * Functions for manipulating streams *
**************************************/ **************************************/

View File

@@ -4,3 +4,18 @@ all:
clean: clean:
scons -c scons -c
coverage:
rm -rf build coverage
# LCOV does not like the newer gcov format
scons CC=gcc-4.6 CXX=gcc-4.6
# We are only interested in pb_encode.o and pb_decode.o
find build -name '*.gcda' -and \! \( -name '*pb_encode*' -or -name '*pb_decode*' \) -exec rm '{}' \;
# Collect the data
mkdir build/coverage
lcov --base-directory . --directory build/ --gcov-tool gcov-4.6 -c -o build/coverage/nanopb.info
# Generate HTML
genhtml -o build/coverage build/coverage/nanopb.info

View File

@@ -50,6 +50,7 @@ if not env.GetOption('clean'):
stdint = conf.CheckCHeader('stdint.h') stdint = conf.CheckCHeader('stdint.h')
stddef = conf.CheckCHeader('stddef.h') stddef = conf.CheckCHeader('stddef.h')
string = conf.CheckCHeader('string.h') string = conf.CheckCHeader('string.h')
stdlib = conf.CheckCHeader('stdlib.h')
if not stdbool or not stdint or not stddef or not string: if not stdbool or not stdint or not stddef or not string:
conf.env.Append(CPPDEFINES = {'PB_SYSTEM_HEADER': '\\"pb_syshdr.h\\"'}) conf.env.Append(CPPDEFINES = {'PB_SYSTEM_HEADER': '\\"pb_syshdr.h\\"'})
conf.env.Append(CPPPATH = "#../extra") conf.env.Append(CPPPATH = "#../extra")
@@ -58,6 +59,7 @@ if not env.GetOption('clean'):
if stdint: conf.env.Append(CPPDEFINES = {'HAVE_STDINT_H': 1}) if stdint: conf.env.Append(CPPDEFINES = {'HAVE_STDINT_H': 1})
if stddef: conf.env.Append(CPPDEFINES = {'HAVE_STDDEF_H': 1}) if stddef: conf.env.Append(CPPDEFINES = {'HAVE_STDDEF_H': 1})
if string: conf.env.Append(CPPDEFINES = {'HAVE_STRING_H': 1}) if string: conf.env.Append(CPPDEFINES = {'HAVE_STRING_H': 1})
if stdlib: conf.env.Append(CPPDEFINES = {'HAVE_STDLIB_H': 1})
# Check if we can use pkg-config to find protobuf include path # Check if we can use pkg-config to find protobuf include path
status, output = conf.TryAction('pkg-config protobuf --variable=includedir > $TARGET') status, output = conf.TryAction('pkg-config protobuf --variable=includedir > $TARGET')
@@ -89,9 +91,9 @@ if 'gcc' in env['CC']:
# GNU Compiler Collection # GNU Compiler Collection
# Debug info, warnings as errors # Debug info, warnings as errors
env.Append(CFLAGS = '-ansi -pedantic -g -O0 -Wall -Werror --coverage -fstack-protector-all') env.Append(CFLAGS = '-ansi -pedantic -g -O0 -Wall -Werror -fprofile-arcs -ftest-coverage -fstack-protector-all')
env.Append(CORECFLAGS = '-Wextra') env.Append(CORECFLAGS = '-Wextra')
env.Append(LINKFLAGS = '--coverage') env.Append(LINKFLAGS = '-g --coverage')
# We currently need uint64_t anyway, even though ANSI C90 otherwise.. # We currently need uint64_t anyway, even though ANSI C90 otherwise..
env.Append(CFLAGS = '-Wno-long-long') env.Append(CFLAGS = '-Wno-long-long')

View File

@@ -4,8 +4,6 @@ Import("env")
# Take copy of the files for custom build. # Take copy of the files for custom build.
c = Copy("$TARGET", "$SOURCE") c = Copy("$TARGET", "$SOURCE")
env.Command("pb_encode.c", "#../pb_encode.c", c)
env.Command("pb_decode.c", "#../pb_decode.c", c)
env.Command("alltypes.pb.h", "$BUILD/alltypes/alltypes.pb.h", c) env.Command("alltypes.pb.h", "$BUILD/alltypes/alltypes.pb.h", c)
env.Command("alltypes.pb.c", "$BUILD/alltypes/alltypes.pb.c", c) env.Command("alltypes.pb.c", "$BUILD/alltypes/alltypes.pb.c", c)
env.Command("encode_alltypes.c", "$BUILD/alltypes/encode_alltypes.c", c) env.Command("encode_alltypes.c", "$BUILD/alltypes/encode_alltypes.c", c)
@@ -15,9 +13,15 @@ env.Command("decode_alltypes.c", "$BUILD/alltypes/decode_alltypes.c", c)
opts = env.Clone() opts = env.Clone()
opts.Append(CPPDEFINES = {'PB_BUFFER_ONLY': 1}) opts.Append(CPPDEFINES = {'PB_BUFFER_ONLY': 1})
# Build new version of core
strict = opts.Clone()
strict.Append(CFLAGS = strict['CORECFLAGS'])
strict.Object("pb_decode_bufonly.o", "$NANOPB/pb_decode.c")
strict.Object("pb_encode_bufonly.o", "$NANOPB/pb_encode.c")
# Now build and run the test normally. # Now build and run the test normally.
enc = opts.Program(["encode_alltypes.c", "alltypes.pb.c", "pb_encode.c"]) enc = opts.Program(["encode_alltypes.c", "alltypes.pb.c", "pb_encode_bufonly.o"])
dec = opts.Program(["decode_alltypes.c", "alltypes.pb.c", "pb_decode.c"]) dec = opts.Program(["decode_alltypes.c", "alltypes.pb.c", "pb_decode_bufonly.o"])
env.RunTest(enc) env.RunTest(enc)
env.RunTest([dec, "encode_alltypes.output"]) env.RunTest([dec, "encode_alltypes.output"])

View File

@@ -281,6 +281,15 @@ int main()
TEST(WRITES(pb_encode_delimited(&s, IntegerContainer_fields, &msg), TEST(WRITES(pb_encode_delimited(&s, IntegerContainer_fields, &msg),
"\x09\x0A\x07\x0A\x05\x01\x02\x03\x04\x05")) "\x09\x0A\x07\x0A\x05\x01\x02\x03\x04\x05"))
} }
{
IntegerContainer msg = {{5, {1,2,3,4,5}}};
size_t size;
COMMENT("Test pb_get_encoded_size.")
TEST(pb_get_encoded_size(&size, IntegerContainer_fields, &msg) &&
size == 9);
}
{ {
uint8_t buffer[10]; uint8_t buffer[10];

View File

@@ -49,7 +49,9 @@ int main(int argc, char **argv)
} }
/* Check that the extensions decoded properly */ /* Check that the extensions decoded properly */
TEST(ext1.found)
TEST(extensionfield1 == 12345) TEST(extensionfield1 == 12345)
TEST(ext2.found)
TEST(strcmp(extensionfield2.test1, "test") == 0) TEST(strcmp(extensionfield2.test1, "test") == 0)
TEST(extensionfield2.test2 == 54321) TEST(extensionfield2.test2 == 54321)

View File

@@ -1,7 +1,7 @@
import 'alltypes.proto'; import 'alltypes.proto';
extend AllTypes { extend AllTypes {
optional int32 AllTypes_extensionfield1 = 255; optional int32 AllTypes_extensionfield1 = 255 [default = 5];
} }
message ExtensionMessage { message ExtensionMessage {

View File

@@ -5,8 +5,6 @@ Import("env")
# Take copy of the files for custom build. # Take copy of the files for custom build.
c = Copy("$TARGET", "$SOURCE") c = Copy("$TARGET", "$SOURCE")
env.Command("pb_encode.c", "#../pb_encode.c", c)
env.Command("pb_decode.c", "#../pb_decode.c", c)
env.Command("encode_alltypes.c", "$BUILD/alltypes/encode_alltypes.c", c) env.Command("encode_alltypes.c", "$BUILD/alltypes/encode_alltypes.c", c)
env.Command("decode_alltypes.c", "$BUILD/alltypes/decode_alltypes.c", c) env.Command("decode_alltypes.c", "$BUILD/alltypes/decode_alltypes.c", c)
@@ -16,9 +14,15 @@ env.NanopbProto(["alltypes", "alltypes.options"])
opts = env.Clone() opts = env.Clone()
opts.Append(CPPDEFINES = {'PB_FIELD_16BIT': 1}) opts.Append(CPPDEFINES = {'PB_FIELD_16BIT': 1})
# Build new version of core
strict = opts.Clone()
strict.Append(CFLAGS = strict['CORECFLAGS'])
strict.Object("pb_decode_fields16.o", "$NANOPB/pb_decode.c")
strict.Object("pb_encode_fields16.o", "$NANOPB/pb_encode.c")
# Now build and run the test normally. # Now build and run the test normally.
enc = opts.Program(["encode_alltypes.c", "alltypes.pb.c", "pb_encode.c"]) enc = opts.Program(["encode_alltypes.c", "alltypes.pb.c", "pb_encode_fields16.o"])
dec = opts.Program(["decode_alltypes.c", "alltypes.pb.c", "pb_decode.c"]) dec = opts.Program(["decode_alltypes.c", "alltypes.pb.c", "pb_decode_fields16.o"])
env.RunTest(enc) env.RunTest(enc)
env.RunTest([dec, "encode_alltypes.output"]) env.RunTest([dec, "encode_alltypes.output"])

View File

@@ -5,8 +5,6 @@ Import("env")
# Take copy of the files for custom build. # Take copy of the files for custom build.
c = Copy("$TARGET", "$SOURCE") c = Copy("$TARGET", "$SOURCE")
env.Command("pb_encode.c", "#../pb_encode.c", c)
env.Command("pb_decode.c", "#../pb_decode.c", c)
env.Command("encode_alltypes.c", "$BUILD/alltypes/encode_alltypes.c", c) env.Command("encode_alltypes.c", "$BUILD/alltypes/encode_alltypes.c", c)
env.Command("decode_alltypes.c", "$BUILD/alltypes/decode_alltypes.c", c) env.Command("decode_alltypes.c", "$BUILD/alltypes/decode_alltypes.c", c)
@@ -16,9 +14,15 @@ env.NanopbProto(["alltypes", "alltypes.options"])
opts = env.Clone() opts = env.Clone()
opts.Append(CPPDEFINES = {'PB_FIELD_32BIT': 1}) opts.Append(CPPDEFINES = {'PB_FIELD_32BIT': 1})
# Build new version of core
strict = opts.Clone()
strict.Append(CFLAGS = strict['CORECFLAGS'])
strict.Object("pb_decode_fields32.o", "$NANOPB/pb_decode.c")
strict.Object("pb_encode_fields32.o", "$NANOPB/pb_encode.c")
# Now build and run the test normally. # Now build and run the test normally.
enc = opts.Program(["encode_alltypes.c", "alltypes.pb.c", "pb_encode.c"]) enc = opts.Program(["encode_alltypes.c", "alltypes.pb.c", "pb_encode_fields32.o"])
dec = opts.Program(["decode_alltypes.c", "alltypes.pb.c", "pb_decode.c"]) dec = opts.Program(["decode_alltypes.c", "alltypes.pb.c", "pb_decode_fields32.o"])
env.RunTest(enc) env.RunTest(enc)
env.RunTest([dec, "encode_alltypes.output"]) env.RunTest([dec, "encode_alltypes.output"])

View File

@@ -4,8 +4,6 @@ Import("env")
# Take copy of the files for custom build. # Take copy of the files for custom build.
c = Copy("$TARGET", "$SOURCE") c = Copy("$TARGET", "$SOURCE")
env.Command("pb_encode.c", "#../pb_encode.c", c)
env.Command("pb_decode.c", "#../pb_decode.c", c)
env.Command("alltypes.pb.h", "$BUILD/alltypes/alltypes.pb.h", c) env.Command("alltypes.pb.h", "$BUILD/alltypes/alltypes.pb.h", c)
env.Command("alltypes.pb.c", "$BUILD/alltypes/alltypes.pb.c", c) env.Command("alltypes.pb.c", "$BUILD/alltypes/alltypes.pb.c", c)
env.Command("encode_alltypes.c", "$BUILD/alltypes/encode_alltypes.c", c) env.Command("encode_alltypes.c", "$BUILD/alltypes/encode_alltypes.c", c)
@@ -15,9 +13,15 @@ env.Command("decode_alltypes.c", "$BUILD/alltypes/decode_alltypes.c", c)
opts = env.Clone() opts = env.Clone()
opts.Append(CPPDEFINES = {'PB_NO_ERRMSG': 1}) opts.Append(CPPDEFINES = {'PB_NO_ERRMSG': 1})
# Build new version of core
strict = opts.Clone()
strict.Append(CFLAGS = strict['CORECFLAGS'])
strict.Object("pb_decode_noerr.o", "$NANOPB/pb_decode.c")
strict.Object("pb_encode_noerr.o", "$NANOPB/pb_encode.c")
# Now build and run the test normally. # Now build and run the test normally.
enc = opts.Program(["encode_alltypes.c", "alltypes.pb.c", "pb_encode.c"]) enc = opts.Program(["encode_alltypes.c", "alltypes.pb.c", "pb_encode_noerr.o"])
dec = opts.Program(["decode_alltypes.c", "alltypes.pb.c", "pb_decode.c"]) dec = opts.Program(["decode_alltypes.c", "alltypes.pb.c", "pb_decode_noerr.o"])
env.RunTest(enc) env.RunTest(enc)
env.RunTest([dec, "encode_alltypes.output"]) env.RunTest([dec, "encode_alltypes.output"])

13
tests/splint/SConscript Normal file
View File

@@ -0,0 +1,13 @@
# Check the nanopb core using splint
Import('env')
p = env.WhereIs('splint')
if p:
env.Command('pb_decode.splint', '$NANOPB/pb_decode.c',
'splint -f splint/splint.rc $SOURCE 2> $TARGET')
env.Command('pb_encode.splint', '$NANOPB/pb_encode.c',
'splint -f splint/splint.rc $SOURCE 2> $TARGET')

37
tests/splint/splint.rc Normal file
View File

@@ -0,0 +1,37 @@
+checks
+partial
+matchanyintegral
+strictlib
-isoreserved # to be fixed in 0.3
-nullassign
-predboolint
-predboolptr
+ptrnegate
-switchloopbreak
+ignoresigns
-infloopsuncon
-type
# splint's memory checks don't quite work without annotations
-mustfreeonly
-compmempass
-nullret
-observertrans
-statictrans
-compdestroy
-nullpass
-nullstate
-compdef
-usereleased
-temptrans
-dependenttrans
-kepttrans
-branchstate
-immediatetrans
# These tests give false positives, compiler typically has
# better warnings for these.
-noret
-noeffect
-usedef