Add compile-time option PB_BUFFER_ONLY.
authorPetteri Aimonen <jpa@git.mail.kapsi.fi>
Wed, 6 Feb 2013 18:54:25 +0000 (20:54 +0200)
committerPetteri Aimonen <jpa@git.mail.kapsi.fi>
Wed, 6 Feb 2013 18:54:25 +0000 (20:54 +0200)
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.

docs/reference.rst
pb_decode.c
pb_decode.h
pb_encode.c
pb_encode.h
tests/Makefile

index 2b10c2e..fee1b70 100644 (file)
@@ -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.
index 9faceca..b664fe1 100644 (file)
@@ -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
index e9f8ced..35de0a2 100644 (file)
@@ -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;
     
index 95223cb..bba5dc1 100644 (file)
@@ -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;
index 85a8297..69b88e8 100644 (file)
@@ -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;
index 6383099..38f10ea 100644 (file)
@@ -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