Example
[apps/agl-service-can-low-level.git] / pb_encode.c
index 63ca288..2e74034 100644 (file)
@@ -124,12 +124,17 @@ bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_
     const pb_field_t *field = fields;
     const void *pData = src_struct;
     const void *pSize;
+    size_t prev_size = 0;
     
     while (field->tag != 0)
     {
-        pData = (const char*)pData + field->data_offset;
+        pData = (const char*)pData + prev_size + field->data_offset;
         pSize = (const char*)pData + field->size_offset;
         
+        prev_size = field->data_size;
+        if (PB_HTYPE(field->type) == PB_HTYPE_ARRAY)
+            prev_size *= field->array_size;
+        
         pb_encoder_t func = PB_ENCODERS[PB_LTYPE(field->type)];
         
         switch (PB_HTYPE(field->type))
@@ -309,16 +314,17 @@ bool pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *sr
 
 bool pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src)
 {
-    pb_ostream_t sizestream = {0};
+    pb_ostream_t substream = {0};
     size_t size;
+    bool status;
     
     if (field->ptr == NULL)
         return false;
     
-    if (!pb_encode(&sizestream, (pb_field_t*)field->ptr, src))
+    if (!pb_encode(&substream, (pb_field_t*)field->ptr, src))
         return false;
     
-    size = sizestream.bytes_written;
+    size = substream.bytes_written;
     
     if (!pb_encode_varint(stream, size))
         return false;
@@ -326,6 +332,23 @@ bool pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void
     if (stream->callback == NULL)
         return pb_write(stream, NULL, size); /* Just sizing */
     
-    return pb_encode(stream, (pb_field_t*)field->ptr, src);
+    if (stream->bytes_written + size > stream->max_size)
+        return false;
+        
+    /* Use a substream to verify that a callback doesn't write more than
+     * what it did the first time. */
+    substream.callback = stream->callback;
+    substream.state = stream->state;
+    substream.max_size = size;
+    substream.bytes_written = 0;
+    
+    status = pb_encode(&substream, (pb_field_t*)field->ptr, src);
+    
+    stream->bytes_written += substream.bytes_written;
+    
+    if (substream.bytes_written != size)
+        return false;
+    
+    return status;
 }