diff --git a/docs/Makefile b/docs/Makefile
index 3c95399..cfd84ac 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -6,3 +6,4 @@ all: index.html concepts.html reference.html \
%.html: %.rst
rst2html --stylesheet=lsr.css --link-stylesheet $< $@
+ sed -i 's!!\n!' $@
diff --git a/docs/logo/logo.png b/docs/logo/logo.png
new file mode 100644
index 0000000..0d9534f
Binary files /dev/null and b/docs/logo/logo.png differ
diff --git a/docs/logo/logo.svg b/docs/logo/logo.svg
new file mode 100644
index 0000000..91ab28b
--- /dev/null
+++ b/docs/logo/logo.svg
@@ -0,0 +1,1470 @@
+
+
+
+
diff --git a/docs/logo/logo16px.png b/docs/logo/logo16px.png
new file mode 100644
index 0000000..8db0e2e
Binary files /dev/null and b/docs/logo/logo16px.png differ
diff --git a/docs/logo/logo48px.png b/docs/logo/logo48px.png
new file mode 100644
index 0000000..b598c01
Binary files /dev/null and b/docs/logo/logo48px.png differ
diff --git a/generator/Makefile b/generator/Makefile
new file mode 100644
index 0000000..161ef38
--- /dev/null
+++ b/generator/Makefile
@@ -0,0 +1,2 @@
+nanopb_pb2.py: nanopb.proto
+ protoc --python_out=. -I /usr/include -I . nanopb.proto
diff --git a/pb.h b/pb.h
index 71c76f0..b4d5a38 100644
--- a/pb.h
+++ b/pb.h
@@ -206,4 +206,4 @@ typedef enum {
#define PB_LAST_FIELD {0,0,0,0}
-#endif
\ No newline at end of file
+#endif
diff --git a/pb_decode.c b/pb_decode.c
index 65675d9..a8e97f3 100644
--- a/pb_decode.c
+++ b/pb_decode.c
@@ -561,8 +561,10 @@ bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, v
#ifdef __BIG_ENDIAN__
uint8_t bytes[4] = {0};
bool status = pb_read(stream, bytes, 4);
- uint8_t bebytes[4] = {bytes[3], bytes[2], bytes[1], bytes[0]};
- memcpy(dest, bebytes, 4);
+ if (status) {
+ uint8_t bebytes[4] = {bytes[3], bytes[2], bytes[1], bytes[0]};
+ memcpy(dest, bebytes, 4);
+ }
return status;
#else
return pb_read(stream, (uint8_t*)dest, 4);
@@ -574,9 +576,11 @@ bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, v
#ifdef __BIG_ENDIAN__
uint8_t bytes[8] = {0};
bool status = pb_read(stream, bytes, 8);
- uint8_t bebytes[8] = {bytes[7], bytes[6], bytes[5], bytes[4],
- bytes[3], bytes[2], bytes[1], bytes[0]};
- memcpy(dest, bebytes, 8);
+ if (status) {
+ uint8_t bebytes[8] = {bytes[7], bytes[6], bytes[5], bytes[4],
+ bytes[3], bytes[2], bytes[1], bytes[0]};
+ memcpy(dest, bebytes, 8);
+ }
return status;
#else
return pb_read(stream, (uint8_t*)dest, 8);
diff --git a/pb_encode.c b/pb_encode.c
index 6837f32..291aa30 100644
--- a/pb_encode.c
+++ b/pb_encode.c
@@ -389,6 +389,7 @@ bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field
status = pb_encode(&substream, (const pb_message_t*)field->ptr, src);
stream->bytes_written += substream.bytes_written;
+ stream->state = substream.state;
if (substream.bytes_written != size)
return false;
diff --git a/pb_encode.h b/pb_encode.h
index f0d0861..0cf9713 100644
--- a/pb_encode.h
+++ b/pb_encode.h
@@ -69,4 +69,4 @@ bool pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src
bool pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src);
bool pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src);
-#endif
\ No newline at end of file
+#endif
diff --git a/tests/Makefile b/tests/Makefile
index e66d831..4a47626 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -24,7 +24,9 @@ decode_ptr_unittests.o: decode_unittests.c $(DEPS)
$(CC) $(CFLAGS) -c -o $@ $<
test_decode1: test_decode1.o pb_decode.o person.pb.o
+test_decode2: test_decode2.o pb_decode.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_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
decode_unittests: decode_unittests.o pb_decode.o unittestproto.pb.o
@@ -47,7 +49,7 @@ coverage: run_unittests
gcov pb_decode.gcda
gcov pb_ptr_decode.gcda
-run_unittests: decode_unittests decode_ptr_unittests encode_unittests test_encode1 test_decode1 test_encode_callbacks test_decode_callbacks
+run_unittests: decode_unittests decode_ptr_unittests encode_unittests test_encode1 test_encode2 test_decode1 test_decode2 test_encode_callbacks test_decode_callbacks
rm -f *.gcda
./decode_unittests > /dev/null
@@ -56,9 +58,15 @@ run_unittests: decode_unittests decode_ptr_unittests encode_unittests test_encod
[ "`./test_encode1 | ./test_decode1`" = \
"`./test_encode1 | protoc --decode=Person -I. -I../generator -I/usr/include person.proto`" ]
+
+ [ "`./test_encode2 | ./test_decode1`" = \
+ "`./test_encode2 | protoc --decode=Person -I. -I../generator -I/usr/include person.proto`" ]
+
+ [ "`./test_encode2 | ./test_decode2`" = \
+ "`./test_encode2 | protoc --decode=Person -I. -I../generator -I/usr/include person.proto`" ]
[ "`./test_encode_callbacks | ./test_decode_callbacks`" = \
"`./test_encode_callbacks | protoc --decode=TestMessage callbacks.proto`" ]
-run_fuzztest: test_decode1
- bash -c 'I=1; while cat /dev/urandom | ./test_decode1 > /dev/null; do I=$$(($$I+1)); echo -en "\r$$I"; done'
+run_fuzztest: test_decode2
+ bash -c 'I=1; while true; do cat /dev/urandom | ./test_decode2 > /dev/null; I=$$(($$I+1)); echo -en "\r$$I"; done'
diff --git a/tests/test_decode1.c b/tests/test_decode1.c
index edad6ad..83aae4c 100644
--- a/tests/test_decode1.c
+++ b/tests/test_decode1.c
@@ -23,7 +23,7 @@ bool print_person(pb_istream_t *stream)
/* Now the decoding is done, rest is just to print stuff out. */
printf("name: \"%s\"\n", person.name);
- printf("id: %d\n", person.id);
+ printf("id: %ld\n", (long)person.id);
if (Person_has(person, email))
printf("email: \"%s\"\n", person.email);
@@ -34,19 +34,22 @@ bool print_person(pb_istream_t *stream)
printf("phone {\n");
printf(" number: \"%s\"\n", phone->number);
- switch (phone->type)
+ if (Person_PhoneNumber_has(*phone, type))
{
- case Person_PhoneType_WORK:
- printf(" type: WORK\n");
- break;
-
- case Person_PhoneType_HOME:
- printf(" type: HOME\n");
- break;
-
- case Person_PhoneType_MOBILE:
- printf(" type: MOBILE\n");
- break;
+ switch (phone->type)
+ {
+ case Person_PhoneType_WORK:
+ printf(" type: WORK\n");
+ break;
+
+ case Person_PhoneType_HOME:
+ printf(" type: HOME\n");
+ break;
+
+ case Person_PhoneType_MOBILE:
+ printf(" type: MOBILE\n");
+ break;
+ }
}
printf("}\n");
}
@@ -54,33 +57,16 @@ bool print_person(pb_istream_t *stream)
return true;
}
-/* This binds the pb_istream_t to stdin */
-bool callback(pb_istream_t *stream, uint8_t *buf, size_t count)
-{
- FILE *file = (FILE*)stream->state;
- bool status;
-
- if (buf == NULL)
- {
- /* Skipping data */
- while (count-- && fgetc(file) != EOF);
- return count == 0;
- }
-
- status = (fread(buf, 1, count, file) == count);
-
- if (feof(file))
- stream->bytes_left = 0;
-
- return status;
-}
-
int main()
{
- /* Maximum size is specified to prevent infinite length messages from
- * hanging this in the fuzz test.
- */
- pb_istream_t stream = {&callback, stdin, 10000};
+ /* Read the data into buffer */
+ uint8_t buffer[512];
+ size_t count = fread(buffer, 1, sizeof(buffer), stdin);
+
+ /* Construct a pb_istream_t for reading from the buffer */
+ pb_istream_t stream = pb_istream_from_buffer(buffer, count);
+
+ /* Decode and print out the stuff */
if (!print_person(&stream))
{
printf("Parsing failed.\n");
diff --git a/tests/test_decode2.c b/tests/test_decode2.c
new file mode 100644
index 0000000..b2e2b68
--- /dev/null
+++ b/tests/test_decode2.c
@@ -0,0 +1,90 @@
+/* Same as test_decode1 but reads from stdin directly.
+ */
+
+#include
+#include
+#include "person.pb.h"
+
+/* This function is called once from main(), it handles
+ the decoding and printing.
+ Ugly copy-paste from test_decode1.c. */
+bool print_person(pb_istream_t *stream)
+{
+ int i;
+ Person person;
+
+ if (!pb_decode(stream, Person_msg, &person))
+ return false;
+
+ /* Now the decoding is done, rest is just to print stuff out. */
+
+ printf("name: \"%s\"\n", person.name);
+ printf("id: %ld\n", (long)person.id);
+
+ if (Person_has(person, email))
+ printf("email: \"%s\"\n", person.email);
+
+ for (i = 0; i < person.phone_count; i++)
+ {
+ Person_PhoneNumber *phone = &person.phone[i];
+ printf("phone {\n");
+ printf(" number: \"%s\"\n", phone->number);
+
+ if (Person_PhoneNumber_has(*phone, type))
+ {
+ switch (phone->type)
+ {
+ case Person_PhoneType_WORK:
+ printf(" type: WORK\n");
+ break;
+
+ case Person_PhoneType_HOME:
+ printf(" type: HOME\n");
+ break;
+
+ case Person_PhoneType_MOBILE:
+ printf(" type: MOBILE\n");
+ break;
+ }
+ }
+ printf("}\n");
+ }
+
+ return true;
+}
+
+/* This binds the pb_istream_t to stdin */
+bool callback(pb_istream_t *stream, uint8_t *buf, size_t count)
+{
+ FILE *file = (FILE*)stream->state;
+ bool status;
+
+ if (buf == NULL)
+ {
+ /* Skipping data */
+ while (count-- && fgetc(file) != EOF);
+ return count == 0;
+ }
+
+ status = (fread(buf, 1, count, file) == count);
+
+ if (feof(file))
+ stream->bytes_left = 0;
+
+ return status;
+}
+
+int main()
+{
+ /* Maximum size is specified to prevent infinite length messages from
+ * hanging this in the fuzz test.
+ */
+ pb_istream_t stream = {&callback, stdin, 10000};
+ if (!print_person(&stream))
+ {
+ printf("Parsing failed.\n");
+ return 1;
+ } else {
+ return 0;
+ }
+}
diff --git a/tests/test_decode_callbacks.c b/tests/test_decode_callbacks.c
index 02c3421..b6073b3 100644
--- a/tests/test_decode_callbacks.c
+++ b/tests/test_decode_callbacks.c
@@ -30,7 +30,7 @@ bool print_int32(pb_istream_t *stream, const pb_field_t *field, void *arg)
if (!pb_decode_varint(stream, &value))
return false;
- printf((char*)arg, (int32_t)value);
+ printf((char*)arg, (long)value);
return true;
}
@@ -40,7 +40,7 @@ bool print_fixed32(pb_istream_t *stream, const pb_field_t *field, void *arg)
if (!pb_dec_fixed32(stream, NULL, &value))
return false;
- printf((char*)arg, value);
+ printf((char*)arg, (long)value);
return true;
}
@@ -50,7 +50,7 @@ bool print_fixed64(pb_istream_t *stream, const pb_field_t *field, void *arg)
if (!pb_dec_fixed64(stream, NULL, &value))
return false;
- printf((char*)arg, value);
+ printf((char*)arg, (long long)value);
return true;
}
@@ -69,18 +69,18 @@ int main()
testmessage.submsg.stringvalue.funcs.decode = &print_string;
testmessage.submsg.stringvalue.arg = "submsg {\n stringvalue: \"%s\"\n";
testmessage.submsg.int32value.funcs.decode = &print_int32;
- testmessage.submsg.int32value.arg = " int32value: %d\n";
+ testmessage.submsg.int32value.arg = " int32value: %ld\n";
testmessage.submsg.fixed32value.funcs.decode = &print_fixed32;
- testmessage.submsg.fixed32value.arg = " fixed32value: %d\n";
+ testmessage.submsg.fixed32value.arg = " fixed32value: %ld\n";
testmessage.submsg.fixed64value.funcs.decode = &print_fixed64;
testmessage.submsg.fixed64value.arg = " fixed64value: %lld\n}\n";
testmessage.stringvalue.funcs.decode = &print_string;
testmessage.stringvalue.arg = "stringvalue: \"%s\"\n";
testmessage.int32value.funcs.decode = &print_int32;
- testmessage.int32value.arg = "int32value: %d\n";
+ testmessage.int32value.arg = "int32value: %ld\n";
testmessage.fixed32value.funcs.decode = &print_fixed32;
- testmessage.fixed32value.arg = "fixed32value: %d\n";
+ testmessage.fixed32value.arg = "fixed32value: %ld\n";
testmessage.fixed64value.funcs.decode = &print_fixed64;
testmessage.fixed64value.arg = "fixed64value: %lld\n";
diff --git a/tests/test_encode1.c b/tests/test_encode1.c
index 5c4adf0..039cc6e 100644
--- a/tests/test_encode1.c
+++ b/tests/test_encode1.c
@@ -1,33 +1,36 @@
/* A very simple encoding test case using person.proto.
- * Just puts constant data in the fields and writes the
- * data to stdout.
+ * Just puts constant data in the fields and encodes into
+ * buffer, which is then written to stdout.
*/
#include
#include
#include "person.pb.h"
-/* This binds the pb_ostream_t into the stdout stream */
-bool streamcallback(pb_ostream_t *stream, const uint8_t *buf, size_t count)
-{
- FILE *file = (FILE*) stream->state;
- return fwrite(buf, 1, count, file) == count;
-}
-
int main()
{
/* Initialize the structure with constants */
- Person person = {{0}, "Test Person 99", 99, "test@person.com",
- 1, {{{0}, "555-12345678", Person_PhoneType_MOBILE}}};
- Person_set(person, email);
- Person_PhoneNumber_set(person.phone[0], type);
+ Person person = {{1 << Person_email_index},
+ "Test Person 99", 99, "test@person.com",
+ 3, {{{1 << Person_PhoneNumber_type_index},
+ "555-12345678", Person_PhoneType_MOBILE},
+ {{1 << Person_PhoneNumber_type_index},
+ "99-2342", 0},
+ {{1 << Person_PhoneNumber_type_index},
+ "1234-5678", Person_PhoneType_WORK},
+ }};
- /* Prepare the stream, output goes directly to stdout */
- pb_ostream_t stream = {&streamcallback, stdout, SIZE_MAX, 0};
+ uint8_t buffer[512];
+ pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
/* Now encode it and check if we succeeded. */
if (pb_encode(&stream, Person_msg, &person))
+ {
+ fwrite(buffer, 1, stream.bytes_written, stdout);
return 0; /* Success */
+ }
else
+ {
return 1; /* Failure */
+ }
}
diff --git a/tests/test_encode2.c b/tests/test_encode2.c
new file mode 100644
index 0000000..133bf1c
--- /dev/null
+++ b/tests/test_encode2.c
@@ -0,0 +1,36 @@
+/* Same as test_encode1.c, except writes directly to stdout.
+ */
+
+#include
+#include
+#include "person.pb.h"
+
+/* This binds the pb_ostream_t into the stdout stream */
+bool streamcallback(pb_ostream_t *stream, const uint8_t *buf, size_t count)
+{
+ FILE *file = (FILE*) stream->state;
+ return fwrite(buf, 1, count, file) == count;
+}
+
+int main()
+{
+ /* Initialize the structure with constants */
+ Person person = {{1 << Person_email_index},
+ "Test Person 99", 99, "test@person.com",
+ 3, {{{1 << Person_PhoneNumber_type_index},
+ "555-12345678", Person_PhoneType_MOBILE},
+ {{1 << Person_PhoneNumber_type_index},
+ "99-2342", 0},
+ {{1 << Person_PhoneNumber_type_index},
+ "1234-5678", Person_PhoneType_WORK},
+ }};
+
+ /* Prepare the stream, output goes directly to stdout */
+ pb_ostream_t stream = {&streamcallback, stdout, SIZE_MAX, 0};
+
+ /* Now encode it and check if we succeeded. */
+ if (pb_encode(&stream, Person_msg, &person))
+ return 0; /* Success */
+ else
+ return 1; /* Failure */
+}