aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetteri Aimonen <jpa@git.mail.kapsi.fi>2013-02-06 20:54:25 +0200
committerPetteri Aimonen <jpa@git.mail.kapsi.fi>2013-02-06 20:54:25 +0200
commit4ba6a3027d7a5d8c17abeb031622389f8be234fe (patch)
tree3c2fdba47e9b9c11a0e3b0996c9f733abb4c07c1
parent39b8a5e2bbd5da85f23b48280e81a5ce6672b09d (diff)
Add compile-time option PB_BUFFER_ONLY.
This allows slight optimizations if only memory buffer support (as opposed to stream callbacks) is wanted. On ARM difference is -12% execution time, -4% code size when enabled.
-rw-r--r--docs/reference.rst2
-rw-r--r--pb_decode.c11
-rw-r--r--pb_decode.h9
-rw-r--r--pb_encode.c11
-rw-r--r--pb_encode.h10
-rw-r--r--tests/Makefile20
6 files changed, 60 insertions, 3 deletions
diff --git a/docs/reference.rst b/docs/reference.rst
index 2b10c2ee..fee1b702 100644
--- a/docs/reference.rst
+++ b/docs/reference.rst
@@ -22,6 +22,8 @@ PB_FIELD_32BIT Add support for tag numbers > 65535 and fields la
Increases code size 9 bytes per each field. Compiler error will tell if you need this.
PB_NO_ERRMSG Disables the support for error messages; only error information is the true/false return value.
Decreases the code size by a few hundred bytes.
+PB_BUFFER_ONLY Disables the support for custom streams. Only supports encoding to memory buffers.
+ Speeds up execution and decreases code size slightly.
============================ ================================================================================================
The PB_MAX_REQUIRED_FIELDS, PB_FIELD_16BIT and PB_FIELD_32BIT settings allow raising some datatype limits to suit larger messages.
diff --git a/pb_decode.c b/pb_decode.c
index 9faceca2..b664fe14 100644
--- a/pb_decode.c
+++ b/pb_decode.c
@@ -52,6 +52,7 @@ static bool checkreturn buf_read(pb_istream_t *stream, uint8_t *buf, size_t coun
bool checkreturn pb_read(pb_istream_t *stream, uint8_t *buf, size_t count)
{
+#ifndef PB_BUFFER_ONLY
if (buf == NULL && stream->callback != buf_read)
{
/* Skip input bytes */
@@ -66,12 +67,18 @@ bool checkreturn pb_read(pb_istream_t *stream, uint8_t *buf, size_t count)
return pb_read(stream, tmp, count);
}
+#endif
if (stream->bytes_left < count)
PB_RETURN_ERROR(stream, "end-of-stream");
+#ifndef PB_BUFFER_ONLY
if (!stream->callback(stream, buf, count))
PB_RETURN_ERROR(stream, "io error");
+#else
+ if (!buf_read(stream, buf, count))
+ return false;
+#endif
stream->bytes_left -= count;
return true;
@@ -80,7 +87,11 @@ bool checkreturn pb_read(pb_istream_t *stream, uint8_t *buf, size_t count)
pb_istream_t pb_istream_from_buffer(uint8_t *buf, size_t bufsize)
{
pb_istream_t stream;
+#ifdef PB_BUFFER_ONLY
+ stream.callback = NULL;
+#else
stream.callback = &buf_read;
+#endif
stream.state = buf;
stream.bytes_left = bufsize;
#ifndef PB_NO_ERRMSG
diff --git a/pb_decode.h b/pb_decode.h
index e9f8ced8..35de0a22 100644
--- a/pb_decode.h
+++ b/pb_decode.h
@@ -32,7 +32,16 @@ extern "C" {
*/
struct _pb_istream_t
{
+#ifdef PB_BUFFER_ONLY
+ /* Callback pointer is not used in buffer-only configuration.
+ * Having an int pointer here allows binary compatibility but
+ * gives an error if someone tries to assign callback function.
+ */
+ int *callback;
+#else
bool (*callback)(pb_istream_t *stream, uint8_t *buf, size_t count);
+#endif
+
void *state; /* Free field for use by callback implementation */
size_t bytes_left;
diff --git a/pb_encode.c b/pb_encode.c
index 95223cb6..bba5dc19 100644
--- a/pb_encode.c
+++ b/pb_encode.c
@@ -48,7 +48,11 @@ static bool checkreturn buf_write(pb_ostream_t *stream, const uint8_t *buf, size
pb_ostream_t pb_ostream_from_buffer(uint8_t *buf, size_t bufsize)
{
pb_ostream_t stream;
+#ifdef PB_BUFFER_ONLY
+ stream.callback = (void*)1; /* Just some marker value */
+#else
stream.callback = &buf_write;
+#endif
stream.state = buf;
stream.max_size = bufsize;
stream.bytes_written = 0;
@@ -61,9 +65,14 @@ bool checkreturn pb_write(pb_ostream_t *stream, const uint8_t *buf, size_t count
{
if (stream->bytes_written + count > stream->max_size)
return false;
-
+
+#ifdef PB_BUFFER_ONLY
+ if (!buf_write(stream, buf, count))
+ return false;
+#else
if (!stream->callback(stream, buf, count))
return false;
+#endif
}
stream->bytes_written += count;
diff --git a/pb_encode.h b/pb_encode.h
index 85a82973..69b88e86 100644
--- a/pb_encode.h
+++ b/pb_encode.h
@@ -32,7 +32,17 @@ extern "C" {
*/
struct _pb_ostream_t
{
+#ifdef PB_BUFFER_ONLY
+ /* Callback pointer is not used in buffer-only configuration.
+ * Having an int pointer here allows binary compatibility but
+ * gives an error if someone tries to assign callback function.
+ * Also, NULL pointer marks a 'sizing stream' that does not
+ * write anything.
+ */
+ int *callback;
+#else
bool (*callback)(pb_ostream_t *stream, const uint8_t *buf, size_t count);
+#endif
void *state; /* Free field for use by callback implementation */
size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */
size_t bytes_written;
diff --git a/tests/Makefile b/tests/Makefile
index 63830999..38f10eae 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -3,8 +3,8 @@ DEPS=../pb_decode.h ../pb_encode.h ../pb.h person.pb.h \
callbacks2.pb.h callbacks.pb.h unittests.h unittestproto.pb.h \
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_decode1 test_decode2 test_decode3 test_decode3_buf \
+ test_encode1 test_encode2 test_encode3 test_encode3_buf \
test_decode_callbacks test_encode_callbacks \
test_missing_fields test_no_messages \
test_multiple_files test_cxxcompile test_options \
@@ -39,11 +39,26 @@ pb_encode.o: ../pb_encode.c $(DEPS)
pb_decode.o: ../pb_decode.c $(DEPS)
$(CC) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $<
+# Test for compilability with c++ compiler
+
pb_encode.cxx.o: ../pb_encode.c $(DEPS)
$(CXX) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $<
pb_decode.cxx.o: ../pb_decode.c $(DEPS)
$(CXX) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $<
+# Test for PB_BUF_ONLY compilation option
+
+pb_encode.buf.o: ../pb_encode.c $(DEPS)
+ $(CC) -DPB_BUFFER_ONLY $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $<
+pb_decode.buf.o: ../pb_decode.c $(DEPS)
+ $(CC) -DPB_BUFFER_ONLY $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $<
+%.buf.o: %.c $(DEPS)
+ $(CC) -DPB_BUFFER_ONLY $(CFLAGS) -c -o $@ $<
+test_encode3_buf: test_encode3.buf.o pb_encode.buf.o alltypes.pb.o
+ $(CC) $(LDFLAGS) $^ -o $@
+test_decode3_buf: test_decode3.buf.o pb_decode.buf.o alltypes.pb.o
+ $(CC) $(LDFLAGS) $^ -o $@
+
test_cxxcompile: pb_encode.cxx.o pb_decode.cxx.o
test_decode1: test_decode1.o pb_decode.o person.pb.o
test_decode2: test_decode2.o pb_decode.o person.pb.o
@@ -98,6 +113,7 @@ run_unittests: $(TESTS)
./test_encode3 | ./test_decode3
./test_encode3 1 | ./test_decode3 1
./test_encode3 1 | protoc --decode=AllTypes -I. -I../generator -I/usr/include alltypes.proto >/dev/null
+ ./test_encode3_buf 1 | ./test_decode3_buf 1
./bc_encode | ./bc_decode
./test_missing_fields