Nanopb is a plain-C implementation of Google's Protocol Buffers data format. It is targeted at 32 bit microcontrollers, but is also fit for other embedded systems with tight (2-10 kB ROM, <1 kB RAM) memory constraints.

Dependents:   FBRLogger Dumb_box_rev2

Uploaded from http://koti.kapsi.fi/~jpa/nanopb/ Original licence included below.

Copyright (c) 2011 Petteri Aimonen <jpa at nanopb.mail.kapsi.fi>

This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.

  1. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
  2. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
  3. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. This notice may not be removed or altered from any source distribution.
Committer:
intrinseca
Date:
Tue Feb 19 20:03:29 2013 +0000
Revision:
0:c7beea49fc91
Child:
1:e08406101222
Initial Uploaded Version 0.1.9

Who changed what in which revision?

UserRevisionLine numberNew contents of line
intrinseca 0:c7beea49fc91 1 /* pb_encode.c -- encode a protobuf using minimal resources
intrinseca 0:c7beea49fc91 2 *
intrinseca 0:c7beea49fc91 3 * 2011 Petteri Aimonen <jpa@kapsi.fi>
intrinseca 0:c7beea49fc91 4 */
intrinseca 0:c7beea49fc91 5
intrinseca 0:c7beea49fc91 6 #define NANOPB_INTERNALS
intrinseca 0:c7beea49fc91 7 #include "pb.h"
intrinseca 0:c7beea49fc91 8 #include "pb_encode.h"
intrinseca 0:c7beea49fc91 9 #include <string.h>
intrinseca 0:c7beea49fc91 10
intrinseca 0:c7beea49fc91 11 /* The warn_unused_result attribute appeared first in gcc-3.4.0 */
intrinseca 0:c7beea49fc91 12 #if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
intrinseca 0:c7beea49fc91 13 #define checkreturn
intrinseca 0:c7beea49fc91 14 #else
intrinseca 0:c7beea49fc91 15 /* Verify that we remember to check all return values for proper error propagation */
intrinseca 0:c7beea49fc91 16 #define checkreturn __attribute__((warn_unused_result))
intrinseca 0:c7beea49fc91 17 #endif
intrinseca 0:c7beea49fc91 18
intrinseca 0:c7beea49fc91 19 typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn;
intrinseca 0:c7beea49fc91 20
intrinseca 0:c7beea49fc91 21 /* --- Function pointers to field encoders ---
intrinseca 0:c7beea49fc91 22 * Order in the array must match pb_action_t LTYPE numbering.
intrinseca 0:c7beea49fc91 23 */
intrinseca 0:c7beea49fc91 24 static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = {
intrinseca 0:c7beea49fc91 25 &pb_enc_varint,
intrinseca 0:c7beea49fc91 26 &pb_enc_svarint,
intrinseca 0:c7beea49fc91 27 &pb_enc_fixed32,
intrinseca 0:c7beea49fc91 28 &pb_enc_fixed64,
intrinseca 0:c7beea49fc91 29
intrinseca 0:c7beea49fc91 30 &pb_enc_bytes,
intrinseca 0:c7beea49fc91 31 &pb_enc_string,
intrinseca 0:c7beea49fc91 32 &pb_enc_submessage
intrinseca 0:c7beea49fc91 33 };
intrinseca 0:c7beea49fc91 34
intrinseca 0:c7beea49fc91 35 /* pb_ostream_t implementation */
intrinseca 0:c7beea49fc91 36
intrinseca 0:c7beea49fc91 37 static bool checkreturn buf_write(pb_ostream_t *stream, const uint8_t *buf, size_t count)
intrinseca 0:c7beea49fc91 38 {
intrinseca 0:c7beea49fc91 39 uint8_t *dest = (uint8_t*)stream->state;
intrinseca 0:c7beea49fc91 40 stream->state = dest + count;
intrinseca 0:c7beea49fc91 41
intrinseca 0:c7beea49fc91 42 while (count--)
intrinseca 0:c7beea49fc91 43 *dest++ = *buf++;
intrinseca 0:c7beea49fc91 44
intrinseca 0:c7beea49fc91 45 return true;
intrinseca 0:c7beea49fc91 46 }
intrinseca 0:c7beea49fc91 47
intrinseca 0:c7beea49fc91 48 pb_ostream_t pb_ostream_from_buffer(uint8_t *buf, size_t bufsize)
intrinseca 0:c7beea49fc91 49 {
intrinseca 0:c7beea49fc91 50 pb_ostream_t stream;
intrinseca 0:c7beea49fc91 51 #ifdef PB_BUFFER_ONLY
intrinseca 0:c7beea49fc91 52 stream.callback = (void*)1; /* Just some marker value */
intrinseca 0:c7beea49fc91 53 #else
intrinseca 0:c7beea49fc91 54 stream.callback = &buf_write;
intrinseca 0:c7beea49fc91 55 #endif
intrinseca 0:c7beea49fc91 56 stream.state = buf;
intrinseca 0:c7beea49fc91 57 stream.max_size = bufsize;
intrinseca 0:c7beea49fc91 58 stream.bytes_written = 0;
intrinseca 0:c7beea49fc91 59 return stream;
intrinseca 0:c7beea49fc91 60 }
intrinseca 0:c7beea49fc91 61
intrinseca 0:c7beea49fc91 62 bool checkreturn pb_write(pb_ostream_t *stream, const uint8_t *buf, size_t count)
intrinseca 0:c7beea49fc91 63 {
intrinseca 0:c7beea49fc91 64 if (stream->callback != NULL)
intrinseca 0:c7beea49fc91 65 {
intrinseca 0:c7beea49fc91 66 if (stream->bytes_written + count > stream->max_size)
intrinseca 0:c7beea49fc91 67 return false;
intrinseca 0:c7beea49fc91 68
intrinseca 0:c7beea49fc91 69 #ifdef PB_BUFFER_ONLY
intrinseca 0:c7beea49fc91 70 if (!buf_write(stream, buf, count))
intrinseca 0:c7beea49fc91 71 return false;
intrinseca 0:c7beea49fc91 72 #else
intrinseca 0:c7beea49fc91 73 if (!stream->callback(stream, buf, count))
intrinseca 0:c7beea49fc91 74 return false;
intrinseca 0:c7beea49fc91 75 #endif
intrinseca 0:c7beea49fc91 76 }
intrinseca 0:c7beea49fc91 77
intrinseca 0:c7beea49fc91 78 stream->bytes_written += count;
intrinseca 0:c7beea49fc91 79 return true;
intrinseca 0:c7beea49fc91 80 }
intrinseca 0:c7beea49fc91 81
intrinseca 0:c7beea49fc91 82 /* Main encoding stuff */
intrinseca 0:c7beea49fc91 83
intrinseca 0:c7beea49fc91 84 /* Callbacks don't need this function because they usually know the data type
intrinseca 0:c7beea49fc91 85 * without examining the field structure.
intrinseca 0:c7beea49fc91 86 * Therefore it is static for now.
intrinseca 0:c7beea49fc91 87 */
intrinseca 0:c7beea49fc91 88 static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field,
intrinseca 0:c7beea49fc91 89 const void *pData, size_t count, pb_encoder_t func)
intrinseca 0:c7beea49fc91 90 {
intrinseca 0:c7beea49fc91 91 size_t i;
intrinseca 0:c7beea49fc91 92 const void *p;
intrinseca 0:c7beea49fc91 93 size_t size;
intrinseca 0:c7beea49fc91 94
intrinseca 0:c7beea49fc91 95 if (count == 0)
intrinseca 0:c7beea49fc91 96 return true;
intrinseca 0:c7beea49fc91 97
intrinseca 0:c7beea49fc91 98 if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE)
intrinseca 0:c7beea49fc91 99 {
intrinseca 0:c7beea49fc91 100 if (!pb_encode_tag(stream, PB_WT_STRING, field->tag))
intrinseca 0:c7beea49fc91 101 return false;
intrinseca 0:c7beea49fc91 102
intrinseca 0:c7beea49fc91 103 /* Determine the total size of packed array. */
intrinseca 0:c7beea49fc91 104 if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32)
intrinseca 0:c7beea49fc91 105 {
intrinseca 0:c7beea49fc91 106 size = 4 * count;
intrinseca 0:c7beea49fc91 107 }
intrinseca 0:c7beea49fc91 108 else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
intrinseca 0:c7beea49fc91 109 {
intrinseca 0:c7beea49fc91 110 size = 8 * count;
intrinseca 0:c7beea49fc91 111 }
intrinseca 0:c7beea49fc91 112 else
intrinseca 0:c7beea49fc91 113 {
intrinseca 0:c7beea49fc91 114 pb_ostream_t sizestream = {0,0,0,0};
intrinseca 0:c7beea49fc91 115 p = pData;
intrinseca 0:c7beea49fc91 116 for (i = 0; i < count; i++)
intrinseca 0:c7beea49fc91 117 {
intrinseca 0:c7beea49fc91 118 if (!func(&sizestream, field, p))
intrinseca 0:c7beea49fc91 119 return false;
intrinseca 0:c7beea49fc91 120 p = (const char*)p + field->data_size;
intrinseca 0:c7beea49fc91 121 }
intrinseca 0:c7beea49fc91 122 size = sizestream.bytes_written;
intrinseca 0:c7beea49fc91 123 }
intrinseca 0:c7beea49fc91 124
intrinseca 0:c7beea49fc91 125 if (!pb_encode_varint(stream, (uint64_t)size))
intrinseca 0:c7beea49fc91 126 return false;
intrinseca 0:c7beea49fc91 127
intrinseca 0:c7beea49fc91 128 if (stream->callback == NULL)
intrinseca 0:c7beea49fc91 129 return pb_write(stream, NULL, size); /* Just sizing.. */
intrinseca 0:c7beea49fc91 130
intrinseca 0:c7beea49fc91 131 /* Write the data */
intrinseca 0:c7beea49fc91 132 p = pData;
intrinseca 0:c7beea49fc91 133 for (i = 0; i < count; i++)
intrinseca 0:c7beea49fc91 134 {
intrinseca 0:c7beea49fc91 135 if (!func(stream, field, p))
intrinseca 0:c7beea49fc91 136 return false;
intrinseca 0:c7beea49fc91 137 p = (const char*)p + field->data_size;
intrinseca 0:c7beea49fc91 138 }
intrinseca 0:c7beea49fc91 139 }
intrinseca 0:c7beea49fc91 140 else
intrinseca 0:c7beea49fc91 141 {
intrinseca 0:c7beea49fc91 142 p = pData;
intrinseca 0:c7beea49fc91 143 for (i = 0; i < count; i++)
intrinseca 0:c7beea49fc91 144 {
intrinseca 0:c7beea49fc91 145 if (!pb_encode_tag_for_field(stream, field))
intrinseca 0:c7beea49fc91 146 return false;
intrinseca 0:c7beea49fc91 147 if (!func(stream, field, p))
intrinseca 0:c7beea49fc91 148 return false;
intrinseca 0:c7beea49fc91 149 p = (const char*)p + field->data_size;
intrinseca 0:c7beea49fc91 150 }
intrinseca 0:c7beea49fc91 151 }
intrinseca 0:c7beea49fc91 152
intrinseca 0:c7beea49fc91 153 return true;
intrinseca 0:c7beea49fc91 154 }
intrinseca 0:c7beea49fc91 155
intrinseca 0:c7beea49fc91 156 bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
intrinseca 0:c7beea49fc91 157 {
intrinseca 0:c7beea49fc91 158 const pb_field_t *field = fields;
intrinseca 0:c7beea49fc91 159 const void *pData = src_struct;
intrinseca 0:c7beea49fc91 160 const void *pSize;
intrinseca 0:c7beea49fc91 161 size_t prev_size = 0;
intrinseca 0:c7beea49fc91 162
intrinseca 0:c7beea49fc91 163 while (field->tag != 0)
intrinseca 0:c7beea49fc91 164 {
intrinseca 0:c7beea49fc91 165 pb_encoder_t func = PB_ENCODERS[PB_LTYPE(field->type)];
intrinseca 0:c7beea49fc91 166 pData = (const char*)pData + prev_size + field->data_offset;
intrinseca 0:c7beea49fc91 167 pSize = (const char*)pData + field->size_offset;
intrinseca 0:c7beea49fc91 168
intrinseca 0:c7beea49fc91 169 prev_size = field->data_size;
intrinseca 0:c7beea49fc91 170 if (PB_HTYPE(field->type) == PB_HTYPE_ARRAY)
intrinseca 0:c7beea49fc91 171 prev_size *= field->array_size;
intrinseca 0:c7beea49fc91 172
intrinseca 0:c7beea49fc91 173 switch (PB_HTYPE(field->type))
intrinseca 0:c7beea49fc91 174 {
intrinseca 0:c7beea49fc91 175 case PB_HTYPE_REQUIRED:
intrinseca 0:c7beea49fc91 176 if (!pb_encode_tag_for_field(stream, field))
intrinseca 0:c7beea49fc91 177 return false;
intrinseca 0:c7beea49fc91 178 if (!func(stream, field, pData))
intrinseca 0:c7beea49fc91 179 return false;
intrinseca 0:c7beea49fc91 180 break;
intrinseca 0:c7beea49fc91 181
intrinseca 0:c7beea49fc91 182 case PB_HTYPE_OPTIONAL:
intrinseca 0:c7beea49fc91 183 if (*(const bool*)pSize)
intrinseca 0:c7beea49fc91 184 {
intrinseca 0:c7beea49fc91 185 if (!pb_encode_tag_for_field(stream, field))
intrinseca 0:c7beea49fc91 186 return false;
intrinseca 0:c7beea49fc91 187
intrinseca 0:c7beea49fc91 188 if (!func(stream, field, pData))
intrinseca 0:c7beea49fc91 189 return false;
intrinseca 0:c7beea49fc91 190 }
intrinseca 0:c7beea49fc91 191 break;
intrinseca 0:c7beea49fc91 192
intrinseca 0:c7beea49fc91 193 case PB_HTYPE_ARRAY:
intrinseca 0:c7beea49fc91 194 if (!encode_array(stream, field, pData, *(const size_t*)pSize, func))
intrinseca 0:c7beea49fc91 195 return false;
intrinseca 0:c7beea49fc91 196 break;
intrinseca 0:c7beea49fc91 197
intrinseca 0:c7beea49fc91 198 case PB_HTYPE_CALLBACK:
intrinseca 0:c7beea49fc91 199 {
intrinseca 0:c7beea49fc91 200 const pb_callback_t *callback = (const pb_callback_t*)pData;
intrinseca 0:c7beea49fc91 201 if (callback->funcs.encode != NULL)
intrinseca 0:c7beea49fc91 202 {
intrinseca 0:c7beea49fc91 203 if (!callback->funcs.encode(stream, field, callback->arg))
intrinseca 0:c7beea49fc91 204 return false;
intrinseca 0:c7beea49fc91 205 }
intrinseca 0:c7beea49fc91 206 break;
intrinseca 0:c7beea49fc91 207 }
intrinseca 0:c7beea49fc91 208 }
intrinseca 0:c7beea49fc91 209
intrinseca 0:c7beea49fc91 210 field++;
intrinseca 0:c7beea49fc91 211 }
intrinseca 0:c7beea49fc91 212
intrinseca 0:c7beea49fc91 213 return true;
intrinseca 0:c7beea49fc91 214 }
intrinseca 0:c7beea49fc91 215
intrinseca 0:c7beea49fc91 216 /* Helper functions */
intrinseca 0:c7beea49fc91 217 bool checkreturn pb_encode_varint(pb_ostream_t *stream, uint64_t value)
intrinseca 0:c7beea49fc91 218 {
intrinseca 0:c7beea49fc91 219 uint8_t buffer[10];
intrinseca 0:c7beea49fc91 220 size_t i = 0;
intrinseca 0:c7beea49fc91 221
intrinseca 0:c7beea49fc91 222 if (value == 0)
intrinseca 0:c7beea49fc91 223 return pb_write(stream, (uint8_t*)&value, 1);
intrinseca 0:c7beea49fc91 224
intrinseca 0:c7beea49fc91 225 while (value)
intrinseca 0:c7beea49fc91 226 {
intrinseca 0:c7beea49fc91 227 buffer[i] = (uint8_t)((value & 0x7F) | 0x80);
intrinseca 0:c7beea49fc91 228 value >>= 7;
intrinseca 0:c7beea49fc91 229 i++;
intrinseca 0:c7beea49fc91 230 }
intrinseca 0:c7beea49fc91 231 buffer[i-1] &= 0x7F; /* Unset top bit on last byte */
intrinseca 0:c7beea49fc91 232
intrinseca 0:c7beea49fc91 233 return pb_write(stream, buffer, i);
intrinseca 0:c7beea49fc91 234 }
intrinseca 0:c7beea49fc91 235
intrinseca 0:c7beea49fc91 236 bool checkreturn pb_encode_svarint(pb_ostream_t *stream, int64_t value)
intrinseca 0:c7beea49fc91 237 {
intrinseca 0:c7beea49fc91 238 uint64_t zigzagged;
intrinseca 0:c7beea49fc91 239 if (value < 0)
intrinseca 0:c7beea49fc91 240 zigzagged = (uint64_t)(~(value << 1));
intrinseca 0:c7beea49fc91 241 else
intrinseca 0:c7beea49fc91 242 zigzagged = (uint64_t)(value << 1);
intrinseca 0:c7beea49fc91 243
intrinseca 0:c7beea49fc91 244 return pb_encode_varint(stream, zigzagged);
intrinseca 0:c7beea49fc91 245 }
intrinseca 0:c7beea49fc91 246
intrinseca 0:c7beea49fc91 247 bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value)
intrinseca 0:c7beea49fc91 248 {
intrinseca 0:c7beea49fc91 249 #ifdef __BIG_ENDIAN__
intrinseca 0:c7beea49fc91 250 const uint8_t *bytes = value;
intrinseca 0:c7beea49fc91 251 uint8_t lebytes[4];
intrinseca 0:c7beea49fc91 252 lebytes[0] = bytes[3];
intrinseca 0:c7beea49fc91 253 lebytes[1] = bytes[2];
intrinseca 0:c7beea49fc91 254 lebytes[2] = bytes[1];
intrinseca 0:c7beea49fc91 255 lebytes[3] = bytes[0];
intrinseca 0:c7beea49fc91 256 return pb_write(stream, lebytes, 4);
intrinseca 0:c7beea49fc91 257 #else
intrinseca 0:c7beea49fc91 258 return pb_write(stream, (const uint8_t*)value, 4);
intrinseca 0:c7beea49fc91 259 #endif
intrinseca 0:c7beea49fc91 260 }
intrinseca 0:c7beea49fc91 261
intrinseca 0:c7beea49fc91 262 bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value)
intrinseca 0:c7beea49fc91 263 {
intrinseca 0:c7beea49fc91 264 #ifdef __BIG_ENDIAN__
intrinseca 0:c7beea49fc91 265 const uint8_t *bytes = value;
intrinseca 0:c7beea49fc91 266 uint8_t lebytes[8];
intrinseca 0:c7beea49fc91 267 lebytes[0] = bytes[7];
intrinseca 0:c7beea49fc91 268 lebytes[1] = bytes[6];
intrinseca 0:c7beea49fc91 269 lebytes[2] = bytes[5];
intrinseca 0:c7beea49fc91 270 lebytes[3] = bytes[4];
intrinseca 0:c7beea49fc91 271 lebytes[4] = bytes[3];
intrinseca 0:c7beea49fc91 272 lebytes[5] = bytes[2];
intrinseca 0:c7beea49fc91 273 lebytes[6] = bytes[1];
intrinseca 0:c7beea49fc91 274 lebytes[7] = bytes[0];
intrinseca 0:c7beea49fc91 275 return pb_write(stream, lebytes, 8);
intrinseca 0:c7beea49fc91 276 #else
intrinseca 0:c7beea49fc91 277 return pb_write(stream, (const uint8_t*)value, 8);
intrinseca 0:c7beea49fc91 278 #endif
intrinseca 0:c7beea49fc91 279 }
intrinseca 0:c7beea49fc91 280
intrinseca 0:c7beea49fc91 281 bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number)
intrinseca 0:c7beea49fc91 282 {
intrinseca 0:c7beea49fc91 283 uint64_t tag = wiretype | (field_number << 3);
intrinseca 0:c7beea49fc91 284 return pb_encode_varint(stream, tag);
intrinseca 0:c7beea49fc91 285 }
intrinseca 0:c7beea49fc91 286
intrinseca 0:c7beea49fc91 287 bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field)
intrinseca 0:c7beea49fc91 288 {
intrinseca 0:c7beea49fc91 289 pb_wire_type_t wiretype;
intrinseca 0:c7beea49fc91 290 switch (PB_LTYPE(field->type))
intrinseca 0:c7beea49fc91 291 {
intrinseca 0:c7beea49fc91 292 case PB_LTYPE_VARINT:
intrinseca 0:c7beea49fc91 293 case PB_LTYPE_SVARINT:
intrinseca 0:c7beea49fc91 294 wiretype = PB_WT_VARINT;
intrinseca 0:c7beea49fc91 295 break;
intrinseca 0:c7beea49fc91 296
intrinseca 0:c7beea49fc91 297 case PB_LTYPE_FIXED32:
intrinseca 0:c7beea49fc91 298 wiretype = PB_WT_32BIT;
intrinseca 0:c7beea49fc91 299 break;
intrinseca 0:c7beea49fc91 300
intrinseca 0:c7beea49fc91 301 case PB_LTYPE_FIXED64:
intrinseca 0:c7beea49fc91 302 wiretype = PB_WT_64BIT;
intrinseca 0:c7beea49fc91 303 break;
intrinseca 0:c7beea49fc91 304
intrinseca 0:c7beea49fc91 305 case PB_LTYPE_BYTES:
intrinseca 0:c7beea49fc91 306 case PB_LTYPE_STRING:
intrinseca 0:c7beea49fc91 307 case PB_LTYPE_SUBMESSAGE:
intrinseca 0:c7beea49fc91 308 wiretype = PB_WT_STRING;
intrinseca 0:c7beea49fc91 309 break;
intrinseca 0:c7beea49fc91 310
intrinseca 0:c7beea49fc91 311 default:
intrinseca 0:c7beea49fc91 312 return false;
intrinseca 0:c7beea49fc91 313 }
intrinseca 0:c7beea49fc91 314
intrinseca 0:c7beea49fc91 315 return pb_encode_tag(stream, wiretype, field->tag);
intrinseca 0:c7beea49fc91 316 }
intrinseca 0:c7beea49fc91 317
intrinseca 0:c7beea49fc91 318 bool checkreturn pb_encode_string(pb_ostream_t *stream, const uint8_t *buffer, size_t size)
intrinseca 0:c7beea49fc91 319 {
intrinseca 0:c7beea49fc91 320 if (!pb_encode_varint(stream, (uint64_t)size))
intrinseca 0:c7beea49fc91 321 return false;
intrinseca 0:c7beea49fc91 322
intrinseca 0:c7beea49fc91 323 return pb_write(stream, buffer, size);
intrinseca 0:c7beea49fc91 324 }
intrinseca 0:c7beea49fc91 325
intrinseca 0:c7beea49fc91 326 bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
intrinseca 0:c7beea49fc91 327 {
intrinseca 0:c7beea49fc91 328 /* First calculate the message size using a non-writing substream. */
intrinseca 0:c7beea49fc91 329 pb_ostream_t substream = {0,0,0,0};
intrinseca 0:c7beea49fc91 330 size_t size;
intrinseca 0:c7beea49fc91 331 bool status;
intrinseca 0:c7beea49fc91 332
intrinseca 0:c7beea49fc91 333 if (!pb_encode(&substream, fields, src_struct))
intrinseca 0:c7beea49fc91 334 return false;
intrinseca 0:c7beea49fc91 335
intrinseca 0:c7beea49fc91 336 size = substream.bytes_written;
intrinseca 0:c7beea49fc91 337
intrinseca 0:c7beea49fc91 338 if (!pb_encode_varint(stream, (uint64_t)size))
intrinseca 0:c7beea49fc91 339 return false;
intrinseca 0:c7beea49fc91 340
intrinseca 0:c7beea49fc91 341 if (stream->callback == NULL)
intrinseca 0:c7beea49fc91 342 return pb_write(stream, NULL, size); /* Just sizing */
intrinseca 0:c7beea49fc91 343
intrinseca 0:c7beea49fc91 344 if (stream->bytes_written + size > stream->max_size)
intrinseca 0:c7beea49fc91 345 return false;
intrinseca 0:c7beea49fc91 346
intrinseca 0:c7beea49fc91 347 /* Use a substream to verify that a callback doesn't write more than
intrinseca 0:c7beea49fc91 348 * what it did the first time. */
intrinseca 0:c7beea49fc91 349 substream.callback = stream->callback;
intrinseca 0:c7beea49fc91 350 substream.state = stream->state;
intrinseca 0:c7beea49fc91 351 substream.max_size = size;
intrinseca 0:c7beea49fc91 352 substream.bytes_written = 0;
intrinseca 0:c7beea49fc91 353
intrinseca 0:c7beea49fc91 354 status = pb_encode(&substream, fields, src_struct);
intrinseca 0:c7beea49fc91 355
intrinseca 0:c7beea49fc91 356 stream->bytes_written += substream.bytes_written;
intrinseca 0:c7beea49fc91 357 stream->state = substream.state;
intrinseca 0:c7beea49fc91 358
intrinseca 0:c7beea49fc91 359 if (substream.bytes_written != size)
intrinseca 0:c7beea49fc91 360 return false;
intrinseca 0:c7beea49fc91 361
intrinseca 0:c7beea49fc91 362 return status;
intrinseca 0:c7beea49fc91 363 }
intrinseca 0:c7beea49fc91 364
intrinseca 0:c7beea49fc91 365 /* Field encoders */
intrinseca 0:c7beea49fc91 366
intrinseca 0:c7beea49fc91 367 bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
intrinseca 0:c7beea49fc91 368 {
intrinseca 0:c7beea49fc91 369 uint64_t value = 0;
intrinseca 0:c7beea49fc91 370
intrinseca 0:c7beea49fc91 371 switch (field->data_size)
intrinseca 0:c7beea49fc91 372 {
intrinseca 0:c7beea49fc91 373 case 1: value = *(const uint8_t*)src; break;
intrinseca 0:c7beea49fc91 374 case 2: value = *(const uint16_t*)src; break;
intrinseca 0:c7beea49fc91 375 case 4: value = *(const uint32_t*)src; break;
intrinseca 0:c7beea49fc91 376 case 8: value = *(const uint64_t*)src; break;
intrinseca 0:c7beea49fc91 377 default: return false;
intrinseca 0:c7beea49fc91 378 }
intrinseca 0:c7beea49fc91 379
intrinseca 0:c7beea49fc91 380 return pb_encode_varint(stream, value);
intrinseca 0:c7beea49fc91 381 }
intrinseca 0:c7beea49fc91 382
intrinseca 0:c7beea49fc91 383 bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
intrinseca 0:c7beea49fc91 384 {
intrinseca 0:c7beea49fc91 385 int64_t value = 0;
intrinseca 0:c7beea49fc91 386
intrinseca 0:c7beea49fc91 387 switch (field->data_size)
intrinseca 0:c7beea49fc91 388 {
intrinseca 0:c7beea49fc91 389 case 4: value = *(const int32_t*)src; break;
intrinseca 0:c7beea49fc91 390 case 8: value = *(const int64_t*)src; break;
intrinseca 0:c7beea49fc91 391 default: return false;
intrinseca 0:c7beea49fc91 392 }
intrinseca 0:c7beea49fc91 393
intrinseca 0:c7beea49fc91 394 return pb_encode_svarint(stream, value);
intrinseca 0:c7beea49fc91 395 }
intrinseca 0:c7beea49fc91 396
intrinseca 0:c7beea49fc91 397 bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src)
intrinseca 0:c7beea49fc91 398 {
intrinseca 0:c7beea49fc91 399 UNUSED(field);
intrinseca 0:c7beea49fc91 400 return pb_encode_fixed64(stream, src);
intrinseca 0:c7beea49fc91 401 }
intrinseca 0:c7beea49fc91 402
intrinseca 0:c7beea49fc91 403 bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src)
intrinseca 0:c7beea49fc91 404 {
intrinseca 0:c7beea49fc91 405 UNUSED(field);
intrinseca 0:c7beea49fc91 406 return pb_encode_fixed32(stream, src);
intrinseca 0:c7beea49fc91 407 }
intrinseca 0:c7beea49fc91 408
intrinseca 0:c7beea49fc91 409 bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src)
intrinseca 0:c7beea49fc91 410 {
intrinseca 0:c7beea49fc91 411 const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)src;
intrinseca 0:c7beea49fc91 412 UNUSED(field);
intrinseca 0:c7beea49fc91 413 return pb_encode_string(stream, bytes->bytes, bytes->size);
intrinseca 0:c7beea49fc91 414 }
intrinseca 0:c7beea49fc91 415
intrinseca 0:c7beea49fc91 416 bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src)
intrinseca 0:c7beea49fc91 417 {
intrinseca 0:c7beea49fc91 418 UNUSED(field);
intrinseca 0:c7beea49fc91 419 return pb_encode_string(stream, (const uint8_t*)src, strlen((const char*)src));
intrinseca 0:c7beea49fc91 420 }
intrinseca 0:c7beea49fc91 421
intrinseca 0:c7beea49fc91 422 bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src)
intrinseca 0:c7beea49fc91 423 {
intrinseca 0:c7beea49fc91 424 if (field->ptr == NULL)
intrinseca 0:c7beea49fc91 425 return false;
intrinseca 0:c7beea49fc91 426
intrinseca 0:c7beea49fc91 427 return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src);
intrinseca 0:c7beea49fc91 428 }
intrinseca 0:c7beea49fc91 429