Nanopb files

Dependents:   nanopb_V2 Message_generator LEX_Threaded_Programming_V3

Committer:
intrinseca
Date:
Fri Mar 01 12:41:26 2013 +0000
Revision:
1:e08406101222
Parent:
0:c7beea49fc91
Child:
2:d2c61a9be078
fix bugs

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