Nanopb files

Dependents:   nanopb_V2 Message_generator LEX_Threaded_Programming_V3

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