test code 123

Dependencies:   mbed

Fork of LinkNode-Test by Qi Yao

Committer:
youkee
Date:
Fri Oct 28 13:04:10 2016 +0000
Revision:
1:b0d4fbbdb244
Parent:
0:1ad0e04b1bc5
ghhbfdd

Who changed what in which revision?

UserRevisionLine numberNew contents of line
youkee 0:1ad0e04b1bc5 1 /* pb_decode.c -- decode a protobuf using minimal resources
youkee 0:1ad0e04b1bc5 2 *
youkee 0:1ad0e04b1bc5 3 * 2011 Petteri Aimonen <jpa@kapsi.fi>
youkee 0:1ad0e04b1bc5 4 */
youkee 0:1ad0e04b1bc5 5
youkee 0:1ad0e04b1bc5 6 /* Use the GCC warn_unused_result attribute to check that all return values
youkee 0:1ad0e04b1bc5 7 * are propagated correctly. On other compilers and gcc before 3.4.0 just
youkee 0:1ad0e04b1bc5 8 * ignore the annotation.
youkee 0:1ad0e04b1bc5 9 */
youkee 0:1ad0e04b1bc5 10 #if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
youkee 0:1ad0e04b1bc5 11 #define checkreturn
youkee 0:1ad0e04b1bc5 12 #else
youkee 0:1ad0e04b1bc5 13 #define checkreturn __attribute__((warn_unused_result))
youkee 0:1ad0e04b1bc5 14 #endif
youkee 0:1ad0e04b1bc5 15
youkee 0:1ad0e04b1bc5 16 #include "pb.h"
youkee 0:1ad0e04b1bc5 17 #include "pb_decode.h"
youkee 0:1ad0e04b1bc5 18 #include "pb_common.h"
youkee 0:1ad0e04b1bc5 19
youkee 0:1ad0e04b1bc5 20 /**************************************
youkee 0:1ad0e04b1bc5 21 * Declarations internal to this file *
youkee 0:1ad0e04b1bc5 22 **************************************/
youkee 0:1ad0e04b1bc5 23
youkee 0:1ad0e04b1bc5 24 typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn;
youkee 0:1ad0e04b1bc5 25
youkee 0:1ad0e04b1bc5 26 static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count);
youkee 0:1ad0e04b1bc5 27 static bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest);
youkee 0:1ad0e04b1bc5 28 static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size);
youkee 0:1ad0e04b1bc5 29 static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter);
youkee 0:1ad0e04b1bc5 30 static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter);
youkee 0:1ad0e04b1bc5 31 static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter);
youkee 0:1ad0e04b1bc5 32 static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension);
youkee 0:1ad0e04b1bc5 33 static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type);
youkee 0:1ad0e04b1bc5 34 static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter);
youkee 0:1ad0e04b1bc5 35 static bool checkreturn find_extension_field(pb_field_iter_t *iter);
youkee 0:1ad0e04b1bc5 36 static void pb_field_set_to_default(pb_field_iter_t *iter);
youkee 0:1ad0e04b1bc5 37 static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct);
youkee 0:1ad0e04b1bc5 38 static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest);
youkee 0:1ad0e04b1bc5 39 static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest);
youkee 0:1ad0e04b1bc5 40 static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest);
youkee 0:1ad0e04b1bc5 41 static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest);
youkee 0:1ad0e04b1bc5 42 static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest);
youkee 0:1ad0e04b1bc5 43 static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest);
youkee 0:1ad0e04b1bc5 44 static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest);
youkee 0:1ad0e04b1bc5 45 static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest);
youkee 0:1ad0e04b1bc5 46 static bool checkreturn pb_skip_varint(pb_istream_t *stream);
youkee 0:1ad0e04b1bc5 47 static bool checkreturn pb_skip_string(pb_istream_t *stream);
youkee 0:1ad0e04b1bc5 48
youkee 0:1ad0e04b1bc5 49 #ifdef PB_ENABLE_MALLOC
youkee 0:1ad0e04b1bc5 50 static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size);
youkee 0:1ad0e04b1bc5 51 static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter);
youkee 0:1ad0e04b1bc5 52 static void pb_release_single_field(const pb_field_iter_t *iter);
youkee 0:1ad0e04b1bc5 53 #endif
youkee 0:1ad0e04b1bc5 54
youkee 0:1ad0e04b1bc5 55 /* --- Function pointers to field decoders ---
youkee 0:1ad0e04b1bc5 56 * Order in the array must match pb_action_t LTYPE numbering.
youkee 0:1ad0e04b1bc5 57 */
youkee 0:1ad0e04b1bc5 58 static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = {
youkee 0:1ad0e04b1bc5 59 &pb_dec_varint,
youkee 0:1ad0e04b1bc5 60 &pb_dec_uvarint,
youkee 0:1ad0e04b1bc5 61 &pb_dec_svarint,
youkee 0:1ad0e04b1bc5 62 &pb_dec_fixed32,
youkee 0:1ad0e04b1bc5 63 &pb_dec_fixed64,
youkee 0:1ad0e04b1bc5 64
youkee 0:1ad0e04b1bc5 65 &pb_dec_bytes,
youkee 0:1ad0e04b1bc5 66 &pb_dec_string,
youkee 0:1ad0e04b1bc5 67 &pb_dec_submessage,
youkee 0:1ad0e04b1bc5 68 NULL /* extensions */
youkee 0:1ad0e04b1bc5 69 };
youkee 0:1ad0e04b1bc5 70
youkee 0:1ad0e04b1bc5 71 /*******************************
youkee 0:1ad0e04b1bc5 72 * pb_istream_t implementation *
youkee 0:1ad0e04b1bc5 73 *******************************/
youkee 0:1ad0e04b1bc5 74
youkee 0:1ad0e04b1bc5 75 static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count)
youkee 0:1ad0e04b1bc5 76 {
youkee 0:1ad0e04b1bc5 77 const pb_byte_t *source = (const pb_byte_t*)stream->state;
youkee 0:1ad0e04b1bc5 78 stream->state = (pb_byte_t*)stream->state + count;
youkee 0:1ad0e04b1bc5 79
youkee 0:1ad0e04b1bc5 80 if (buf != NULL)
youkee 0:1ad0e04b1bc5 81 {
youkee 0:1ad0e04b1bc5 82 while (count--)
youkee 0:1ad0e04b1bc5 83 *buf++ = *source++;
youkee 0:1ad0e04b1bc5 84 }
youkee 0:1ad0e04b1bc5 85
youkee 0:1ad0e04b1bc5 86 return true;
youkee 0:1ad0e04b1bc5 87 }
youkee 0:1ad0e04b1bc5 88
youkee 0:1ad0e04b1bc5 89 bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count)
youkee 0:1ad0e04b1bc5 90 {
youkee 0:1ad0e04b1bc5 91 #ifndef PB_BUFFER_ONLY
youkee 0:1ad0e04b1bc5 92 if (buf == NULL && stream->callback != buf_read)
youkee 0:1ad0e04b1bc5 93 {
youkee 0:1ad0e04b1bc5 94 /* Skip input bytes */
youkee 0:1ad0e04b1bc5 95 pb_byte_t tmp[16];
youkee 0:1ad0e04b1bc5 96 while (count > 16)
youkee 0:1ad0e04b1bc5 97 {
youkee 0:1ad0e04b1bc5 98 if (!pb_read(stream, tmp, 16))
youkee 0:1ad0e04b1bc5 99 return false;
youkee 0:1ad0e04b1bc5 100
youkee 0:1ad0e04b1bc5 101 count -= 16;
youkee 0:1ad0e04b1bc5 102 }
youkee 0:1ad0e04b1bc5 103
youkee 0:1ad0e04b1bc5 104 return pb_read(stream, tmp, count);
youkee 0:1ad0e04b1bc5 105 }
youkee 0:1ad0e04b1bc5 106 #endif
youkee 0:1ad0e04b1bc5 107
youkee 0:1ad0e04b1bc5 108 if (stream->bytes_left < count)
youkee 0:1ad0e04b1bc5 109 PB_RETURN_ERROR(stream, "end-of-stream");
youkee 0:1ad0e04b1bc5 110
youkee 0:1ad0e04b1bc5 111 #ifndef PB_BUFFER_ONLY
youkee 0:1ad0e04b1bc5 112 if (!stream->callback(stream, buf, count))
youkee 0:1ad0e04b1bc5 113 PB_RETURN_ERROR(stream, "io error");
youkee 0:1ad0e04b1bc5 114 #else
youkee 0:1ad0e04b1bc5 115 if (!buf_read(stream, buf, count))
youkee 0:1ad0e04b1bc5 116 return false;
youkee 0:1ad0e04b1bc5 117 #endif
youkee 0:1ad0e04b1bc5 118
youkee 0:1ad0e04b1bc5 119 stream->bytes_left -= count;
youkee 0:1ad0e04b1bc5 120 return true;
youkee 0:1ad0e04b1bc5 121 }
youkee 0:1ad0e04b1bc5 122
youkee 0:1ad0e04b1bc5 123 /* Read a single byte from input stream. buf may not be NULL.
youkee 0:1ad0e04b1bc5 124 * This is an optimization for the varint decoding. */
youkee 0:1ad0e04b1bc5 125 static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf)
youkee 0:1ad0e04b1bc5 126 {
youkee 0:1ad0e04b1bc5 127 if (stream->bytes_left == 0)
youkee 0:1ad0e04b1bc5 128 PB_RETURN_ERROR(stream, "end-of-stream");
youkee 0:1ad0e04b1bc5 129
youkee 0:1ad0e04b1bc5 130 #ifndef PB_BUFFER_ONLY
youkee 0:1ad0e04b1bc5 131 if (!stream->callback(stream, buf, 1))
youkee 0:1ad0e04b1bc5 132 PB_RETURN_ERROR(stream, "io error");
youkee 0:1ad0e04b1bc5 133 #else
youkee 0:1ad0e04b1bc5 134 *buf = *(const pb_byte_t*)stream->state;
youkee 0:1ad0e04b1bc5 135 stream->state = (pb_byte_t*)stream->state + 1;
youkee 0:1ad0e04b1bc5 136 #endif
youkee 0:1ad0e04b1bc5 137
youkee 0:1ad0e04b1bc5 138 stream->bytes_left--;
youkee 0:1ad0e04b1bc5 139
youkee 0:1ad0e04b1bc5 140 return true;
youkee 0:1ad0e04b1bc5 141 }
youkee 0:1ad0e04b1bc5 142
youkee 0:1ad0e04b1bc5 143 pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize)
youkee 0:1ad0e04b1bc5 144 {
youkee 0:1ad0e04b1bc5 145 pb_istream_t stream;
youkee 0:1ad0e04b1bc5 146 /* Cast away the const from buf without a compiler error. We are
youkee 0:1ad0e04b1bc5 147 * careful to use it only in a const manner in the callbacks.
youkee 0:1ad0e04b1bc5 148 */
youkee 0:1ad0e04b1bc5 149 union {
youkee 0:1ad0e04b1bc5 150 void *state;
youkee 0:1ad0e04b1bc5 151 const void *c_state;
youkee 0:1ad0e04b1bc5 152 } state;
youkee 0:1ad0e04b1bc5 153 #ifdef PB_BUFFER_ONLY
youkee 0:1ad0e04b1bc5 154 stream.callback = NULL;
youkee 0:1ad0e04b1bc5 155 #else
youkee 0:1ad0e04b1bc5 156 stream.callback = &buf_read;
youkee 0:1ad0e04b1bc5 157 #endif
youkee 0:1ad0e04b1bc5 158 state.c_state = buf;
youkee 0:1ad0e04b1bc5 159 stream.state = state.state;
youkee 0:1ad0e04b1bc5 160 stream.bytes_left = bufsize;
youkee 0:1ad0e04b1bc5 161 #ifndef PB_NO_ERRMSG
youkee 0:1ad0e04b1bc5 162 stream.errmsg = NULL;
youkee 0:1ad0e04b1bc5 163 #endif
youkee 0:1ad0e04b1bc5 164 return stream;
youkee 0:1ad0e04b1bc5 165 }
youkee 0:1ad0e04b1bc5 166
youkee 0:1ad0e04b1bc5 167 /********************
youkee 0:1ad0e04b1bc5 168 * Helper functions *
youkee 0:1ad0e04b1bc5 169 ********************/
youkee 0:1ad0e04b1bc5 170
youkee 0:1ad0e04b1bc5 171 static bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest)
youkee 0:1ad0e04b1bc5 172 {
youkee 0:1ad0e04b1bc5 173 pb_byte_t byte;
youkee 0:1ad0e04b1bc5 174 uint32_t result;
youkee 0:1ad0e04b1bc5 175
youkee 0:1ad0e04b1bc5 176 if (!pb_readbyte(stream, &byte))
youkee 0:1ad0e04b1bc5 177 return false;
youkee 0:1ad0e04b1bc5 178
youkee 0:1ad0e04b1bc5 179 if ((byte & 0x80) == 0)
youkee 0:1ad0e04b1bc5 180 {
youkee 0:1ad0e04b1bc5 181 /* Quick case, 1 byte value */
youkee 0:1ad0e04b1bc5 182 result = byte;
youkee 0:1ad0e04b1bc5 183 }
youkee 0:1ad0e04b1bc5 184 else
youkee 0:1ad0e04b1bc5 185 {
youkee 0:1ad0e04b1bc5 186 /* Multibyte case */
youkee 0:1ad0e04b1bc5 187 uint_fast8_t bitpos = 7;
youkee 0:1ad0e04b1bc5 188 result = byte & 0x7F;
youkee 0:1ad0e04b1bc5 189
youkee 0:1ad0e04b1bc5 190 do
youkee 0:1ad0e04b1bc5 191 {
youkee 0:1ad0e04b1bc5 192 if (bitpos >= 32)
youkee 0:1ad0e04b1bc5 193 PB_RETURN_ERROR(stream, "varint overflow");
youkee 0:1ad0e04b1bc5 194
youkee 0:1ad0e04b1bc5 195 if (!pb_readbyte(stream, &byte))
youkee 0:1ad0e04b1bc5 196 return false;
youkee 0:1ad0e04b1bc5 197
youkee 0:1ad0e04b1bc5 198 result |= (uint32_t)(byte & 0x7F) << bitpos;
youkee 0:1ad0e04b1bc5 199 bitpos = (uint_fast8_t)(bitpos + 7);
youkee 0:1ad0e04b1bc5 200 } while (byte & 0x80);
youkee 0:1ad0e04b1bc5 201 }
youkee 0:1ad0e04b1bc5 202
youkee 0:1ad0e04b1bc5 203 *dest = result;
youkee 0:1ad0e04b1bc5 204 return true;
youkee 0:1ad0e04b1bc5 205 }
youkee 0:1ad0e04b1bc5 206
youkee 0:1ad0e04b1bc5 207 bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest)
youkee 0:1ad0e04b1bc5 208 {
youkee 0:1ad0e04b1bc5 209 pb_byte_t byte;
youkee 0:1ad0e04b1bc5 210 uint_fast8_t bitpos = 0;
youkee 0:1ad0e04b1bc5 211 uint64_t result = 0;
youkee 0:1ad0e04b1bc5 212
youkee 0:1ad0e04b1bc5 213 do
youkee 0:1ad0e04b1bc5 214 {
youkee 0:1ad0e04b1bc5 215 if (bitpos >= 64)
youkee 0:1ad0e04b1bc5 216 PB_RETURN_ERROR(stream, "varint overflow");
youkee 0:1ad0e04b1bc5 217
youkee 0:1ad0e04b1bc5 218 if (!pb_readbyte(stream, &byte))
youkee 0:1ad0e04b1bc5 219 return false;
youkee 0:1ad0e04b1bc5 220
youkee 0:1ad0e04b1bc5 221 result |= (uint64_t)(byte & 0x7F) << bitpos;
youkee 0:1ad0e04b1bc5 222 bitpos = (uint_fast8_t)(bitpos + 7);
youkee 0:1ad0e04b1bc5 223 } while (byte & 0x80);
youkee 0:1ad0e04b1bc5 224
youkee 0:1ad0e04b1bc5 225 *dest = result;
youkee 0:1ad0e04b1bc5 226 return true;
youkee 0:1ad0e04b1bc5 227 }
youkee 0:1ad0e04b1bc5 228
youkee 0:1ad0e04b1bc5 229 bool checkreturn pb_skip_varint(pb_istream_t *stream)
youkee 0:1ad0e04b1bc5 230 {
youkee 0:1ad0e04b1bc5 231 pb_byte_t byte;
youkee 0:1ad0e04b1bc5 232 do
youkee 0:1ad0e04b1bc5 233 {
youkee 0:1ad0e04b1bc5 234 if (!pb_read(stream, &byte, 1))
youkee 0:1ad0e04b1bc5 235 return false;
youkee 0:1ad0e04b1bc5 236 } while (byte & 0x80);
youkee 0:1ad0e04b1bc5 237 return true;
youkee 0:1ad0e04b1bc5 238 }
youkee 0:1ad0e04b1bc5 239
youkee 0:1ad0e04b1bc5 240 bool checkreturn pb_skip_string(pb_istream_t *stream)
youkee 0:1ad0e04b1bc5 241 {
youkee 0:1ad0e04b1bc5 242 uint32_t length;
youkee 0:1ad0e04b1bc5 243 if (!pb_decode_varint32(stream, &length))
youkee 0:1ad0e04b1bc5 244 return false;
youkee 0:1ad0e04b1bc5 245
youkee 0:1ad0e04b1bc5 246 return pb_read(stream, NULL, length);
youkee 0:1ad0e04b1bc5 247 }
youkee 0:1ad0e04b1bc5 248
youkee 0:1ad0e04b1bc5 249 bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof)
youkee 0:1ad0e04b1bc5 250 {
youkee 0:1ad0e04b1bc5 251 uint32_t temp;
youkee 0:1ad0e04b1bc5 252 *eof = false;
youkee 0:1ad0e04b1bc5 253 *wire_type = (pb_wire_type_t) 0;
youkee 0:1ad0e04b1bc5 254 *tag = 0;
youkee 0:1ad0e04b1bc5 255
youkee 0:1ad0e04b1bc5 256 if (!pb_decode_varint32(stream, &temp))
youkee 0:1ad0e04b1bc5 257 {
youkee 0:1ad0e04b1bc5 258 if (stream->bytes_left == 0)
youkee 0:1ad0e04b1bc5 259 *eof = true;
youkee 0:1ad0e04b1bc5 260
youkee 0:1ad0e04b1bc5 261 return false;
youkee 0:1ad0e04b1bc5 262 }
youkee 0:1ad0e04b1bc5 263
youkee 0:1ad0e04b1bc5 264 if (temp == 0)
youkee 0:1ad0e04b1bc5 265 {
youkee 0:1ad0e04b1bc5 266 *eof = true; /* Special feature: allow 0-terminated messages. */
youkee 0:1ad0e04b1bc5 267 return false;
youkee 0:1ad0e04b1bc5 268 }
youkee 0:1ad0e04b1bc5 269
youkee 0:1ad0e04b1bc5 270 *tag = temp >> 3;
youkee 0:1ad0e04b1bc5 271 *wire_type = (pb_wire_type_t)(temp & 7);
youkee 0:1ad0e04b1bc5 272 return true;
youkee 0:1ad0e04b1bc5 273 }
youkee 0:1ad0e04b1bc5 274
youkee 0:1ad0e04b1bc5 275 bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type)
youkee 0:1ad0e04b1bc5 276 {
youkee 0:1ad0e04b1bc5 277 switch (wire_type)
youkee 0:1ad0e04b1bc5 278 {
youkee 0:1ad0e04b1bc5 279 case PB_WT_VARINT: return pb_skip_varint(stream);
youkee 0:1ad0e04b1bc5 280 case PB_WT_64BIT: return pb_read(stream, NULL, 8);
youkee 0:1ad0e04b1bc5 281 case PB_WT_STRING: return pb_skip_string(stream);
youkee 0:1ad0e04b1bc5 282 case PB_WT_32BIT: return pb_read(stream, NULL, 4);
youkee 0:1ad0e04b1bc5 283 default: PB_RETURN_ERROR(stream, "invalid wire_type");
youkee 0:1ad0e04b1bc5 284 }
youkee 0:1ad0e04b1bc5 285 }
youkee 0:1ad0e04b1bc5 286
youkee 0:1ad0e04b1bc5 287 /* Read a raw value to buffer, for the purpose of passing it to callback as
youkee 0:1ad0e04b1bc5 288 * a substream. Size is maximum size on call, and actual size on return.
youkee 0:1ad0e04b1bc5 289 */
youkee 0:1ad0e04b1bc5 290 static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size)
youkee 0:1ad0e04b1bc5 291 {
youkee 0:1ad0e04b1bc5 292 size_t max_size = *size;
youkee 0:1ad0e04b1bc5 293 switch (wire_type)
youkee 0:1ad0e04b1bc5 294 {
youkee 0:1ad0e04b1bc5 295 case PB_WT_VARINT:
youkee 0:1ad0e04b1bc5 296 *size = 0;
youkee 0:1ad0e04b1bc5 297 do
youkee 0:1ad0e04b1bc5 298 {
youkee 0:1ad0e04b1bc5 299 (*size)++;
youkee 0:1ad0e04b1bc5 300 if (*size > max_size) return false;
youkee 0:1ad0e04b1bc5 301 if (!pb_read(stream, buf, 1)) return false;
youkee 0:1ad0e04b1bc5 302 } while (*buf++ & 0x80);
youkee 0:1ad0e04b1bc5 303 return true;
youkee 0:1ad0e04b1bc5 304
youkee 0:1ad0e04b1bc5 305 case PB_WT_64BIT:
youkee 0:1ad0e04b1bc5 306 *size = 8;
youkee 0:1ad0e04b1bc5 307 return pb_read(stream, buf, 8);
youkee 0:1ad0e04b1bc5 308
youkee 0:1ad0e04b1bc5 309 case PB_WT_32BIT:
youkee 0:1ad0e04b1bc5 310 *size = 4;
youkee 0:1ad0e04b1bc5 311 return pb_read(stream, buf, 4);
youkee 0:1ad0e04b1bc5 312
youkee 0:1ad0e04b1bc5 313 default: PB_RETURN_ERROR(stream, "invalid wire_type");
youkee 0:1ad0e04b1bc5 314 }
youkee 0:1ad0e04b1bc5 315 }
youkee 0:1ad0e04b1bc5 316
youkee 0:1ad0e04b1bc5 317 /* Decode string length from stream and return a substream with limited length.
youkee 0:1ad0e04b1bc5 318 * Remember to close the substream using pb_close_string_substream().
youkee 0:1ad0e04b1bc5 319 */
youkee 0:1ad0e04b1bc5 320 bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream)
youkee 0:1ad0e04b1bc5 321 {
youkee 0:1ad0e04b1bc5 322 uint32_t size;
youkee 0:1ad0e04b1bc5 323 if (!pb_decode_varint32(stream, &size))
youkee 0:1ad0e04b1bc5 324 return false;
youkee 0:1ad0e04b1bc5 325
youkee 0:1ad0e04b1bc5 326 *substream = *stream;
youkee 0:1ad0e04b1bc5 327 if (substream->bytes_left < size)
youkee 0:1ad0e04b1bc5 328 PB_RETURN_ERROR(stream, "parent stream too short");
youkee 0:1ad0e04b1bc5 329
youkee 0:1ad0e04b1bc5 330 substream->bytes_left = size;
youkee 0:1ad0e04b1bc5 331 stream->bytes_left -= size;
youkee 0:1ad0e04b1bc5 332 return true;
youkee 0:1ad0e04b1bc5 333 }
youkee 0:1ad0e04b1bc5 334
youkee 0:1ad0e04b1bc5 335 void pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream)
youkee 0:1ad0e04b1bc5 336 {
youkee 0:1ad0e04b1bc5 337 stream->state = substream->state;
youkee 0:1ad0e04b1bc5 338
youkee 0:1ad0e04b1bc5 339 #ifndef PB_NO_ERRMSG
youkee 0:1ad0e04b1bc5 340 stream->errmsg = substream->errmsg;
youkee 0:1ad0e04b1bc5 341 #endif
youkee 0:1ad0e04b1bc5 342 }
youkee 0:1ad0e04b1bc5 343
youkee 0:1ad0e04b1bc5 344 /*************************
youkee 0:1ad0e04b1bc5 345 * Decode a single field *
youkee 0:1ad0e04b1bc5 346 *************************/
youkee 0:1ad0e04b1bc5 347
youkee 0:1ad0e04b1bc5 348 static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter)
youkee 0:1ad0e04b1bc5 349 {
youkee 0:1ad0e04b1bc5 350 pb_type_t type;
youkee 0:1ad0e04b1bc5 351 pb_decoder_t func;
youkee 0:1ad0e04b1bc5 352
youkee 0:1ad0e04b1bc5 353 type = iter->pos->type;
youkee 0:1ad0e04b1bc5 354 func = PB_DECODERS[PB_LTYPE(type)];
youkee 0:1ad0e04b1bc5 355
youkee 0:1ad0e04b1bc5 356 switch (PB_HTYPE(type))
youkee 0:1ad0e04b1bc5 357 {
youkee 0:1ad0e04b1bc5 358 case PB_HTYPE_REQUIRED:
youkee 0:1ad0e04b1bc5 359 return func(stream, iter->pos, iter->pData);
youkee 0:1ad0e04b1bc5 360
youkee 0:1ad0e04b1bc5 361 case PB_HTYPE_OPTIONAL:
youkee 0:1ad0e04b1bc5 362 *(bool*)iter->pSize = true;
youkee 0:1ad0e04b1bc5 363 return func(stream, iter->pos, iter->pData);
youkee 0:1ad0e04b1bc5 364
youkee 0:1ad0e04b1bc5 365 case PB_HTYPE_REPEATED:
youkee 0:1ad0e04b1bc5 366 if (wire_type == PB_WT_STRING
youkee 0:1ad0e04b1bc5 367 && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE)
youkee 0:1ad0e04b1bc5 368 {
youkee 0:1ad0e04b1bc5 369 /* Packed array */
youkee 0:1ad0e04b1bc5 370 bool status = true;
youkee 0:1ad0e04b1bc5 371 pb_size_t *size = (pb_size_t*)iter->pSize;
youkee 0:1ad0e04b1bc5 372 pb_istream_t substream;
youkee 0:1ad0e04b1bc5 373 if (!pb_make_string_substream(stream, &substream))
youkee 0:1ad0e04b1bc5 374 return false;
youkee 0:1ad0e04b1bc5 375
youkee 0:1ad0e04b1bc5 376 while (substream.bytes_left > 0 && *size < iter->pos->array_size)
youkee 0:1ad0e04b1bc5 377 {
youkee 0:1ad0e04b1bc5 378 void *pItem = (char*)iter->pData + iter->pos->data_size * (*size);
youkee 0:1ad0e04b1bc5 379 if (!func(&substream, iter->pos, pItem))
youkee 0:1ad0e04b1bc5 380 {
youkee 0:1ad0e04b1bc5 381 status = false;
youkee 0:1ad0e04b1bc5 382 break;
youkee 0:1ad0e04b1bc5 383 }
youkee 0:1ad0e04b1bc5 384 (*size)++;
youkee 0:1ad0e04b1bc5 385 }
youkee 0:1ad0e04b1bc5 386 pb_close_string_substream(stream, &substream);
youkee 0:1ad0e04b1bc5 387
youkee 0:1ad0e04b1bc5 388 if (substream.bytes_left != 0)
youkee 0:1ad0e04b1bc5 389 PB_RETURN_ERROR(stream, "array overflow");
youkee 0:1ad0e04b1bc5 390
youkee 0:1ad0e04b1bc5 391 return status;
youkee 0:1ad0e04b1bc5 392 }
youkee 0:1ad0e04b1bc5 393 else
youkee 0:1ad0e04b1bc5 394 {
youkee 0:1ad0e04b1bc5 395 /* Repeated field */
youkee 0:1ad0e04b1bc5 396 pb_size_t *size = (pb_size_t*)iter->pSize;
youkee 0:1ad0e04b1bc5 397 void *pItem = (char*)iter->pData + iter->pos->data_size * (*size);
youkee 0:1ad0e04b1bc5 398 if (*size >= iter->pos->array_size)
youkee 0:1ad0e04b1bc5 399 PB_RETURN_ERROR(stream, "array overflow");
youkee 0:1ad0e04b1bc5 400
youkee 0:1ad0e04b1bc5 401 (*size)++;
youkee 0:1ad0e04b1bc5 402 return func(stream, iter->pos, pItem);
youkee 0:1ad0e04b1bc5 403 }
youkee 0:1ad0e04b1bc5 404
youkee 0:1ad0e04b1bc5 405 case PB_HTYPE_ONEOF:
youkee 0:1ad0e04b1bc5 406 *(pb_size_t*)iter->pSize = iter->pos->tag;
youkee 0:1ad0e04b1bc5 407 if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE)
youkee 0:1ad0e04b1bc5 408 {
youkee 0:1ad0e04b1bc5 409 /* We memset to zero so that any callbacks are set to NULL.
youkee 0:1ad0e04b1bc5 410 * Then set any default values. */
youkee 0:1ad0e04b1bc5 411 memset(iter->pData, 0, iter->pos->data_size);
youkee 0:1ad0e04b1bc5 412 pb_message_set_to_defaults((const pb_field_t*)iter->pos->ptr, iter->pData);
youkee 0:1ad0e04b1bc5 413 }
youkee 0:1ad0e04b1bc5 414 return func(stream, iter->pos, iter->pData);
youkee 0:1ad0e04b1bc5 415
youkee 0:1ad0e04b1bc5 416 default:
youkee 0:1ad0e04b1bc5 417 PB_RETURN_ERROR(stream, "invalid field type");
youkee 0:1ad0e04b1bc5 418 }
youkee 0:1ad0e04b1bc5 419 }
youkee 0:1ad0e04b1bc5 420
youkee 0:1ad0e04b1bc5 421 #ifdef PB_ENABLE_MALLOC
youkee 0:1ad0e04b1bc5 422 /* Allocate storage for the field and store the pointer at iter->pData.
youkee 0:1ad0e04b1bc5 423 * array_size is the number of entries to reserve in an array.
youkee 0:1ad0e04b1bc5 424 * Zero size is not allowed, use pb_free() for releasing.
youkee 0:1ad0e04b1bc5 425 */
youkee 0:1ad0e04b1bc5 426 static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size)
youkee 0:1ad0e04b1bc5 427 {
youkee 0:1ad0e04b1bc5 428 void *ptr = *(void**)pData;
youkee 0:1ad0e04b1bc5 429
youkee 0:1ad0e04b1bc5 430 if (data_size == 0 || array_size == 0)
youkee 0:1ad0e04b1bc5 431 PB_RETURN_ERROR(stream, "invalid size");
youkee 0:1ad0e04b1bc5 432
youkee 0:1ad0e04b1bc5 433 /* Check for multiplication overflows.
youkee 0:1ad0e04b1bc5 434 * This code avoids the costly division if the sizes are small enough.
youkee 0:1ad0e04b1bc5 435 * Multiplication is safe as long as only half of bits are set
youkee 0:1ad0e04b1bc5 436 * in either multiplicand.
youkee 0:1ad0e04b1bc5 437 */
youkee 0:1ad0e04b1bc5 438 {
youkee 0:1ad0e04b1bc5 439 const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4);
youkee 0:1ad0e04b1bc5 440 if (data_size >= check_limit || array_size >= check_limit)
youkee 0:1ad0e04b1bc5 441 {
youkee 0:1ad0e04b1bc5 442 const size_t size_max = (size_t)-1;
youkee 0:1ad0e04b1bc5 443 if (size_max / array_size < data_size)
youkee 0:1ad0e04b1bc5 444 {
youkee 0:1ad0e04b1bc5 445 PB_RETURN_ERROR(stream, "size too large");
youkee 0:1ad0e04b1bc5 446 }
youkee 0:1ad0e04b1bc5 447 }
youkee 0:1ad0e04b1bc5 448 }
youkee 0:1ad0e04b1bc5 449
youkee 0:1ad0e04b1bc5 450 /* Allocate new or expand previous allocation */
youkee 0:1ad0e04b1bc5 451 /* Note: on failure the old pointer will remain in the structure,
youkee 0:1ad0e04b1bc5 452 * the message must be freed by caller also on error return. */
youkee 0:1ad0e04b1bc5 453 ptr = pb_realloc(ptr, array_size * data_size);
youkee 0:1ad0e04b1bc5 454 if (ptr == NULL)
youkee 0:1ad0e04b1bc5 455 PB_RETURN_ERROR(stream, "realloc failed");
youkee 0:1ad0e04b1bc5 456
youkee 0:1ad0e04b1bc5 457 *(void**)pData = ptr;
youkee 0:1ad0e04b1bc5 458 return true;
youkee 0:1ad0e04b1bc5 459 }
youkee 0:1ad0e04b1bc5 460
youkee 0:1ad0e04b1bc5 461 /* Clear a newly allocated item in case it contains a pointer, or is a submessage. */
youkee 0:1ad0e04b1bc5 462 static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter)
youkee 0:1ad0e04b1bc5 463 {
youkee 0:1ad0e04b1bc5 464 if (PB_LTYPE(iter->pos->type) == PB_LTYPE_STRING ||
youkee 0:1ad0e04b1bc5 465 PB_LTYPE(iter->pos->type) == PB_LTYPE_BYTES)
youkee 0:1ad0e04b1bc5 466 {
youkee 0:1ad0e04b1bc5 467 *(void**)pItem = NULL;
youkee 0:1ad0e04b1bc5 468 }
youkee 0:1ad0e04b1bc5 469 else if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE)
youkee 0:1ad0e04b1bc5 470 {
youkee 0:1ad0e04b1bc5 471 pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, pItem);
youkee 0:1ad0e04b1bc5 472 }
youkee 0:1ad0e04b1bc5 473 }
youkee 0:1ad0e04b1bc5 474 #endif
youkee 0:1ad0e04b1bc5 475
youkee 0:1ad0e04b1bc5 476 static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter)
youkee 0:1ad0e04b1bc5 477 {
youkee 0:1ad0e04b1bc5 478 #ifndef PB_ENABLE_MALLOC
youkee 0:1ad0e04b1bc5 479 PB_UNUSED(wire_type);
youkee 0:1ad0e04b1bc5 480 PB_UNUSED(iter);
youkee 0:1ad0e04b1bc5 481 PB_RETURN_ERROR(stream, "no malloc support");
youkee 0:1ad0e04b1bc5 482 #else
youkee 0:1ad0e04b1bc5 483 pb_type_t type;
youkee 0:1ad0e04b1bc5 484 pb_decoder_t func;
youkee 0:1ad0e04b1bc5 485
youkee 0:1ad0e04b1bc5 486 type = iter->pos->type;
youkee 0:1ad0e04b1bc5 487 func = PB_DECODERS[PB_LTYPE(type)];
youkee 0:1ad0e04b1bc5 488
youkee 0:1ad0e04b1bc5 489 switch (PB_HTYPE(type))
youkee 0:1ad0e04b1bc5 490 {
youkee 0:1ad0e04b1bc5 491 case PB_HTYPE_REQUIRED:
youkee 0:1ad0e04b1bc5 492 case PB_HTYPE_OPTIONAL:
youkee 0:1ad0e04b1bc5 493 case PB_HTYPE_ONEOF:
youkee 0:1ad0e04b1bc5 494 if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE &&
youkee 0:1ad0e04b1bc5 495 *(void**)iter->pData != NULL)
youkee 0:1ad0e04b1bc5 496 {
youkee 0:1ad0e04b1bc5 497 /* Duplicate field, have to release the old allocation first. */
youkee 0:1ad0e04b1bc5 498 pb_release_single_field(iter);
youkee 0:1ad0e04b1bc5 499 }
youkee 0:1ad0e04b1bc5 500
youkee 0:1ad0e04b1bc5 501 if (PB_HTYPE(type) == PB_HTYPE_ONEOF)
youkee 0:1ad0e04b1bc5 502 {
youkee 0:1ad0e04b1bc5 503 *(pb_size_t*)iter->pSize = iter->pos->tag;
youkee 0:1ad0e04b1bc5 504 }
youkee 0:1ad0e04b1bc5 505
youkee 0:1ad0e04b1bc5 506 if (PB_LTYPE(type) == PB_LTYPE_STRING ||
youkee 0:1ad0e04b1bc5 507 PB_LTYPE(type) == PB_LTYPE_BYTES)
youkee 0:1ad0e04b1bc5 508 {
youkee 0:1ad0e04b1bc5 509 return func(stream, iter->pos, iter->pData);
youkee 0:1ad0e04b1bc5 510 }
youkee 0:1ad0e04b1bc5 511 else
youkee 0:1ad0e04b1bc5 512 {
youkee 0:1ad0e04b1bc5 513 if (!allocate_field(stream, iter->pData, iter->pos->data_size, 1))
youkee 0:1ad0e04b1bc5 514 return false;
youkee 0:1ad0e04b1bc5 515
youkee 0:1ad0e04b1bc5 516 initialize_pointer_field(*(void**)iter->pData, iter);
youkee 0:1ad0e04b1bc5 517 return func(stream, iter->pos, *(void**)iter->pData);
youkee 0:1ad0e04b1bc5 518 }
youkee 0:1ad0e04b1bc5 519
youkee 0:1ad0e04b1bc5 520 case PB_HTYPE_REPEATED:
youkee 0:1ad0e04b1bc5 521 if (wire_type == PB_WT_STRING
youkee 0:1ad0e04b1bc5 522 && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE)
youkee 0:1ad0e04b1bc5 523 {
youkee 0:1ad0e04b1bc5 524 /* Packed array, multiple items come in at once. */
youkee 0:1ad0e04b1bc5 525 bool status = true;
youkee 0:1ad0e04b1bc5 526 pb_size_t *size = (pb_size_t*)iter->pSize;
youkee 0:1ad0e04b1bc5 527 size_t allocated_size = *size;
youkee 0:1ad0e04b1bc5 528 void *pItem;
youkee 0:1ad0e04b1bc5 529 pb_istream_t substream;
youkee 0:1ad0e04b1bc5 530
youkee 0:1ad0e04b1bc5 531 if (!pb_make_string_substream(stream, &substream))
youkee 0:1ad0e04b1bc5 532 return false;
youkee 0:1ad0e04b1bc5 533
youkee 0:1ad0e04b1bc5 534 while (substream.bytes_left)
youkee 0:1ad0e04b1bc5 535 {
youkee 0:1ad0e04b1bc5 536 if ((size_t)*size + 1 > allocated_size)
youkee 0:1ad0e04b1bc5 537 {
youkee 0:1ad0e04b1bc5 538 /* Allocate more storage. This tries to guess the
youkee 0:1ad0e04b1bc5 539 * number of remaining entries. Round the division
youkee 0:1ad0e04b1bc5 540 * upwards. */
youkee 0:1ad0e04b1bc5 541 allocated_size += (substream.bytes_left - 1) / iter->pos->data_size + 1;
youkee 0:1ad0e04b1bc5 542
youkee 0:1ad0e04b1bc5 543 if (!allocate_field(&substream, iter->pData, iter->pos->data_size, allocated_size))
youkee 0:1ad0e04b1bc5 544 {
youkee 0:1ad0e04b1bc5 545 status = false;
youkee 0:1ad0e04b1bc5 546 break;
youkee 0:1ad0e04b1bc5 547 }
youkee 0:1ad0e04b1bc5 548 }
youkee 0:1ad0e04b1bc5 549
youkee 0:1ad0e04b1bc5 550 /* Decode the array entry */
youkee 0:1ad0e04b1bc5 551 pItem = *(char**)iter->pData + iter->pos->data_size * (*size);
youkee 0:1ad0e04b1bc5 552 initialize_pointer_field(pItem, iter);
youkee 0:1ad0e04b1bc5 553 if (!func(&substream, iter->pos, pItem))
youkee 0:1ad0e04b1bc5 554 {
youkee 0:1ad0e04b1bc5 555 status = false;
youkee 0:1ad0e04b1bc5 556 break;
youkee 0:1ad0e04b1bc5 557 }
youkee 0:1ad0e04b1bc5 558
youkee 0:1ad0e04b1bc5 559 if (*size == PB_SIZE_MAX)
youkee 0:1ad0e04b1bc5 560 {
youkee 0:1ad0e04b1bc5 561 #ifndef PB_NO_ERRMSG
youkee 0:1ad0e04b1bc5 562 stream->errmsg = "too many array entries";
youkee 0:1ad0e04b1bc5 563 #endif
youkee 0:1ad0e04b1bc5 564 status = false;
youkee 0:1ad0e04b1bc5 565 break;
youkee 0:1ad0e04b1bc5 566 }
youkee 0:1ad0e04b1bc5 567
youkee 0:1ad0e04b1bc5 568 (*size)++;
youkee 0:1ad0e04b1bc5 569 }
youkee 0:1ad0e04b1bc5 570 pb_close_string_substream(stream, &substream);
youkee 0:1ad0e04b1bc5 571
youkee 0:1ad0e04b1bc5 572 return status;
youkee 0:1ad0e04b1bc5 573 }
youkee 0:1ad0e04b1bc5 574 else
youkee 0:1ad0e04b1bc5 575 {
youkee 0:1ad0e04b1bc5 576 /* Normal repeated field, i.e. only one item at a time. */
youkee 0:1ad0e04b1bc5 577 pb_size_t *size = (pb_size_t*)iter->pSize;
youkee 0:1ad0e04b1bc5 578 void *pItem;
youkee 0:1ad0e04b1bc5 579
youkee 0:1ad0e04b1bc5 580 if (*size == PB_SIZE_MAX)
youkee 0:1ad0e04b1bc5 581 PB_RETURN_ERROR(stream, "too many array entries");
youkee 0:1ad0e04b1bc5 582
youkee 0:1ad0e04b1bc5 583 (*size)++;
youkee 0:1ad0e04b1bc5 584 if (!allocate_field(stream, iter->pData, iter->pos->data_size, *size))
youkee 0:1ad0e04b1bc5 585 return false;
youkee 0:1ad0e04b1bc5 586
youkee 0:1ad0e04b1bc5 587 pItem = *(char**)iter->pData + iter->pos->data_size * (*size - 1);
youkee 0:1ad0e04b1bc5 588 initialize_pointer_field(pItem, iter);
youkee 0:1ad0e04b1bc5 589 return func(stream, iter->pos, pItem);
youkee 0:1ad0e04b1bc5 590 }
youkee 0:1ad0e04b1bc5 591
youkee 0:1ad0e04b1bc5 592 default:
youkee 0:1ad0e04b1bc5 593 PB_RETURN_ERROR(stream, "invalid field type");
youkee 0:1ad0e04b1bc5 594 }
youkee 0:1ad0e04b1bc5 595 #endif
youkee 0:1ad0e04b1bc5 596 }
youkee 0:1ad0e04b1bc5 597
youkee 0:1ad0e04b1bc5 598 static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter)
youkee 0:1ad0e04b1bc5 599 {
youkee 0:1ad0e04b1bc5 600 pb_callback_t *pCallback = (pb_callback_t*)iter->pData;
youkee 0:1ad0e04b1bc5 601
youkee 0:1ad0e04b1bc5 602 #ifdef PB_OLD_CALLBACK_STYLE
youkee 0:1ad0e04b1bc5 603 void *arg = pCallback->arg;
youkee 0:1ad0e04b1bc5 604 #else
youkee 0:1ad0e04b1bc5 605 void **arg = &(pCallback->arg);
youkee 0:1ad0e04b1bc5 606 #endif
youkee 0:1ad0e04b1bc5 607
youkee 0:1ad0e04b1bc5 608 if (pCallback->funcs.decode == NULL)
youkee 0:1ad0e04b1bc5 609 return pb_skip_field(stream, wire_type);
youkee 0:1ad0e04b1bc5 610
youkee 0:1ad0e04b1bc5 611 if (wire_type == PB_WT_STRING)
youkee 0:1ad0e04b1bc5 612 {
youkee 0:1ad0e04b1bc5 613 pb_istream_t substream;
youkee 0:1ad0e04b1bc5 614
youkee 0:1ad0e04b1bc5 615 if (!pb_make_string_substream(stream, &substream))
youkee 0:1ad0e04b1bc5 616 return false;
youkee 0:1ad0e04b1bc5 617
youkee 0:1ad0e04b1bc5 618 do
youkee 0:1ad0e04b1bc5 619 {
youkee 0:1ad0e04b1bc5 620 if (!pCallback->funcs.decode(&substream, iter->pos, arg))
youkee 0:1ad0e04b1bc5 621 PB_RETURN_ERROR(stream, "callback failed");
youkee 0:1ad0e04b1bc5 622 } while (substream.bytes_left);
youkee 0:1ad0e04b1bc5 623
youkee 0:1ad0e04b1bc5 624 pb_close_string_substream(stream, &substream);
youkee 0:1ad0e04b1bc5 625 return true;
youkee 0:1ad0e04b1bc5 626 }
youkee 0:1ad0e04b1bc5 627 else
youkee 0:1ad0e04b1bc5 628 {
youkee 0:1ad0e04b1bc5 629 /* Copy the single scalar value to stack.
youkee 0:1ad0e04b1bc5 630 * This is required so that we can limit the stream length,
youkee 0:1ad0e04b1bc5 631 * which in turn allows to use same callback for packed and
youkee 0:1ad0e04b1bc5 632 * not-packed fields. */
youkee 0:1ad0e04b1bc5 633 pb_istream_t substream;
youkee 0:1ad0e04b1bc5 634 pb_byte_t buffer[10];
youkee 0:1ad0e04b1bc5 635 size_t size = sizeof(buffer);
youkee 0:1ad0e04b1bc5 636
youkee 0:1ad0e04b1bc5 637 if (!read_raw_value(stream, wire_type, buffer, &size))
youkee 0:1ad0e04b1bc5 638 return false;
youkee 0:1ad0e04b1bc5 639 substream = pb_istream_from_buffer(buffer, size);
youkee 0:1ad0e04b1bc5 640
youkee 0:1ad0e04b1bc5 641 return pCallback->funcs.decode(&substream, iter->pos, arg);
youkee 0:1ad0e04b1bc5 642 }
youkee 0:1ad0e04b1bc5 643 }
youkee 0:1ad0e04b1bc5 644
youkee 0:1ad0e04b1bc5 645 static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter)
youkee 0:1ad0e04b1bc5 646 {
youkee 0:1ad0e04b1bc5 647 #ifdef PB_ENABLE_MALLOC
youkee 0:1ad0e04b1bc5 648 /* When decoding an oneof field, check if there is old data that must be
youkee 0:1ad0e04b1bc5 649 * released first. */
youkee 0:1ad0e04b1bc5 650 if (PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF)
youkee 0:1ad0e04b1bc5 651 {
youkee 0:1ad0e04b1bc5 652 if (!pb_release_union_field(stream, iter))
youkee 0:1ad0e04b1bc5 653 return false;
youkee 0:1ad0e04b1bc5 654 }
youkee 0:1ad0e04b1bc5 655 #endif
youkee 0:1ad0e04b1bc5 656
youkee 0:1ad0e04b1bc5 657 switch (PB_ATYPE(iter->pos->type))
youkee 0:1ad0e04b1bc5 658 {
youkee 0:1ad0e04b1bc5 659 case PB_ATYPE_STATIC:
youkee 0:1ad0e04b1bc5 660 return decode_static_field(stream, wire_type, iter);
youkee 0:1ad0e04b1bc5 661
youkee 0:1ad0e04b1bc5 662 case PB_ATYPE_POINTER:
youkee 0:1ad0e04b1bc5 663 return decode_pointer_field(stream, wire_type, iter);
youkee 0:1ad0e04b1bc5 664
youkee 0:1ad0e04b1bc5 665 case PB_ATYPE_CALLBACK:
youkee 0:1ad0e04b1bc5 666 return decode_callback_field(stream, wire_type, iter);
youkee 0:1ad0e04b1bc5 667
youkee 0:1ad0e04b1bc5 668 default:
youkee 0:1ad0e04b1bc5 669 PB_RETURN_ERROR(stream, "invalid field type");
youkee 0:1ad0e04b1bc5 670 }
youkee 0:1ad0e04b1bc5 671 }
youkee 0:1ad0e04b1bc5 672
youkee 0:1ad0e04b1bc5 673 static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension)
youkee 0:1ad0e04b1bc5 674 {
youkee 0:1ad0e04b1bc5 675 /* Fake a field iterator for the extension field.
youkee 0:1ad0e04b1bc5 676 * It is not actually safe to advance this iterator, but decode_field
youkee 0:1ad0e04b1bc5 677 * will not even try to. */
youkee 0:1ad0e04b1bc5 678 const pb_field_t *field = (const pb_field_t*)extension->type->arg;
youkee 0:1ad0e04b1bc5 679 (void)pb_field_iter_begin(iter, field, extension->dest);
youkee 0:1ad0e04b1bc5 680 iter->pData = extension->dest;
youkee 0:1ad0e04b1bc5 681 iter->pSize = &extension->found;
youkee 0:1ad0e04b1bc5 682
youkee 0:1ad0e04b1bc5 683 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
youkee 0:1ad0e04b1bc5 684 {
youkee 0:1ad0e04b1bc5 685 /* For pointer extensions, the pointer is stored directly
youkee 0:1ad0e04b1bc5 686 * in the extension structure. This avoids having an extra
youkee 0:1ad0e04b1bc5 687 * indirection. */
youkee 0:1ad0e04b1bc5 688 iter->pData = &extension->dest;
youkee 0:1ad0e04b1bc5 689 }
youkee 0:1ad0e04b1bc5 690 }
youkee 0:1ad0e04b1bc5 691
youkee 0:1ad0e04b1bc5 692 /* Default handler for extension fields. Expects a pb_field_t structure
youkee 0:1ad0e04b1bc5 693 * in extension->type->arg. */
youkee 0:1ad0e04b1bc5 694 static bool checkreturn default_extension_decoder(pb_istream_t *stream,
youkee 0:1ad0e04b1bc5 695 pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type)
youkee 0:1ad0e04b1bc5 696 {
youkee 0:1ad0e04b1bc5 697 const pb_field_t *field = (const pb_field_t*)extension->type->arg;
youkee 0:1ad0e04b1bc5 698 pb_field_iter_t iter;
youkee 0:1ad0e04b1bc5 699
youkee 0:1ad0e04b1bc5 700 if (field->tag != tag)
youkee 0:1ad0e04b1bc5 701 return true;
youkee 0:1ad0e04b1bc5 702
youkee 0:1ad0e04b1bc5 703 iter_from_extension(&iter, extension);
youkee 0:1ad0e04b1bc5 704 extension->found = true;
youkee 0:1ad0e04b1bc5 705 return decode_field(stream, wire_type, &iter);
youkee 0:1ad0e04b1bc5 706 }
youkee 0:1ad0e04b1bc5 707
youkee 0:1ad0e04b1bc5 708 /* Try to decode an unknown field as an extension field. Tries each extension
youkee 0:1ad0e04b1bc5 709 * decoder in turn, until one of them handles the field or loop ends. */
youkee 0:1ad0e04b1bc5 710 static bool checkreturn decode_extension(pb_istream_t *stream,
youkee 0:1ad0e04b1bc5 711 uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter)
youkee 0:1ad0e04b1bc5 712 {
youkee 0:1ad0e04b1bc5 713 pb_extension_t *extension = *(pb_extension_t* const *)iter->pData;
youkee 0:1ad0e04b1bc5 714 size_t pos = stream->bytes_left;
youkee 0:1ad0e04b1bc5 715
youkee 0:1ad0e04b1bc5 716 while (extension != NULL && pos == stream->bytes_left)
youkee 0:1ad0e04b1bc5 717 {
youkee 0:1ad0e04b1bc5 718 bool status;
youkee 0:1ad0e04b1bc5 719 if (extension->type->decode)
youkee 0:1ad0e04b1bc5 720 status = extension->type->decode(stream, extension, tag, wire_type);
youkee 0:1ad0e04b1bc5 721 else
youkee 0:1ad0e04b1bc5 722 status = default_extension_decoder(stream, extension, tag, wire_type);
youkee 0:1ad0e04b1bc5 723
youkee 0:1ad0e04b1bc5 724 if (!status)
youkee 0:1ad0e04b1bc5 725 return false;
youkee 0:1ad0e04b1bc5 726
youkee 0:1ad0e04b1bc5 727 extension = extension->next;
youkee 0:1ad0e04b1bc5 728 }
youkee 0:1ad0e04b1bc5 729
youkee 0:1ad0e04b1bc5 730 return true;
youkee 0:1ad0e04b1bc5 731 }
youkee 0:1ad0e04b1bc5 732
youkee 0:1ad0e04b1bc5 733 /* Step through the iterator until an extension field is found or until all
youkee 0:1ad0e04b1bc5 734 * entries have been checked. There can be only one extension field per
youkee 0:1ad0e04b1bc5 735 * message. Returns false if no extension field is found. */
youkee 0:1ad0e04b1bc5 736 static bool checkreturn find_extension_field(pb_field_iter_t *iter)
youkee 0:1ad0e04b1bc5 737 {
youkee 0:1ad0e04b1bc5 738 const pb_field_t *start = iter->pos;
youkee 0:1ad0e04b1bc5 739
youkee 0:1ad0e04b1bc5 740 do {
youkee 0:1ad0e04b1bc5 741 if (PB_LTYPE(iter->pos->type) == PB_LTYPE_EXTENSION)
youkee 0:1ad0e04b1bc5 742 return true;
youkee 0:1ad0e04b1bc5 743 (void)pb_field_iter_next(iter);
youkee 0:1ad0e04b1bc5 744 } while (iter->pos != start);
youkee 0:1ad0e04b1bc5 745
youkee 0:1ad0e04b1bc5 746 return false;
youkee 0:1ad0e04b1bc5 747 }
youkee 0:1ad0e04b1bc5 748
youkee 0:1ad0e04b1bc5 749 /* Initialize message fields to default values, recursively */
youkee 0:1ad0e04b1bc5 750 static void pb_field_set_to_default(pb_field_iter_t *iter)
youkee 0:1ad0e04b1bc5 751 {
youkee 0:1ad0e04b1bc5 752 pb_type_t type;
youkee 0:1ad0e04b1bc5 753 type = iter->pos->type;
youkee 0:1ad0e04b1bc5 754
youkee 0:1ad0e04b1bc5 755 if (PB_LTYPE(type) == PB_LTYPE_EXTENSION)
youkee 0:1ad0e04b1bc5 756 {
youkee 0:1ad0e04b1bc5 757 pb_extension_t *ext = *(pb_extension_t* const *)iter->pData;
youkee 0:1ad0e04b1bc5 758 while (ext != NULL)
youkee 0:1ad0e04b1bc5 759 {
youkee 0:1ad0e04b1bc5 760 pb_field_iter_t ext_iter;
youkee 0:1ad0e04b1bc5 761 ext->found = false;
youkee 0:1ad0e04b1bc5 762 iter_from_extension(&ext_iter, ext);
youkee 0:1ad0e04b1bc5 763 pb_field_set_to_default(&ext_iter);
youkee 0:1ad0e04b1bc5 764 ext = ext->next;
youkee 0:1ad0e04b1bc5 765 }
youkee 0:1ad0e04b1bc5 766 }
youkee 0:1ad0e04b1bc5 767 else if (PB_ATYPE(type) == PB_ATYPE_STATIC)
youkee 0:1ad0e04b1bc5 768 {
youkee 0:1ad0e04b1bc5 769 bool init_data = true;
youkee 0:1ad0e04b1bc5 770 if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL)
youkee 0:1ad0e04b1bc5 771 {
youkee 0:1ad0e04b1bc5 772 /* Set has_field to false. Still initialize the optional field
youkee 0:1ad0e04b1bc5 773 * itself also. */
youkee 0:1ad0e04b1bc5 774 *(bool*)iter->pSize = false;
youkee 0:1ad0e04b1bc5 775 }
youkee 0:1ad0e04b1bc5 776 else if (PB_HTYPE(type) == PB_HTYPE_REPEATED ||
youkee 0:1ad0e04b1bc5 777 PB_HTYPE(type) == PB_HTYPE_ONEOF)
youkee 0:1ad0e04b1bc5 778 {
youkee 0:1ad0e04b1bc5 779 /* REPEATED: Set array count to 0, no need to initialize contents.
youkee 0:1ad0e04b1bc5 780 ONEOF: Set which_field to 0. */
youkee 0:1ad0e04b1bc5 781 *(pb_size_t*)iter->pSize = 0;
youkee 0:1ad0e04b1bc5 782 init_data = false;
youkee 0:1ad0e04b1bc5 783 }
youkee 0:1ad0e04b1bc5 784
youkee 0:1ad0e04b1bc5 785 if (init_data)
youkee 0:1ad0e04b1bc5 786 {
youkee 0:1ad0e04b1bc5 787 if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE)
youkee 0:1ad0e04b1bc5 788 {
youkee 0:1ad0e04b1bc5 789 /* Initialize submessage to defaults */
youkee 0:1ad0e04b1bc5 790 pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, iter->pData);
youkee 0:1ad0e04b1bc5 791 }
youkee 0:1ad0e04b1bc5 792 else if (iter->pos->ptr != NULL)
youkee 0:1ad0e04b1bc5 793 {
youkee 0:1ad0e04b1bc5 794 /* Initialize to default value */
youkee 0:1ad0e04b1bc5 795 memcpy(iter->pData, iter->pos->ptr, iter->pos->data_size);
youkee 0:1ad0e04b1bc5 796 }
youkee 0:1ad0e04b1bc5 797 else
youkee 0:1ad0e04b1bc5 798 {
youkee 0:1ad0e04b1bc5 799 /* Initialize to zeros */
youkee 0:1ad0e04b1bc5 800 memset(iter->pData, 0, iter->pos->data_size);
youkee 0:1ad0e04b1bc5 801 }
youkee 0:1ad0e04b1bc5 802 }
youkee 0:1ad0e04b1bc5 803 }
youkee 0:1ad0e04b1bc5 804 else if (PB_ATYPE(type) == PB_ATYPE_POINTER)
youkee 0:1ad0e04b1bc5 805 {
youkee 0:1ad0e04b1bc5 806 /* Initialize the pointer to NULL. */
youkee 0:1ad0e04b1bc5 807 *(void**)iter->pData = NULL;
youkee 0:1ad0e04b1bc5 808
youkee 0:1ad0e04b1bc5 809 /* Initialize array count to 0. */
youkee 0:1ad0e04b1bc5 810 if (PB_HTYPE(type) == PB_HTYPE_REPEATED ||
youkee 0:1ad0e04b1bc5 811 PB_HTYPE(type) == PB_HTYPE_ONEOF)
youkee 0:1ad0e04b1bc5 812 {
youkee 0:1ad0e04b1bc5 813 *(pb_size_t*)iter->pSize = 0;
youkee 0:1ad0e04b1bc5 814 }
youkee 0:1ad0e04b1bc5 815 }
youkee 0:1ad0e04b1bc5 816 else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK)
youkee 0:1ad0e04b1bc5 817 {
youkee 0:1ad0e04b1bc5 818 /* Don't overwrite callback */
youkee 0:1ad0e04b1bc5 819 }
youkee 0:1ad0e04b1bc5 820 }
youkee 0:1ad0e04b1bc5 821
youkee 0:1ad0e04b1bc5 822 static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct)
youkee 0:1ad0e04b1bc5 823 {
youkee 0:1ad0e04b1bc5 824 pb_field_iter_t iter;
youkee 0:1ad0e04b1bc5 825
youkee 0:1ad0e04b1bc5 826 if (!pb_field_iter_begin(&iter, fields, dest_struct))
youkee 0:1ad0e04b1bc5 827 return; /* Empty message type */
youkee 0:1ad0e04b1bc5 828
youkee 0:1ad0e04b1bc5 829 do
youkee 0:1ad0e04b1bc5 830 {
youkee 0:1ad0e04b1bc5 831 pb_field_set_to_default(&iter);
youkee 0:1ad0e04b1bc5 832 } while (pb_field_iter_next(&iter));
youkee 0:1ad0e04b1bc5 833 }
youkee 0:1ad0e04b1bc5 834
youkee 0:1ad0e04b1bc5 835 /*********************
youkee 0:1ad0e04b1bc5 836 * Decode all fields *
youkee 0:1ad0e04b1bc5 837 *********************/
youkee 0:1ad0e04b1bc5 838
youkee 0:1ad0e04b1bc5 839 bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
youkee 0:1ad0e04b1bc5 840 {
youkee 0:1ad0e04b1bc5 841 uint32_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 31) / 32] = {0, 0};
youkee 0:1ad0e04b1bc5 842 const uint32_t allbits = ~(uint32_t)0;
youkee 0:1ad0e04b1bc5 843 uint32_t extension_range_start = 0;
youkee 0:1ad0e04b1bc5 844 pb_field_iter_t iter;
youkee 0:1ad0e04b1bc5 845
youkee 0:1ad0e04b1bc5 846 /* Return value ignored, as empty message types will be correctly handled by
youkee 0:1ad0e04b1bc5 847 * pb_field_iter_find() anyway. */
youkee 0:1ad0e04b1bc5 848 (void)pb_field_iter_begin(&iter, fields, dest_struct);
youkee 0:1ad0e04b1bc5 849
youkee 0:1ad0e04b1bc5 850 while (stream->bytes_left)
youkee 0:1ad0e04b1bc5 851 {
youkee 0:1ad0e04b1bc5 852 uint32_t tag;
youkee 0:1ad0e04b1bc5 853 pb_wire_type_t wire_type;
youkee 0:1ad0e04b1bc5 854 bool eof;
youkee 0:1ad0e04b1bc5 855
youkee 0:1ad0e04b1bc5 856 if (!pb_decode_tag(stream, &wire_type, &tag, &eof))
youkee 0:1ad0e04b1bc5 857 {
youkee 0:1ad0e04b1bc5 858 if (eof)
youkee 0:1ad0e04b1bc5 859 break;
youkee 0:1ad0e04b1bc5 860 else
youkee 0:1ad0e04b1bc5 861 return false;
youkee 0:1ad0e04b1bc5 862 }
youkee 0:1ad0e04b1bc5 863
youkee 0:1ad0e04b1bc5 864 if (!pb_field_iter_find(&iter, tag))
youkee 0:1ad0e04b1bc5 865 {
youkee 0:1ad0e04b1bc5 866 /* No match found, check if it matches an extension. */
youkee 0:1ad0e04b1bc5 867 if (tag >= extension_range_start)
youkee 0:1ad0e04b1bc5 868 {
youkee 0:1ad0e04b1bc5 869 if (!find_extension_field(&iter))
youkee 0:1ad0e04b1bc5 870 extension_range_start = (uint32_t)-1;
youkee 0:1ad0e04b1bc5 871 else
youkee 0:1ad0e04b1bc5 872 extension_range_start = iter.pos->tag;
youkee 0:1ad0e04b1bc5 873
youkee 0:1ad0e04b1bc5 874 if (tag >= extension_range_start)
youkee 0:1ad0e04b1bc5 875 {
youkee 0:1ad0e04b1bc5 876 size_t pos = stream->bytes_left;
youkee 0:1ad0e04b1bc5 877
youkee 0:1ad0e04b1bc5 878 if (!decode_extension(stream, tag, wire_type, &iter))
youkee 0:1ad0e04b1bc5 879 return false;
youkee 0:1ad0e04b1bc5 880
youkee 0:1ad0e04b1bc5 881 if (pos != stream->bytes_left)
youkee 0:1ad0e04b1bc5 882 {
youkee 0:1ad0e04b1bc5 883 /* The field was handled */
youkee 0:1ad0e04b1bc5 884 continue;
youkee 0:1ad0e04b1bc5 885 }
youkee 0:1ad0e04b1bc5 886 }
youkee 0:1ad0e04b1bc5 887 }
youkee 0:1ad0e04b1bc5 888
youkee 0:1ad0e04b1bc5 889 /* No match found, skip data */
youkee 0:1ad0e04b1bc5 890 if (!pb_skip_field(stream, wire_type))
youkee 0:1ad0e04b1bc5 891 return false;
youkee 0:1ad0e04b1bc5 892 continue;
youkee 0:1ad0e04b1bc5 893 }
youkee 0:1ad0e04b1bc5 894
youkee 0:1ad0e04b1bc5 895 if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REQUIRED
youkee 0:1ad0e04b1bc5 896 && iter.required_field_index < PB_MAX_REQUIRED_FIELDS)
youkee 0:1ad0e04b1bc5 897 {
youkee 0:1ad0e04b1bc5 898 uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31));
youkee 0:1ad0e04b1bc5 899 fields_seen[iter.required_field_index >> 5] |= tmp;
youkee 0:1ad0e04b1bc5 900 }
youkee 0:1ad0e04b1bc5 901
youkee 0:1ad0e04b1bc5 902 if (!decode_field(stream, wire_type, &iter))
youkee 0:1ad0e04b1bc5 903 return false;
youkee 0:1ad0e04b1bc5 904 }
youkee 0:1ad0e04b1bc5 905
youkee 0:1ad0e04b1bc5 906 /* Check that all required fields were present. */
youkee 0:1ad0e04b1bc5 907 {
youkee 0:1ad0e04b1bc5 908 /* First figure out the number of required fields by
youkee 0:1ad0e04b1bc5 909 * seeking to the end of the field array. Usually we
youkee 0:1ad0e04b1bc5 910 * are already close to end after decoding.
youkee 0:1ad0e04b1bc5 911 */
youkee 0:1ad0e04b1bc5 912 unsigned req_field_count;
youkee 0:1ad0e04b1bc5 913 pb_type_t last_type;
youkee 0:1ad0e04b1bc5 914 unsigned i;
youkee 0:1ad0e04b1bc5 915 do {
youkee 0:1ad0e04b1bc5 916 req_field_count = iter.required_field_index;
youkee 0:1ad0e04b1bc5 917 last_type = iter.pos->type;
youkee 0:1ad0e04b1bc5 918 } while (pb_field_iter_next(&iter));
youkee 0:1ad0e04b1bc5 919
youkee 0:1ad0e04b1bc5 920 /* Fixup if last field was also required. */
youkee 0:1ad0e04b1bc5 921 if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag != 0)
youkee 0:1ad0e04b1bc5 922 req_field_count++;
youkee 0:1ad0e04b1bc5 923
youkee 0:1ad0e04b1bc5 924 if (req_field_count > 0)
youkee 0:1ad0e04b1bc5 925 {
youkee 0:1ad0e04b1bc5 926 /* Check the whole words */
youkee 0:1ad0e04b1bc5 927 for (i = 0; i < (req_field_count >> 5); i++)
youkee 0:1ad0e04b1bc5 928 {
youkee 0:1ad0e04b1bc5 929 if (fields_seen[i] != allbits)
youkee 0:1ad0e04b1bc5 930 PB_RETURN_ERROR(stream, "missing required field");
youkee 0:1ad0e04b1bc5 931 }
youkee 0:1ad0e04b1bc5 932
youkee 0:1ad0e04b1bc5 933 /* Check the remaining bits */
youkee 0:1ad0e04b1bc5 934 if (fields_seen[req_field_count >> 5] != (allbits >> (32 - (req_field_count & 31))))
youkee 0:1ad0e04b1bc5 935 PB_RETURN_ERROR(stream, "missing required field");
youkee 0:1ad0e04b1bc5 936 }
youkee 0:1ad0e04b1bc5 937 }
youkee 0:1ad0e04b1bc5 938
youkee 0:1ad0e04b1bc5 939 return true;
youkee 0:1ad0e04b1bc5 940 }
youkee 0:1ad0e04b1bc5 941
youkee 0:1ad0e04b1bc5 942 bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
youkee 0:1ad0e04b1bc5 943 {
youkee 0:1ad0e04b1bc5 944 bool status;
youkee 0:1ad0e04b1bc5 945 pb_message_set_to_defaults(fields, dest_struct);
youkee 0:1ad0e04b1bc5 946 status = pb_decode_noinit(stream, fields, dest_struct);
youkee 0:1ad0e04b1bc5 947
youkee 0:1ad0e04b1bc5 948 #ifdef PB_ENABLE_MALLOC
youkee 0:1ad0e04b1bc5 949 if (!status)
youkee 0:1ad0e04b1bc5 950 pb_release(fields, dest_struct);
youkee 0:1ad0e04b1bc5 951 #endif
youkee 0:1ad0e04b1bc5 952
youkee 0:1ad0e04b1bc5 953 return status;
youkee 0:1ad0e04b1bc5 954 }
youkee 0:1ad0e04b1bc5 955
youkee 0:1ad0e04b1bc5 956 bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
youkee 0:1ad0e04b1bc5 957 {
youkee 0:1ad0e04b1bc5 958 pb_istream_t substream;
youkee 0:1ad0e04b1bc5 959 bool status;
youkee 0:1ad0e04b1bc5 960
youkee 0:1ad0e04b1bc5 961 if (!pb_make_string_substream(stream, &substream))
youkee 0:1ad0e04b1bc5 962 return false;
youkee 0:1ad0e04b1bc5 963
youkee 0:1ad0e04b1bc5 964 status = pb_decode(&substream, fields, dest_struct);
youkee 0:1ad0e04b1bc5 965 pb_close_string_substream(stream, &substream);
youkee 0:1ad0e04b1bc5 966 return status;
youkee 0:1ad0e04b1bc5 967 }
youkee 0:1ad0e04b1bc5 968
youkee 0:1ad0e04b1bc5 969 #ifdef PB_ENABLE_MALLOC
youkee 0:1ad0e04b1bc5 970 /* Given an oneof field, if there has already been a field inside this oneof,
youkee 0:1ad0e04b1bc5 971 * release it before overwriting with a different one. */
youkee 0:1ad0e04b1bc5 972 static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter)
youkee 0:1ad0e04b1bc5 973 {
youkee 0:1ad0e04b1bc5 974 pb_size_t old_tag = *(pb_size_t*)iter->pSize; /* Previous which_ value */
youkee 0:1ad0e04b1bc5 975 pb_size_t new_tag = iter->pos->tag; /* New which_ value */
youkee 0:1ad0e04b1bc5 976
youkee 0:1ad0e04b1bc5 977 if (old_tag == 0)
youkee 0:1ad0e04b1bc5 978 return true; /* Ok, no old data in union */
youkee 0:1ad0e04b1bc5 979
youkee 0:1ad0e04b1bc5 980 if (old_tag == new_tag)
youkee 0:1ad0e04b1bc5 981 return true; /* Ok, old data is of same type => merge */
youkee 0:1ad0e04b1bc5 982
youkee 0:1ad0e04b1bc5 983 /* Release old data. The find can fail if the message struct contains
youkee 0:1ad0e04b1bc5 984 * invalid data. */
youkee 0:1ad0e04b1bc5 985 if (!pb_field_iter_find(iter, old_tag))
youkee 0:1ad0e04b1bc5 986 PB_RETURN_ERROR(stream, "invalid union tag");
youkee 0:1ad0e04b1bc5 987
youkee 0:1ad0e04b1bc5 988 pb_release_single_field(iter);
youkee 0:1ad0e04b1bc5 989
youkee 0:1ad0e04b1bc5 990 /* Restore iterator to where it should be.
youkee 0:1ad0e04b1bc5 991 * This shouldn't fail unless the pb_field_t structure is corrupted. */
youkee 0:1ad0e04b1bc5 992 if (!pb_field_iter_find(iter, new_tag))
youkee 0:1ad0e04b1bc5 993 PB_RETURN_ERROR(stream, "iterator error");
youkee 0:1ad0e04b1bc5 994
youkee 0:1ad0e04b1bc5 995 return true;
youkee 0:1ad0e04b1bc5 996 }
youkee 0:1ad0e04b1bc5 997
youkee 0:1ad0e04b1bc5 998 static void pb_release_single_field(const pb_field_iter_t *iter)
youkee 0:1ad0e04b1bc5 999 {
youkee 0:1ad0e04b1bc5 1000 pb_type_t type;
youkee 0:1ad0e04b1bc5 1001 type = iter->pos->type;
youkee 0:1ad0e04b1bc5 1002
youkee 0:1ad0e04b1bc5 1003 if (PB_HTYPE(type) == PB_HTYPE_ONEOF)
youkee 0:1ad0e04b1bc5 1004 {
youkee 0:1ad0e04b1bc5 1005 if (*(pb_size_t*)iter->pSize != iter->pos->tag)
youkee 0:1ad0e04b1bc5 1006 return; /* This is not the current field in the union */
youkee 0:1ad0e04b1bc5 1007 }
youkee 0:1ad0e04b1bc5 1008
youkee 0:1ad0e04b1bc5 1009 /* Release anything contained inside an extension or submsg.
youkee 0:1ad0e04b1bc5 1010 * This has to be done even if the submsg itself is statically
youkee 0:1ad0e04b1bc5 1011 * allocated. */
youkee 0:1ad0e04b1bc5 1012 if (PB_LTYPE(type) == PB_LTYPE_EXTENSION)
youkee 0:1ad0e04b1bc5 1013 {
youkee 0:1ad0e04b1bc5 1014 /* Release fields from all extensions in the linked list */
youkee 0:1ad0e04b1bc5 1015 pb_extension_t *ext = *(pb_extension_t**)iter->pData;
youkee 0:1ad0e04b1bc5 1016 while (ext != NULL)
youkee 0:1ad0e04b1bc5 1017 {
youkee 0:1ad0e04b1bc5 1018 pb_field_iter_t ext_iter;
youkee 0:1ad0e04b1bc5 1019 iter_from_extension(&ext_iter, ext);
youkee 0:1ad0e04b1bc5 1020 pb_release_single_field(&ext_iter);
youkee 0:1ad0e04b1bc5 1021 ext = ext->next;
youkee 0:1ad0e04b1bc5 1022 }
youkee 0:1ad0e04b1bc5 1023 }
youkee 0:1ad0e04b1bc5 1024 else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE)
youkee 0:1ad0e04b1bc5 1025 {
youkee 0:1ad0e04b1bc5 1026 /* Release fields in submessage or submsg array */
youkee 0:1ad0e04b1bc5 1027 void *pItem = iter->pData;
youkee 0:1ad0e04b1bc5 1028 pb_size_t count = 1;
youkee 0:1ad0e04b1bc5 1029
youkee 0:1ad0e04b1bc5 1030 if (PB_ATYPE(type) == PB_ATYPE_POINTER)
youkee 0:1ad0e04b1bc5 1031 {
youkee 0:1ad0e04b1bc5 1032 pItem = *(void**)iter->pData;
youkee 0:1ad0e04b1bc5 1033 }
youkee 0:1ad0e04b1bc5 1034
youkee 0:1ad0e04b1bc5 1035 if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
youkee 0:1ad0e04b1bc5 1036 {
youkee 0:1ad0e04b1bc5 1037 count = *(pb_size_t*)iter->pSize;
youkee 0:1ad0e04b1bc5 1038
youkee 0:1ad0e04b1bc5 1039 if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > iter->pos->array_size)
youkee 0:1ad0e04b1bc5 1040 {
youkee 0:1ad0e04b1bc5 1041 /* Protect against corrupted _count fields */
youkee 0:1ad0e04b1bc5 1042 count = iter->pos->array_size;
youkee 0:1ad0e04b1bc5 1043 }
youkee 0:1ad0e04b1bc5 1044 }
youkee 0:1ad0e04b1bc5 1045
youkee 0:1ad0e04b1bc5 1046 if (pItem)
youkee 0:1ad0e04b1bc5 1047 {
youkee 0:1ad0e04b1bc5 1048 while (count--)
youkee 0:1ad0e04b1bc5 1049 {
youkee 0:1ad0e04b1bc5 1050 pb_release((const pb_field_t*)iter->pos->ptr, pItem);
youkee 0:1ad0e04b1bc5 1051 pItem = (char*)pItem + iter->pos->data_size;
youkee 0:1ad0e04b1bc5 1052 }
youkee 0:1ad0e04b1bc5 1053 }
youkee 0:1ad0e04b1bc5 1054 }
youkee 0:1ad0e04b1bc5 1055
youkee 0:1ad0e04b1bc5 1056 if (PB_ATYPE(type) == PB_ATYPE_POINTER)
youkee 0:1ad0e04b1bc5 1057 {
youkee 0:1ad0e04b1bc5 1058 if (PB_HTYPE(type) == PB_HTYPE_REPEATED &&
youkee 0:1ad0e04b1bc5 1059 (PB_LTYPE(type) == PB_LTYPE_STRING ||
youkee 0:1ad0e04b1bc5 1060 PB_LTYPE(type) == PB_LTYPE_BYTES))
youkee 0:1ad0e04b1bc5 1061 {
youkee 0:1ad0e04b1bc5 1062 /* Release entries in repeated string or bytes array */
youkee 0:1ad0e04b1bc5 1063 void **pItem = *(void***)iter->pData;
youkee 0:1ad0e04b1bc5 1064 pb_size_t count = *(pb_size_t*)iter->pSize;
youkee 0:1ad0e04b1bc5 1065 while (count--)
youkee 0:1ad0e04b1bc5 1066 {
youkee 0:1ad0e04b1bc5 1067 pb_free(*pItem);
youkee 0:1ad0e04b1bc5 1068 *pItem++ = NULL;
youkee 0:1ad0e04b1bc5 1069 }
youkee 0:1ad0e04b1bc5 1070 }
youkee 0:1ad0e04b1bc5 1071
youkee 0:1ad0e04b1bc5 1072 if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
youkee 0:1ad0e04b1bc5 1073 {
youkee 0:1ad0e04b1bc5 1074 /* We are going to release the array, so set the size to 0 */
youkee 0:1ad0e04b1bc5 1075 *(pb_size_t*)iter->pSize = 0;
youkee 0:1ad0e04b1bc5 1076 }
youkee 0:1ad0e04b1bc5 1077
youkee 0:1ad0e04b1bc5 1078 /* Release main item */
youkee 0:1ad0e04b1bc5 1079 pb_free(*(void**)iter->pData);
youkee 0:1ad0e04b1bc5 1080 *(void**)iter->pData = NULL;
youkee 0:1ad0e04b1bc5 1081 }
youkee 0:1ad0e04b1bc5 1082 }
youkee 0:1ad0e04b1bc5 1083
youkee 0:1ad0e04b1bc5 1084 void pb_release(const pb_field_t fields[], void *dest_struct)
youkee 0:1ad0e04b1bc5 1085 {
youkee 0:1ad0e04b1bc5 1086 pb_field_iter_t iter;
youkee 0:1ad0e04b1bc5 1087
youkee 0:1ad0e04b1bc5 1088 if (!dest_struct)
youkee 0:1ad0e04b1bc5 1089 return; /* Ignore NULL pointers, similar to free() */
youkee 0:1ad0e04b1bc5 1090
youkee 0:1ad0e04b1bc5 1091 if (!pb_field_iter_begin(&iter, fields, dest_struct))
youkee 0:1ad0e04b1bc5 1092 return; /* Empty message type */
youkee 0:1ad0e04b1bc5 1093
youkee 0:1ad0e04b1bc5 1094 do
youkee 0:1ad0e04b1bc5 1095 {
youkee 0:1ad0e04b1bc5 1096 pb_release_single_field(&iter);
youkee 0:1ad0e04b1bc5 1097 } while (pb_field_iter_next(&iter));
youkee 0:1ad0e04b1bc5 1098 }
youkee 0:1ad0e04b1bc5 1099 #endif
youkee 0:1ad0e04b1bc5 1100
youkee 0:1ad0e04b1bc5 1101 /* Field decoders */
youkee 0:1ad0e04b1bc5 1102
youkee 0:1ad0e04b1bc5 1103 bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest)
youkee 0:1ad0e04b1bc5 1104 {
youkee 0:1ad0e04b1bc5 1105 uint64_t value;
youkee 0:1ad0e04b1bc5 1106 if (!pb_decode_varint(stream, &value))
youkee 0:1ad0e04b1bc5 1107 return false;
youkee 0:1ad0e04b1bc5 1108
youkee 0:1ad0e04b1bc5 1109 if (value & 1)
youkee 0:1ad0e04b1bc5 1110 *dest = (int64_t)(~(value >> 1));
youkee 0:1ad0e04b1bc5 1111 else
youkee 0:1ad0e04b1bc5 1112 *dest = (int64_t)(value >> 1);
youkee 0:1ad0e04b1bc5 1113
youkee 0:1ad0e04b1bc5 1114 return true;
youkee 0:1ad0e04b1bc5 1115 }
youkee 0:1ad0e04b1bc5 1116
youkee 0:1ad0e04b1bc5 1117 bool pb_decode_fixed32(pb_istream_t *stream, void *dest)
youkee 0:1ad0e04b1bc5 1118 {
youkee 0:1ad0e04b1bc5 1119 pb_byte_t bytes[4];
youkee 0:1ad0e04b1bc5 1120
youkee 0:1ad0e04b1bc5 1121 if (!pb_read(stream, bytes, 4))
youkee 0:1ad0e04b1bc5 1122 return false;
youkee 0:1ad0e04b1bc5 1123
youkee 0:1ad0e04b1bc5 1124 *(uint32_t*)dest = ((uint32_t)bytes[0] << 0) |
youkee 0:1ad0e04b1bc5 1125 ((uint32_t)bytes[1] << 8) |
youkee 0:1ad0e04b1bc5 1126 ((uint32_t)bytes[2] << 16) |
youkee 0:1ad0e04b1bc5 1127 ((uint32_t)bytes[3] << 24);
youkee 0:1ad0e04b1bc5 1128 return true;
youkee 0:1ad0e04b1bc5 1129 }
youkee 0:1ad0e04b1bc5 1130
youkee 0:1ad0e04b1bc5 1131 bool pb_decode_fixed64(pb_istream_t *stream, void *dest)
youkee 0:1ad0e04b1bc5 1132 {
youkee 0:1ad0e04b1bc5 1133 pb_byte_t bytes[8];
youkee 0:1ad0e04b1bc5 1134
youkee 0:1ad0e04b1bc5 1135 if (!pb_read(stream, bytes, 8))
youkee 0:1ad0e04b1bc5 1136 return false;
youkee 0:1ad0e04b1bc5 1137
youkee 0:1ad0e04b1bc5 1138 *(uint64_t*)dest = ((uint64_t)bytes[0] << 0) |
youkee 0:1ad0e04b1bc5 1139 ((uint64_t)bytes[1] << 8) |
youkee 0:1ad0e04b1bc5 1140 ((uint64_t)bytes[2] << 16) |
youkee 0:1ad0e04b1bc5 1141 ((uint64_t)bytes[3] << 24) |
youkee 0:1ad0e04b1bc5 1142 ((uint64_t)bytes[4] << 32) |
youkee 0:1ad0e04b1bc5 1143 ((uint64_t)bytes[5] << 40) |
youkee 0:1ad0e04b1bc5 1144 ((uint64_t)bytes[6] << 48) |
youkee 0:1ad0e04b1bc5 1145 ((uint64_t)bytes[7] << 56);
youkee 0:1ad0e04b1bc5 1146
youkee 0:1ad0e04b1bc5 1147 return true;
youkee 0:1ad0e04b1bc5 1148 }
youkee 0:1ad0e04b1bc5 1149
youkee 0:1ad0e04b1bc5 1150 static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest)
youkee 0:1ad0e04b1bc5 1151 {
youkee 0:1ad0e04b1bc5 1152 uint64_t value;
youkee 0:1ad0e04b1bc5 1153 int64_t svalue;
youkee 0:1ad0e04b1bc5 1154 int64_t clamped;
youkee 0:1ad0e04b1bc5 1155 if (!pb_decode_varint(stream, &value))
youkee 0:1ad0e04b1bc5 1156 return false;
youkee 0:1ad0e04b1bc5 1157
youkee 0:1ad0e04b1bc5 1158 /* See issue 97: Google's C++ protobuf allows negative varint values to
youkee 0:1ad0e04b1bc5 1159 * be cast as int32_t, instead of the int64_t that should be used when
youkee 0:1ad0e04b1bc5 1160 * encoding. Previous nanopb versions had a bug in encoding. In order to
youkee 0:1ad0e04b1bc5 1161 * not break decoding of such messages, we cast <=32 bit fields to
youkee 0:1ad0e04b1bc5 1162 * int32_t first to get the sign correct.
youkee 0:1ad0e04b1bc5 1163 */
youkee 0:1ad0e04b1bc5 1164 if (field->data_size == sizeof(int64_t))
youkee 0:1ad0e04b1bc5 1165 svalue = (int64_t)value;
youkee 0:1ad0e04b1bc5 1166 else
youkee 0:1ad0e04b1bc5 1167 svalue = (int32_t)value;
youkee 0:1ad0e04b1bc5 1168
youkee 0:1ad0e04b1bc5 1169 /* Cast to the proper field size, while checking for overflows */
youkee 0:1ad0e04b1bc5 1170 if (field->data_size == sizeof(int64_t))
youkee 0:1ad0e04b1bc5 1171 clamped = *(int64_t*)dest = svalue;
youkee 0:1ad0e04b1bc5 1172 else if (field->data_size == sizeof(int32_t))
youkee 0:1ad0e04b1bc5 1173 clamped = *(int32_t*)dest = (int32_t)svalue;
youkee 0:1ad0e04b1bc5 1174 else if (field->data_size == sizeof(int_least16_t))
youkee 0:1ad0e04b1bc5 1175 clamped = *(int_least16_t*)dest = (int_least16_t)svalue;
youkee 0:1ad0e04b1bc5 1176 else if (field->data_size == sizeof(int_least8_t))
youkee 0:1ad0e04b1bc5 1177 clamped = *(int_least8_t*)dest = (int_least8_t)svalue;
youkee 0:1ad0e04b1bc5 1178 else
youkee 0:1ad0e04b1bc5 1179 PB_RETURN_ERROR(stream, "invalid data_size");
youkee 0:1ad0e04b1bc5 1180
youkee 0:1ad0e04b1bc5 1181 if (clamped != svalue)
youkee 0:1ad0e04b1bc5 1182 PB_RETURN_ERROR(stream, "integer too large");
youkee 0:1ad0e04b1bc5 1183
youkee 0:1ad0e04b1bc5 1184 return true;
youkee 0:1ad0e04b1bc5 1185 }
youkee 0:1ad0e04b1bc5 1186
youkee 0:1ad0e04b1bc5 1187 static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
youkee 0:1ad0e04b1bc5 1188 {
youkee 0:1ad0e04b1bc5 1189 uint64_t value, clamped;
youkee 0:1ad0e04b1bc5 1190 if (!pb_decode_varint(stream, &value))
youkee 0:1ad0e04b1bc5 1191 return false;
youkee 0:1ad0e04b1bc5 1192
youkee 0:1ad0e04b1bc5 1193 /* Cast to the proper field size, while checking for overflows */
youkee 0:1ad0e04b1bc5 1194 if (field->data_size == sizeof(uint64_t))
youkee 0:1ad0e04b1bc5 1195 clamped = *(uint64_t*)dest = value;
youkee 0:1ad0e04b1bc5 1196 else if (field->data_size == sizeof(uint32_t))
youkee 0:1ad0e04b1bc5 1197 clamped = *(uint32_t*)dest = (uint32_t)value;
youkee 0:1ad0e04b1bc5 1198 else if (field->data_size == sizeof(uint_least16_t))
youkee 0:1ad0e04b1bc5 1199 clamped = *(uint_least16_t*)dest = (uint_least16_t)value;
youkee 0:1ad0e04b1bc5 1200 else if (field->data_size == sizeof(uint_least8_t))
youkee 0:1ad0e04b1bc5 1201 clamped = *(uint_least8_t*)dest = (uint_least8_t)value;
youkee 0:1ad0e04b1bc5 1202 else
youkee 0:1ad0e04b1bc5 1203 PB_RETURN_ERROR(stream, "invalid data_size");
youkee 0:1ad0e04b1bc5 1204
youkee 0:1ad0e04b1bc5 1205 if (clamped != value)
youkee 0:1ad0e04b1bc5 1206 PB_RETURN_ERROR(stream, "integer too large");
youkee 0:1ad0e04b1bc5 1207
youkee 0:1ad0e04b1bc5 1208 return true;
youkee 0:1ad0e04b1bc5 1209 }
youkee 0:1ad0e04b1bc5 1210
youkee 0:1ad0e04b1bc5 1211 static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
youkee 0:1ad0e04b1bc5 1212 {
youkee 0:1ad0e04b1bc5 1213 int64_t value, clamped;
youkee 0:1ad0e04b1bc5 1214 if (!pb_decode_svarint(stream, &value))
youkee 0:1ad0e04b1bc5 1215 return false;
youkee 0:1ad0e04b1bc5 1216
youkee 0:1ad0e04b1bc5 1217 /* Cast to the proper field size, while checking for overflows */
youkee 0:1ad0e04b1bc5 1218 if (field->data_size == sizeof(int64_t))
youkee 0:1ad0e04b1bc5 1219 clamped = *(int64_t*)dest = value;
youkee 0:1ad0e04b1bc5 1220 else if (field->data_size == sizeof(int32_t))
youkee 0:1ad0e04b1bc5 1221 clamped = *(int32_t*)dest = (int32_t)value;
youkee 0:1ad0e04b1bc5 1222 else if (field->data_size == sizeof(int_least16_t))
youkee 0:1ad0e04b1bc5 1223 clamped = *(int_least16_t*)dest = (int_least16_t)value;
youkee 0:1ad0e04b1bc5 1224 else if (field->data_size == sizeof(int_least8_t))
youkee 0:1ad0e04b1bc5 1225 clamped = *(int_least8_t*)dest = (int_least8_t)value;
youkee 0:1ad0e04b1bc5 1226 else
youkee 0:1ad0e04b1bc5 1227 PB_RETURN_ERROR(stream, "invalid data_size");
youkee 0:1ad0e04b1bc5 1228
youkee 0:1ad0e04b1bc5 1229 if (clamped != value)
youkee 0:1ad0e04b1bc5 1230 PB_RETURN_ERROR(stream, "integer too large");
youkee 0:1ad0e04b1bc5 1231
youkee 0:1ad0e04b1bc5 1232 return true;
youkee 0:1ad0e04b1bc5 1233 }
youkee 0:1ad0e04b1bc5 1234
youkee 0:1ad0e04b1bc5 1235 static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest)
youkee 0:1ad0e04b1bc5 1236 {
youkee 0:1ad0e04b1bc5 1237 PB_UNUSED(field);
youkee 0:1ad0e04b1bc5 1238 return pb_decode_fixed32(stream, dest);
youkee 0:1ad0e04b1bc5 1239 }
youkee 0:1ad0e04b1bc5 1240
youkee 0:1ad0e04b1bc5 1241 static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest)
youkee 0:1ad0e04b1bc5 1242 {
youkee 0:1ad0e04b1bc5 1243 PB_UNUSED(field);
youkee 0:1ad0e04b1bc5 1244 return pb_decode_fixed64(stream, dest);
youkee 0:1ad0e04b1bc5 1245 }
youkee 0:1ad0e04b1bc5 1246
youkee 0:1ad0e04b1bc5 1247 static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest)
youkee 0:1ad0e04b1bc5 1248 {
youkee 0:1ad0e04b1bc5 1249 uint32_t size;
youkee 0:1ad0e04b1bc5 1250 size_t alloc_size;
youkee 0:1ad0e04b1bc5 1251 pb_bytes_array_t *bdest;
youkee 0:1ad0e04b1bc5 1252
youkee 0:1ad0e04b1bc5 1253 if (!pb_decode_varint32(stream, &size))
youkee 0:1ad0e04b1bc5 1254 return false;
youkee 0:1ad0e04b1bc5 1255
youkee 0:1ad0e04b1bc5 1256 if (size > PB_SIZE_MAX)
youkee 0:1ad0e04b1bc5 1257 PB_RETURN_ERROR(stream, "bytes overflow");
youkee 0:1ad0e04b1bc5 1258
youkee 0:1ad0e04b1bc5 1259 alloc_size = PB_BYTES_ARRAY_T_ALLOCSIZE(size);
youkee 0:1ad0e04b1bc5 1260 if (size > alloc_size)
youkee 0:1ad0e04b1bc5 1261 PB_RETURN_ERROR(stream, "size too large");
youkee 0:1ad0e04b1bc5 1262
youkee 0:1ad0e04b1bc5 1263 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
youkee 0:1ad0e04b1bc5 1264 {
youkee 0:1ad0e04b1bc5 1265 #ifndef PB_ENABLE_MALLOC
youkee 0:1ad0e04b1bc5 1266 PB_RETURN_ERROR(stream, "no malloc support");
youkee 0:1ad0e04b1bc5 1267 #else
youkee 0:1ad0e04b1bc5 1268 if (!allocate_field(stream, dest, alloc_size, 1))
youkee 0:1ad0e04b1bc5 1269 return false;
youkee 0:1ad0e04b1bc5 1270 bdest = *(pb_bytes_array_t**)dest;
youkee 0:1ad0e04b1bc5 1271 #endif
youkee 0:1ad0e04b1bc5 1272 }
youkee 0:1ad0e04b1bc5 1273 else
youkee 0:1ad0e04b1bc5 1274 {
youkee 0:1ad0e04b1bc5 1275 if (alloc_size > field->data_size)
youkee 0:1ad0e04b1bc5 1276 PB_RETURN_ERROR(stream, "bytes overflow");
youkee 0:1ad0e04b1bc5 1277 bdest = (pb_bytes_array_t*)dest;
youkee 0:1ad0e04b1bc5 1278 }
youkee 0:1ad0e04b1bc5 1279
youkee 0:1ad0e04b1bc5 1280 bdest->size = (pb_size_t)size;
youkee 0:1ad0e04b1bc5 1281 return pb_read(stream, bdest->bytes, size);
youkee 0:1ad0e04b1bc5 1282 }
youkee 0:1ad0e04b1bc5 1283
youkee 0:1ad0e04b1bc5 1284 static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest)
youkee 0:1ad0e04b1bc5 1285 {
youkee 0:1ad0e04b1bc5 1286 uint32_t size;
youkee 0:1ad0e04b1bc5 1287 size_t alloc_size;
youkee 0:1ad0e04b1bc5 1288 bool status;
youkee 0:1ad0e04b1bc5 1289 if (!pb_decode_varint32(stream, &size))
youkee 0:1ad0e04b1bc5 1290 return false;
youkee 0:1ad0e04b1bc5 1291
youkee 0:1ad0e04b1bc5 1292 /* Space for null terminator */
youkee 0:1ad0e04b1bc5 1293 alloc_size = size + 1;
youkee 0:1ad0e04b1bc5 1294
youkee 0:1ad0e04b1bc5 1295 if (alloc_size < size)
youkee 0:1ad0e04b1bc5 1296 PB_RETURN_ERROR(stream, "size too large");
youkee 0:1ad0e04b1bc5 1297
youkee 0:1ad0e04b1bc5 1298 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
youkee 0:1ad0e04b1bc5 1299 {
youkee 0:1ad0e04b1bc5 1300 #ifndef PB_ENABLE_MALLOC
youkee 0:1ad0e04b1bc5 1301 PB_RETURN_ERROR(stream, "no malloc support");
youkee 0:1ad0e04b1bc5 1302 #else
youkee 0:1ad0e04b1bc5 1303 if (!allocate_field(stream, dest, alloc_size, 1))
youkee 0:1ad0e04b1bc5 1304 return false;
youkee 0:1ad0e04b1bc5 1305 dest = *(void**)dest;
youkee 0:1ad0e04b1bc5 1306 #endif
youkee 0:1ad0e04b1bc5 1307 }
youkee 0:1ad0e04b1bc5 1308 else
youkee 0:1ad0e04b1bc5 1309 {
youkee 0:1ad0e04b1bc5 1310 if (alloc_size > field->data_size)
youkee 0:1ad0e04b1bc5 1311 PB_RETURN_ERROR(stream, "string overflow");
youkee 0:1ad0e04b1bc5 1312 }
youkee 0:1ad0e04b1bc5 1313
youkee 0:1ad0e04b1bc5 1314 status = pb_read(stream, (pb_byte_t*)dest, size);
youkee 0:1ad0e04b1bc5 1315 *((pb_byte_t*)dest + size) = 0;
youkee 0:1ad0e04b1bc5 1316 return status;
youkee 0:1ad0e04b1bc5 1317 }
youkee 0:1ad0e04b1bc5 1318
youkee 0:1ad0e04b1bc5 1319 static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest)
youkee 0:1ad0e04b1bc5 1320 {
youkee 0:1ad0e04b1bc5 1321 bool status;
youkee 0:1ad0e04b1bc5 1322 pb_istream_t substream;
youkee 0:1ad0e04b1bc5 1323 const pb_field_t* submsg_fields = (const pb_field_t*)field->ptr;
youkee 0:1ad0e04b1bc5 1324
youkee 0:1ad0e04b1bc5 1325 if (!pb_make_string_substream(stream, &substream))
youkee 0:1ad0e04b1bc5 1326 return false;
youkee 0:1ad0e04b1bc5 1327
youkee 0:1ad0e04b1bc5 1328 if (field->ptr == NULL)
youkee 0:1ad0e04b1bc5 1329 PB_RETURN_ERROR(stream, "invalid field descriptor");
youkee 0:1ad0e04b1bc5 1330
youkee 0:1ad0e04b1bc5 1331 /* New array entries need to be initialized, while required and optional
youkee 0:1ad0e04b1bc5 1332 * submessages have already been initialized in the top-level pb_decode. */
youkee 0:1ad0e04b1bc5 1333 if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED)
youkee 0:1ad0e04b1bc5 1334 status = pb_decode(&substream, submsg_fields, dest);
youkee 0:1ad0e04b1bc5 1335 else
youkee 0:1ad0e04b1bc5 1336 status = pb_decode_noinit(&substream, submsg_fields, dest);
youkee 0:1ad0e04b1bc5 1337
youkee 0:1ad0e04b1bc5 1338 pb_close_string_substream(stream, &substream);
youkee 0:1ad0e04b1bc5 1339 return status;
youkee 0:1ad0e04b1bc5 1340 }