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_encode.c -- encode 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 #include "pb.h"
youkee 0:1ad0e04b1bc5 7 #include "pb_encode.h"
youkee 0:1ad0e04b1bc5 8 #include "pb_common.h"
youkee 0:1ad0e04b1bc5 9
youkee 0:1ad0e04b1bc5 10 /* Use the GCC warn_unused_result attribute to check that all return values
youkee 0:1ad0e04b1bc5 11 * are propagated correctly. On other compilers and gcc before 3.4.0 just
youkee 0:1ad0e04b1bc5 12 * ignore the annotation.
youkee 0:1ad0e04b1bc5 13 */
youkee 0:1ad0e04b1bc5 14 #if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
youkee 0:1ad0e04b1bc5 15 #define checkreturn
youkee 0:1ad0e04b1bc5 16 #else
youkee 0:1ad0e04b1bc5 17 #define checkreturn __attribute__((warn_unused_result))
youkee 0:1ad0e04b1bc5 18 #endif
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 typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn;
youkee 0:1ad0e04b1bc5 24
youkee 0:1ad0e04b1bc5 25 static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
youkee 0:1ad0e04b1bc5 26 static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func);
youkee 0:1ad0e04b1bc5 27 static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData);
youkee 0:1ad0e04b1bc5 28 static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension);
youkee 0:1ad0e04b1bc5 29 static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData);
youkee 0:1ad0e04b1bc5 30 static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
youkee 0:1ad0e04b1bc5 31 static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
youkee 0:1ad0e04b1bc5 32 static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
youkee 0:1ad0e04b1bc5 33 static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src);
youkee 0:1ad0e04b1bc5 34 static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src);
youkee 0:1ad0e04b1bc5 35 static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src);
youkee 0:1ad0e04b1bc5 36 static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src);
youkee 0:1ad0e04b1bc5 37 static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src);
youkee 0:1ad0e04b1bc5 38
youkee 0:1ad0e04b1bc5 39 /* --- Function pointers to field encoders ---
youkee 0:1ad0e04b1bc5 40 * Order in the array must match pb_action_t LTYPE numbering.
youkee 0:1ad0e04b1bc5 41 */
youkee 0:1ad0e04b1bc5 42 static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = {
youkee 0:1ad0e04b1bc5 43 &pb_enc_varint,
youkee 0:1ad0e04b1bc5 44 &pb_enc_uvarint,
youkee 0:1ad0e04b1bc5 45 &pb_enc_svarint,
youkee 0:1ad0e04b1bc5 46 &pb_enc_fixed32,
youkee 0:1ad0e04b1bc5 47 &pb_enc_fixed64,
youkee 0:1ad0e04b1bc5 48
youkee 0:1ad0e04b1bc5 49 &pb_enc_bytes,
youkee 0:1ad0e04b1bc5 50 &pb_enc_string,
youkee 0:1ad0e04b1bc5 51 &pb_enc_submessage,
youkee 0:1ad0e04b1bc5 52 NULL /* extensions */
youkee 0:1ad0e04b1bc5 53 };
youkee 0:1ad0e04b1bc5 54
youkee 0:1ad0e04b1bc5 55 /*******************************
youkee 0:1ad0e04b1bc5 56 * pb_ostream_t implementation *
youkee 0:1ad0e04b1bc5 57 *******************************/
youkee 0:1ad0e04b1bc5 58
youkee 0:1ad0e04b1bc5 59 static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
youkee 0:1ad0e04b1bc5 60 {
youkee 0:1ad0e04b1bc5 61 pb_byte_t *dest = (pb_byte_t*)stream->state;
youkee 0:1ad0e04b1bc5 62 stream->state = dest + count;
youkee 0:1ad0e04b1bc5 63
youkee 0:1ad0e04b1bc5 64 while (count--)
youkee 0:1ad0e04b1bc5 65 *dest++ = *buf++;
youkee 0:1ad0e04b1bc5 66
youkee 0:1ad0e04b1bc5 67 return true;
youkee 0:1ad0e04b1bc5 68 }
youkee 0:1ad0e04b1bc5 69
youkee 0:1ad0e04b1bc5 70 pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize)
youkee 0:1ad0e04b1bc5 71 {
youkee 0:1ad0e04b1bc5 72 pb_ostream_t stream;
youkee 0:1ad0e04b1bc5 73 #ifdef PB_BUFFER_ONLY
youkee 0:1ad0e04b1bc5 74 stream.callback = (void*)1; /* Just a marker value */
youkee 0:1ad0e04b1bc5 75 #else
youkee 0:1ad0e04b1bc5 76 stream.callback = &buf_write;
youkee 0:1ad0e04b1bc5 77 #endif
youkee 0:1ad0e04b1bc5 78 stream.state = buf;
youkee 0:1ad0e04b1bc5 79 stream.max_size = bufsize;
youkee 0:1ad0e04b1bc5 80 stream.bytes_written = 0;
youkee 0:1ad0e04b1bc5 81 #ifndef PB_NO_ERRMSG
youkee 0:1ad0e04b1bc5 82 stream.errmsg = NULL;
youkee 0:1ad0e04b1bc5 83 #endif
youkee 0:1ad0e04b1bc5 84 return stream;
youkee 0:1ad0e04b1bc5 85 }
youkee 0:1ad0e04b1bc5 86
youkee 0:1ad0e04b1bc5 87 bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
youkee 0:1ad0e04b1bc5 88 {
youkee 0:1ad0e04b1bc5 89 if (stream->callback != NULL)
youkee 0:1ad0e04b1bc5 90 {
youkee 0:1ad0e04b1bc5 91 if (stream->bytes_written + count > stream->max_size)
youkee 0:1ad0e04b1bc5 92 PB_RETURN_ERROR(stream, "stream full");
youkee 0:1ad0e04b1bc5 93
youkee 0:1ad0e04b1bc5 94 #ifdef PB_BUFFER_ONLY
youkee 0:1ad0e04b1bc5 95 if (!buf_write(stream, buf, count))
youkee 0:1ad0e04b1bc5 96 PB_RETURN_ERROR(stream, "io error");
youkee 0:1ad0e04b1bc5 97 #else
youkee 0:1ad0e04b1bc5 98 if (!stream->callback(stream, buf, count))
youkee 0:1ad0e04b1bc5 99 PB_RETURN_ERROR(stream, "io error");
youkee 0:1ad0e04b1bc5 100 #endif
youkee 0:1ad0e04b1bc5 101 }
youkee 0:1ad0e04b1bc5 102
youkee 0:1ad0e04b1bc5 103 stream->bytes_written += count;
youkee 0:1ad0e04b1bc5 104 return true;
youkee 0:1ad0e04b1bc5 105 }
youkee 0:1ad0e04b1bc5 106
youkee 0:1ad0e04b1bc5 107 /*************************
youkee 0:1ad0e04b1bc5 108 * Encode a single field *
youkee 0:1ad0e04b1bc5 109 *************************/
youkee 0:1ad0e04b1bc5 110
youkee 0:1ad0e04b1bc5 111 /* Encode a static array. Handles the size calculations and possible packing. */
youkee 0:1ad0e04b1bc5 112 static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field,
youkee 0:1ad0e04b1bc5 113 const void *pData, size_t count, pb_encoder_t func)
youkee 0:1ad0e04b1bc5 114 {
youkee 0:1ad0e04b1bc5 115 size_t i;
youkee 0:1ad0e04b1bc5 116 const void *p;
youkee 0:1ad0e04b1bc5 117 size_t size;
youkee 0:1ad0e04b1bc5 118
youkee 0:1ad0e04b1bc5 119 if (count == 0)
youkee 0:1ad0e04b1bc5 120 return true;
youkee 0:1ad0e04b1bc5 121
youkee 0:1ad0e04b1bc5 122 if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size)
youkee 0:1ad0e04b1bc5 123 PB_RETURN_ERROR(stream, "array max size exceeded");
youkee 0:1ad0e04b1bc5 124
youkee 0:1ad0e04b1bc5 125 /* We always pack arrays if the datatype allows it. */
youkee 0:1ad0e04b1bc5 126 if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE)
youkee 0:1ad0e04b1bc5 127 {
youkee 0:1ad0e04b1bc5 128 if (!pb_encode_tag(stream, PB_WT_STRING, field->tag))
youkee 0:1ad0e04b1bc5 129 return false;
youkee 0:1ad0e04b1bc5 130
youkee 0:1ad0e04b1bc5 131 /* Determine the total size of packed array. */
youkee 0:1ad0e04b1bc5 132 if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32)
youkee 0:1ad0e04b1bc5 133 {
youkee 0:1ad0e04b1bc5 134 size = 4 * count;
youkee 0:1ad0e04b1bc5 135 }
youkee 0:1ad0e04b1bc5 136 else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
youkee 0:1ad0e04b1bc5 137 {
youkee 0:1ad0e04b1bc5 138 size = 8 * count;
youkee 0:1ad0e04b1bc5 139 }
youkee 0:1ad0e04b1bc5 140 else
youkee 0:1ad0e04b1bc5 141 {
youkee 0:1ad0e04b1bc5 142 pb_ostream_t sizestream = PB_OSTREAM_SIZING;
youkee 0:1ad0e04b1bc5 143 p = pData;
youkee 0:1ad0e04b1bc5 144 for (i = 0; i < count; i++)
youkee 0:1ad0e04b1bc5 145 {
youkee 0:1ad0e04b1bc5 146 if (!func(&sizestream, field, p))
youkee 0:1ad0e04b1bc5 147 return false;
youkee 0:1ad0e04b1bc5 148 p = (const char*)p + field->data_size;
youkee 0:1ad0e04b1bc5 149 }
youkee 0:1ad0e04b1bc5 150 size = sizestream.bytes_written;
youkee 0:1ad0e04b1bc5 151 }
youkee 0:1ad0e04b1bc5 152
youkee 0:1ad0e04b1bc5 153 if (!pb_encode_varint(stream, (uint64_t)size))
youkee 0:1ad0e04b1bc5 154 return false;
youkee 0:1ad0e04b1bc5 155
youkee 0:1ad0e04b1bc5 156 if (stream->callback == NULL)
youkee 0:1ad0e04b1bc5 157 return pb_write(stream, NULL, size); /* Just sizing.. */
youkee 0:1ad0e04b1bc5 158
youkee 0:1ad0e04b1bc5 159 /* Write the data */
youkee 0:1ad0e04b1bc5 160 p = pData;
youkee 0:1ad0e04b1bc5 161 for (i = 0; i < count; i++)
youkee 0:1ad0e04b1bc5 162 {
youkee 0:1ad0e04b1bc5 163 if (!func(stream, field, p))
youkee 0:1ad0e04b1bc5 164 return false;
youkee 0:1ad0e04b1bc5 165 p = (const char*)p + field->data_size;
youkee 0:1ad0e04b1bc5 166 }
youkee 0:1ad0e04b1bc5 167 }
youkee 0:1ad0e04b1bc5 168 else
youkee 0:1ad0e04b1bc5 169 {
youkee 0:1ad0e04b1bc5 170 p = pData;
youkee 0:1ad0e04b1bc5 171 for (i = 0; i < count; i++)
youkee 0:1ad0e04b1bc5 172 {
youkee 0:1ad0e04b1bc5 173 if (!pb_encode_tag_for_field(stream, field))
youkee 0:1ad0e04b1bc5 174 return false;
youkee 0:1ad0e04b1bc5 175
youkee 0:1ad0e04b1bc5 176 /* Normally the data is stored directly in the array entries, but
youkee 0:1ad0e04b1bc5 177 * for pointer-type string and bytes fields, the array entries are
youkee 0:1ad0e04b1bc5 178 * actually pointers themselves also. So we have to dereference once
youkee 0:1ad0e04b1bc5 179 * more to get to the actual data. */
youkee 0:1ad0e04b1bc5 180 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER &&
youkee 0:1ad0e04b1bc5 181 (PB_LTYPE(field->type) == PB_LTYPE_STRING ||
youkee 0:1ad0e04b1bc5 182 PB_LTYPE(field->type) == PB_LTYPE_BYTES))
youkee 0:1ad0e04b1bc5 183 {
youkee 0:1ad0e04b1bc5 184 if (!func(stream, field, *(const void* const*)p))
youkee 0:1ad0e04b1bc5 185 return false;
youkee 0:1ad0e04b1bc5 186 }
youkee 0:1ad0e04b1bc5 187 else
youkee 0:1ad0e04b1bc5 188 {
youkee 0:1ad0e04b1bc5 189 if (!func(stream, field, p))
youkee 0:1ad0e04b1bc5 190 return false;
youkee 0:1ad0e04b1bc5 191 }
youkee 0:1ad0e04b1bc5 192 p = (const char*)p + field->data_size;
youkee 0:1ad0e04b1bc5 193 }
youkee 0:1ad0e04b1bc5 194 }
youkee 0:1ad0e04b1bc5 195
youkee 0:1ad0e04b1bc5 196 return true;
youkee 0:1ad0e04b1bc5 197 }
youkee 0:1ad0e04b1bc5 198
youkee 0:1ad0e04b1bc5 199 /* Encode a field with static or pointer allocation, i.e. one whose data
youkee 0:1ad0e04b1bc5 200 * is available to the encoder directly. */
youkee 0:1ad0e04b1bc5 201 static bool checkreturn encode_basic_field(pb_ostream_t *stream,
youkee 0:1ad0e04b1bc5 202 const pb_field_t *field, const void *pData)
youkee 0:1ad0e04b1bc5 203 {
youkee 0:1ad0e04b1bc5 204 pb_encoder_t func;
youkee 0:1ad0e04b1bc5 205 const void *pSize;
youkee 0:1ad0e04b1bc5 206 bool implicit_has = true;
youkee 0:1ad0e04b1bc5 207
youkee 0:1ad0e04b1bc5 208 func = PB_ENCODERS[PB_LTYPE(field->type)];
youkee 0:1ad0e04b1bc5 209
youkee 0:1ad0e04b1bc5 210 if (field->size_offset)
youkee 0:1ad0e04b1bc5 211 pSize = (const char*)pData + field->size_offset;
youkee 0:1ad0e04b1bc5 212 else
youkee 0:1ad0e04b1bc5 213 pSize = &implicit_has;
youkee 0:1ad0e04b1bc5 214
youkee 0:1ad0e04b1bc5 215 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
youkee 0:1ad0e04b1bc5 216 {
youkee 0:1ad0e04b1bc5 217 /* pData is a pointer to the field, which contains pointer to
youkee 0:1ad0e04b1bc5 218 * the data. If the 2nd pointer is NULL, it is interpreted as if
youkee 0:1ad0e04b1bc5 219 * the has_field was false.
youkee 0:1ad0e04b1bc5 220 */
youkee 0:1ad0e04b1bc5 221
youkee 0:1ad0e04b1bc5 222 pData = *(const void* const*)pData;
youkee 0:1ad0e04b1bc5 223 implicit_has = (pData != NULL);
youkee 0:1ad0e04b1bc5 224 }
youkee 0:1ad0e04b1bc5 225
youkee 0:1ad0e04b1bc5 226 switch (PB_HTYPE(field->type))
youkee 0:1ad0e04b1bc5 227 {
youkee 0:1ad0e04b1bc5 228 case PB_HTYPE_REQUIRED:
youkee 0:1ad0e04b1bc5 229 if (!pData)
youkee 0:1ad0e04b1bc5 230 PB_RETURN_ERROR(stream, "missing required field");
youkee 0:1ad0e04b1bc5 231 if (!pb_encode_tag_for_field(stream, field))
youkee 0:1ad0e04b1bc5 232 return false;
youkee 0:1ad0e04b1bc5 233 if (!func(stream, field, pData))
youkee 0:1ad0e04b1bc5 234 return false;
youkee 0:1ad0e04b1bc5 235 break;
youkee 0:1ad0e04b1bc5 236
youkee 0:1ad0e04b1bc5 237 case PB_HTYPE_OPTIONAL:
youkee 0:1ad0e04b1bc5 238 if (*(const bool*)pSize)
youkee 0:1ad0e04b1bc5 239 {
youkee 0:1ad0e04b1bc5 240 if (!pb_encode_tag_for_field(stream, field))
youkee 0:1ad0e04b1bc5 241 return false;
youkee 0:1ad0e04b1bc5 242
youkee 0:1ad0e04b1bc5 243 if (!func(stream, field, pData))
youkee 0:1ad0e04b1bc5 244 return false;
youkee 0:1ad0e04b1bc5 245 }
youkee 0:1ad0e04b1bc5 246 break;
youkee 0:1ad0e04b1bc5 247
youkee 0:1ad0e04b1bc5 248 case PB_HTYPE_REPEATED:
youkee 0:1ad0e04b1bc5 249 if (!encode_array(stream, field, pData, *(const pb_size_t*)pSize, func))
youkee 0:1ad0e04b1bc5 250 return false;
youkee 0:1ad0e04b1bc5 251 break;
youkee 0:1ad0e04b1bc5 252
youkee 0:1ad0e04b1bc5 253 case PB_HTYPE_ONEOF:
youkee 0:1ad0e04b1bc5 254 if (*(const pb_size_t*)pSize == field->tag)
youkee 0:1ad0e04b1bc5 255 {
youkee 0:1ad0e04b1bc5 256 if (!pb_encode_tag_for_field(stream, field))
youkee 0:1ad0e04b1bc5 257 return false;
youkee 0:1ad0e04b1bc5 258
youkee 0:1ad0e04b1bc5 259 if (!func(stream, field, pData))
youkee 0:1ad0e04b1bc5 260 return false;
youkee 0:1ad0e04b1bc5 261 }
youkee 0:1ad0e04b1bc5 262 break;
youkee 0:1ad0e04b1bc5 263
youkee 0:1ad0e04b1bc5 264 default:
youkee 0:1ad0e04b1bc5 265 PB_RETURN_ERROR(stream, "invalid field type");
youkee 0:1ad0e04b1bc5 266 }
youkee 0:1ad0e04b1bc5 267
youkee 0:1ad0e04b1bc5 268 return true;
youkee 0:1ad0e04b1bc5 269 }
youkee 0:1ad0e04b1bc5 270
youkee 0:1ad0e04b1bc5 271 /* Encode a field with callback semantics. This means that a user function is
youkee 0:1ad0e04b1bc5 272 * called to provide and encode the actual data. */
youkee 0:1ad0e04b1bc5 273 static bool checkreturn encode_callback_field(pb_ostream_t *stream,
youkee 0:1ad0e04b1bc5 274 const pb_field_t *field, const void *pData)
youkee 0:1ad0e04b1bc5 275 {
youkee 0:1ad0e04b1bc5 276 const pb_callback_t *callback = (const pb_callback_t*)pData;
youkee 0:1ad0e04b1bc5 277
youkee 0:1ad0e04b1bc5 278 #ifdef PB_OLD_CALLBACK_STYLE
youkee 0:1ad0e04b1bc5 279 const void *arg = callback->arg;
youkee 0:1ad0e04b1bc5 280 #else
youkee 0:1ad0e04b1bc5 281 void * const *arg = &(callback->arg);
youkee 0:1ad0e04b1bc5 282 #endif
youkee 0:1ad0e04b1bc5 283
youkee 0:1ad0e04b1bc5 284 if (callback->funcs.encode != NULL)
youkee 0:1ad0e04b1bc5 285 {
youkee 0:1ad0e04b1bc5 286 if (!callback->funcs.encode(stream, field, arg))
youkee 0:1ad0e04b1bc5 287 PB_RETURN_ERROR(stream, "callback error");
youkee 0:1ad0e04b1bc5 288 }
youkee 0:1ad0e04b1bc5 289 return true;
youkee 0:1ad0e04b1bc5 290 }
youkee 0:1ad0e04b1bc5 291
youkee 0:1ad0e04b1bc5 292 /* Encode a single field of any callback or static type. */
youkee 0:1ad0e04b1bc5 293 static bool checkreturn encode_field(pb_ostream_t *stream,
youkee 0:1ad0e04b1bc5 294 const pb_field_t *field, const void *pData)
youkee 0:1ad0e04b1bc5 295 {
youkee 0:1ad0e04b1bc5 296 switch (PB_ATYPE(field->type))
youkee 0:1ad0e04b1bc5 297 {
youkee 0:1ad0e04b1bc5 298 case PB_ATYPE_STATIC:
youkee 0:1ad0e04b1bc5 299 case PB_ATYPE_POINTER:
youkee 0:1ad0e04b1bc5 300 return encode_basic_field(stream, field, pData);
youkee 0:1ad0e04b1bc5 301
youkee 0:1ad0e04b1bc5 302 case PB_ATYPE_CALLBACK:
youkee 0:1ad0e04b1bc5 303 return encode_callback_field(stream, field, pData);
youkee 0:1ad0e04b1bc5 304
youkee 0:1ad0e04b1bc5 305 default:
youkee 0:1ad0e04b1bc5 306 PB_RETURN_ERROR(stream, "invalid field type");
youkee 0:1ad0e04b1bc5 307 }
youkee 0:1ad0e04b1bc5 308 }
youkee 0:1ad0e04b1bc5 309
youkee 0:1ad0e04b1bc5 310 /* Default handler for extension fields. Expects to have a pb_field_t
youkee 0:1ad0e04b1bc5 311 * pointer in the extension->type->arg field. */
youkee 0:1ad0e04b1bc5 312 static bool checkreturn default_extension_encoder(pb_ostream_t *stream,
youkee 0:1ad0e04b1bc5 313 const pb_extension_t *extension)
youkee 0:1ad0e04b1bc5 314 {
youkee 0:1ad0e04b1bc5 315 const pb_field_t *field = (const pb_field_t*)extension->type->arg;
youkee 0:1ad0e04b1bc5 316
youkee 0:1ad0e04b1bc5 317 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
youkee 0:1ad0e04b1bc5 318 {
youkee 0:1ad0e04b1bc5 319 /* For pointer extensions, the pointer is stored directly
youkee 0:1ad0e04b1bc5 320 * in the extension structure. This avoids having an extra
youkee 0:1ad0e04b1bc5 321 * indirection. */
youkee 0:1ad0e04b1bc5 322 return encode_field(stream, field, &extension->dest);
youkee 0:1ad0e04b1bc5 323 }
youkee 0:1ad0e04b1bc5 324 else
youkee 0:1ad0e04b1bc5 325 {
youkee 0:1ad0e04b1bc5 326 return encode_field(stream, field, extension->dest);
youkee 0:1ad0e04b1bc5 327 }
youkee 0:1ad0e04b1bc5 328 }
youkee 0:1ad0e04b1bc5 329
youkee 0:1ad0e04b1bc5 330 /* Walk through all the registered extensions and give them a chance
youkee 0:1ad0e04b1bc5 331 * to encode themselves. */
youkee 0:1ad0e04b1bc5 332 static bool checkreturn encode_extension_field(pb_ostream_t *stream,
youkee 0:1ad0e04b1bc5 333 const pb_field_t *field, const void *pData)
youkee 0:1ad0e04b1bc5 334 {
youkee 0:1ad0e04b1bc5 335 const pb_extension_t *extension = *(const pb_extension_t* const *)pData;
youkee 0:1ad0e04b1bc5 336 PB_UNUSED(field);
youkee 0:1ad0e04b1bc5 337
youkee 0:1ad0e04b1bc5 338 while (extension)
youkee 0:1ad0e04b1bc5 339 {
youkee 0:1ad0e04b1bc5 340 bool status;
youkee 0:1ad0e04b1bc5 341 if (extension->type->encode)
youkee 0:1ad0e04b1bc5 342 status = extension->type->encode(stream, extension);
youkee 0:1ad0e04b1bc5 343 else
youkee 0:1ad0e04b1bc5 344 status = default_extension_encoder(stream, extension);
youkee 0:1ad0e04b1bc5 345
youkee 0:1ad0e04b1bc5 346 if (!status)
youkee 0:1ad0e04b1bc5 347 return false;
youkee 0:1ad0e04b1bc5 348
youkee 0:1ad0e04b1bc5 349 extension = extension->next;
youkee 0:1ad0e04b1bc5 350 }
youkee 0:1ad0e04b1bc5 351
youkee 0:1ad0e04b1bc5 352 return true;
youkee 0:1ad0e04b1bc5 353 }
youkee 0:1ad0e04b1bc5 354
youkee 0:1ad0e04b1bc5 355 /*********************
youkee 0:1ad0e04b1bc5 356 * Encode all fields *
youkee 0:1ad0e04b1bc5 357 *********************/
youkee 0:1ad0e04b1bc5 358
youkee 0:1ad0e04b1bc5 359 static void *remove_const(const void *p)
youkee 0:1ad0e04b1bc5 360 {
youkee 0:1ad0e04b1bc5 361 /* Note: this casts away const, in order to use the common field iterator
youkee 0:1ad0e04b1bc5 362 * logic for both encoding and decoding. */
youkee 0:1ad0e04b1bc5 363 union {
youkee 0:1ad0e04b1bc5 364 void *p1;
youkee 0:1ad0e04b1bc5 365 const void *p2;
youkee 0:1ad0e04b1bc5 366 } t;
youkee 0:1ad0e04b1bc5 367 t.p2 = p;
youkee 0:1ad0e04b1bc5 368 return t.p1;
youkee 0:1ad0e04b1bc5 369 }
youkee 0:1ad0e04b1bc5 370
youkee 0:1ad0e04b1bc5 371 bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
youkee 0:1ad0e04b1bc5 372 {
youkee 0:1ad0e04b1bc5 373 pb_field_iter_t iter;
youkee 0:1ad0e04b1bc5 374 if (!pb_field_iter_begin(&iter, fields, remove_const(src_struct)))
youkee 0:1ad0e04b1bc5 375 return true; /* Empty message type */
youkee 0:1ad0e04b1bc5 376
youkee 0:1ad0e04b1bc5 377 do {
youkee 0:1ad0e04b1bc5 378 if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION)
youkee 0:1ad0e04b1bc5 379 {
youkee 0:1ad0e04b1bc5 380 /* Special case for the extension field placeholder */
youkee 0:1ad0e04b1bc5 381 if (!encode_extension_field(stream, iter.pos, iter.pData))
youkee 0:1ad0e04b1bc5 382 return false;
youkee 0:1ad0e04b1bc5 383 }
youkee 0:1ad0e04b1bc5 384 else
youkee 0:1ad0e04b1bc5 385 {
youkee 0:1ad0e04b1bc5 386 /* Regular field */
youkee 0:1ad0e04b1bc5 387 if (!encode_field(stream, iter.pos, iter.pData))
youkee 0:1ad0e04b1bc5 388 return false;
youkee 0:1ad0e04b1bc5 389 }
youkee 0:1ad0e04b1bc5 390 } while (pb_field_iter_next(&iter));
youkee 0:1ad0e04b1bc5 391
youkee 0:1ad0e04b1bc5 392 return true;
youkee 0:1ad0e04b1bc5 393 }
youkee 0:1ad0e04b1bc5 394
youkee 0:1ad0e04b1bc5 395 bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
youkee 0:1ad0e04b1bc5 396 {
youkee 0:1ad0e04b1bc5 397 return pb_encode_submessage(stream, fields, src_struct);
youkee 0:1ad0e04b1bc5 398 }
youkee 0:1ad0e04b1bc5 399
youkee 0:1ad0e04b1bc5 400 bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct)
youkee 0:1ad0e04b1bc5 401 {
youkee 0:1ad0e04b1bc5 402 pb_ostream_t stream = PB_OSTREAM_SIZING;
youkee 0:1ad0e04b1bc5 403
youkee 0:1ad0e04b1bc5 404 if (!pb_encode(&stream, fields, src_struct))
youkee 0:1ad0e04b1bc5 405 return false;
youkee 0:1ad0e04b1bc5 406
youkee 0:1ad0e04b1bc5 407 *size = stream.bytes_written;
youkee 0:1ad0e04b1bc5 408 return true;
youkee 0:1ad0e04b1bc5 409 }
youkee 0:1ad0e04b1bc5 410
youkee 0:1ad0e04b1bc5 411 /********************
youkee 0:1ad0e04b1bc5 412 * Helper functions *
youkee 0:1ad0e04b1bc5 413 ********************/
youkee 0:1ad0e04b1bc5 414 bool checkreturn pb_encode_varint(pb_ostream_t *stream, uint64_t value)
youkee 0:1ad0e04b1bc5 415 {
youkee 0:1ad0e04b1bc5 416 pb_byte_t buffer[10];
youkee 0:1ad0e04b1bc5 417 size_t i = 0;
youkee 0:1ad0e04b1bc5 418
youkee 0:1ad0e04b1bc5 419 if (value <= 0x7F)
youkee 0:1ad0e04b1bc5 420 {
youkee 0:1ad0e04b1bc5 421 pb_byte_t v = (pb_byte_t)value;
youkee 0:1ad0e04b1bc5 422 return pb_write(stream, &v, 1);
youkee 0:1ad0e04b1bc5 423 }
youkee 0:1ad0e04b1bc5 424
youkee 0:1ad0e04b1bc5 425 while (value)
youkee 0:1ad0e04b1bc5 426 {
youkee 0:1ad0e04b1bc5 427 buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80);
youkee 0:1ad0e04b1bc5 428 value >>= 7;
youkee 0:1ad0e04b1bc5 429 i++;
youkee 0:1ad0e04b1bc5 430 }
youkee 0:1ad0e04b1bc5 431 buffer[i-1] &= 0x7F; /* Unset top bit on last byte */
youkee 0:1ad0e04b1bc5 432
youkee 0:1ad0e04b1bc5 433 return pb_write(stream, buffer, i);
youkee 0:1ad0e04b1bc5 434 }
youkee 0:1ad0e04b1bc5 435
youkee 0:1ad0e04b1bc5 436 bool checkreturn pb_encode_svarint(pb_ostream_t *stream, int64_t value)
youkee 0:1ad0e04b1bc5 437 {
youkee 0:1ad0e04b1bc5 438 uint64_t zigzagged;
youkee 0:1ad0e04b1bc5 439 if (value < 0)
youkee 0:1ad0e04b1bc5 440 zigzagged = ~((uint64_t)value << 1);
youkee 0:1ad0e04b1bc5 441 else
youkee 0:1ad0e04b1bc5 442 zigzagged = (uint64_t)value << 1;
youkee 0:1ad0e04b1bc5 443
youkee 0:1ad0e04b1bc5 444 return pb_encode_varint(stream, zigzagged);
youkee 0:1ad0e04b1bc5 445 }
youkee 0:1ad0e04b1bc5 446
youkee 0:1ad0e04b1bc5 447 bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value)
youkee 0:1ad0e04b1bc5 448 {
youkee 0:1ad0e04b1bc5 449 uint32_t val = *(const uint32_t*)value;
youkee 0:1ad0e04b1bc5 450 pb_byte_t bytes[4];
youkee 0:1ad0e04b1bc5 451 bytes[0] = (pb_byte_t)(val & 0xFF);
youkee 0:1ad0e04b1bc5 452 bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
youkee 0:1ad0e04b1bc5 453 bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
youkee 0:1ad0e04b1bc5 454 bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
youkee 0:1ad0e04b1bc5 455 return pb_write(stream, bytes, 4);
youkee 0:1ad0e04b1bc5 456 }
youkee 0:1ad0e04b1bc5 457
youkee 0:1ad0e04b1bc5 458 bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value)
youkee 0:1ad0e04b1bc5 459 {
youkee 0:1ad0e04b1bc5 460 uint64_t val = *(const uint64_t*)value;
youkee 0:1ad0e04b1bc5 461 pb_byte_t bytes[8];
youkee 0:1ad0e04b1bc5 462 bytes[0] = (pb_byte_t)(val & 0xFF);
youkee 0:1ad0e04b1bc5 463 bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
youkee 0:1ad0e04b1bc5 464 bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
youkee 0:1ad0e04b1bc5 465 bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
youkee 0:1ad0e04b1bc5 466 bytes[4] = (pb_byte_t)((val >> 32) & 0xFF);
youkee 0:1ad0e04b1bc5 467 bytes[5] = (pb_byte_t)((val >> 40) & 0xFF);
youkee 0:1ad0e04b1bc5 468 bytes[6] = (pb_byte_t)((val >> 48) & 0xFF);
youkee 0:1ad0e04b1bc5 469 bytes[7] = (pb_byte_t)((val >> 56) & 0xFF);
youkee 0:1ad0e04b1bc5 470 return pb_write(stream, bytes, 8);
youkee 0:1ad0e04b1bc5 471 }
youkee 0:1ad0e04b1bc5 472
youkee 0:1ad0e04b1bc5 473 bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number)
youkee 0:1ad0e04b1bc5 474 {
youkee 0:1ad0e04b1bc5 475 uint64_t tag = ((uint64_t)field_number << 3) | wiretype;
youkee 0:1ad0e04b1bc5 476 return pb_encode_varint(stream, tag);
youkee 0:1ad0e04b1bc5 477 }
youkee 0:1ad0e04b1bc5 478
youkee 0:1ad0e04b1bc5 479 bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field)
youkee 0:1ad0e04b1bc5 480 {
youkee 0:1ad0e04b1bc5 481 pb_wire_type_t wiretype;
youkee 0:1ad0e04b1bc5 482 switch (PB_LTYPE(field->type))
youkee 0:1ad0e04b1bc5 483 {
youkee 0:1ad0e04b1bc5 484 case PB_LTYPE_VARINT:
youkee 0:1ad0e04b1bc5 485 case PB_LTYPE_UVARINT:
youkee 0:1ad0e04b1bc5 486 case PB_LTYPE_SVARINT:
youkee 0:1ad0e04b1bc5 487 wiretype = PB_WT_VARINT;
youkee 0:1ad0e04b1bc5 488 break;
youkee 0:1ad0e04b1bc5 489
youkee 0:1ad0e04b1bc5 490 case PB_LTYPE_FIXED32:
youkee 0:1ad0e04b1bc5 491 wiretype = PB_WT_32BIT;
youkee 0:1ad0e04b1bc5 492 break;
youkee 0:1ad0e04b1bc5 493
youkee 0:1ad0e04b1bc5 494 case PB_LTYPE_FIXED64:
youkee 0:1ad0e04b1bc5 495 wiretype = PB_WT_64BIT;
youkee 0:1ad0e04b1bc5 496 break;
youkee 0:1ad0e04b1bc5 497
youkee 0:1ad0e04b1bc5 498 case PB_LTYPE_BYTES:
youkee 0:1ad0e04b1bc5 499 case PB_LTYPE_STRING:
youkee 0:1ad0e04b1bc5 500 case PB_LTYPE_SUBMESSAGE:
youkee 0:1ad0e04b1bc5 501 wiretype = PB_WT_STRING;
youkee 0:1ad0e04b1bc5 502 break;
youkee 0:1ad0e04b1bc5 503
youkee 0:1ad0e04b1bc5 504 default:
youkee 0:1ad0e04b1bc5 505 PB_RETURN_ERROR(stream, "invalid field type");
youkee 0:1ad0e04b1bc5 506 }
youkee 0:1ad0e04b1bc5 507
youkee 0:1ad0e04b1bc5 508 return pb_encode_tag(stream, wiretype, field->tag);
youkee 0:1ad0e04b1bc5 509 }
youkee 0:1ad0e04b1bc5 510
youkee 0:1ad0e04b1bc5 511 bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size)
youkee 0:1ad0e04b1bc5 512 {
youkee 0:1ad0e04b1bc5 513 if (!pb_encode_varint(stream, (uint64_t)size))
youkee 0:1ad0e04b1bc5 514 return false;
youkee 0:1ad0e04b1bc5 515
youkee 0:1ad0e04b1bc5 516 return pb_write(stream, buffer, size);
youkee 0:1ad0e04b1bc5 517 }
youkee 0:1ad0e04b1bc5 518
youkee 0:1ad0e04b1bc5 519 bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
youkee 0:1ad0e04b1bc5 520 {
youkee 0:1ad0e04b1bc5 521 /* First calculate the message size using a non-writing substream. */
youkee 0:1ad0e04b1bc5 522 pb_ostream_t substream = PB_OSTREAM_SIZING;
youkee 0:1ad0e04b1bc5 523 size_t size;
youkee 0:1ad0e04b1bc5 524 bool status;
youkee 0:1ad0e04b1bc5 525
youkee 0:1ad0e04b1bc5 526 if (!pb_encode(&substream, fields, src_struct))
youkee 0:1ad0e04b1bc5 527 {
youkee 0:1ad0e04b1bc5 528 #ifndef PB_NO_ERRMSG
youkee 0:1ad0e04b1bc5 529 stream->errmsg = substream.errmsg;
youkee 0:1ad0e04b1bc5 530 #endif
youkee 0:1ad0e04b1bc5 531 return false;
youkee 0:1ad0e04b1bc5 532 }
youkee 0:1ad0e04b1bc5 533
youkee 0:1ad0e04b1bc5 534 size = substream.bytes_written;
youkee 0:1ad0e04b1bc5 535
youkee 0:1ad0e04b1bc5 536 if (!pb_encode_varint(stream, (uint64_t)size))
youkee 0:1ad0e04b1bc5 537 return false;
youkee 0:1ad0e04b1bc5 538
youkee 0:1ad0e04b1bc5 539 if (stream->callback == NULL)
youkee 0:1ad0e04b1bc5 540 return pb_write(stream, NULL, size); /* Just sizing */
youkee 0:1ad0e04b1bc5 541
youkee 0:1ad0e04b1bc5 542 if (stream->bytes_written + size > stream->max_size)
youkee 0:1ad0e04b1bc5 543 PB_RETURN_ERROR(stream, "stream full");
youkee 0:1ad0e04b1bc5 544
youkee 0:1ad0e04b1bc5 545 /* Use a substream to verify that a callback doesn't write more than
youkee 0:1ad0e04b1bc5 546 * what it did the first time. */
youkee 0:1ad0e04b1bc5 547 substream.callback = stream->callback;
youkee 0:1ad0e04b1bc5 548 substream.state = stream->state;
youkee 0:1ad0e04b1bc5 549 substream.max_size = size;
youkee 0:1ad0e04b1bc5 550 substream.bytes_written = 0;
youkee 0:1ad0e04b1bc5 551 #ifndef PB_NO_ERRMSG
youkee 0:1ad0e04b1bc5 552 substream.errmsg = NULL;
youkee 0:1ad0e04b1bc5 553 #endif
youkee 0:1ad0e04b1bc5 554
youkee 0:1ad0e04b1bc5 555 status = pb_encode(&substream, fields, src_struct);
youkee 0:1ad0e04b1bc5 556
youkee 0:1ad0e04b1bc5 557 stream->bytes_written += substream.bytes_written;
youkee 0:1ad0e04b1bc5 558 stream->state = substream.state;
youkee 0:1ad0e04b1bc5 559 #ifndef PB_NO_ERRMSG
youkee 0:1ad0e04b1bc5 560 stream->errmsg = substream.errmsg;
youkee 0:1ad0e04b1bc5 561 #endif
youkee 0:1ad0e04b1bc5 562
youkee 0:1ad0e04b1bc5 563 if (substream.bytes_written != size)
youkee 0:1ad0e04b1bc5 564 PB_RETURN_ERROR(stream, "submsg size changed");
youkee 0:1ad0e04b1bc5 565
youkee 0:1ad0e04b1bc5 566 return status;
youkee 0:1ad0e04b1bc5 567 }
youkee 0:1ad0e04b1bc5 568
youkee 0:1ad0e04b1bc5 569 /* Field encoders */
youkee 0:1ad0e04b1bc5 570
youkee 0:1ad0e04b1bc5 571 static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
youkee 0:1ad0e04b1bc5 572 {
youkee 0:1ad0e04b1bc5 573 int64_t value = 0;
youkee 0:1ad0e04b1bc5 574
youkee 0:1ad0e04b1bc5 575 if (field->data_size == sizeof(int_least8_t))
youkee 0:1ad0e04b1bc5 576 value = *(const int_least8_t*)src;
youkee 0:1ad0e04b1bc5 577 else if (field->data_size == sizeof(int_least16_t))
youkee 0:1ad0e04b1bc5 578 value = *(const int_least16_t*)src;
youkee 0:1ad0e04b1bc5 579 else if (field->data_size == sizeof(int32_t))
youkee 0:1ad0e04b1bc5 580 value = *(const int32_t*)src;
youkee 0:1ad0e04b1bc5 581 else if (field->data_size == sizeof(int64_t))
youkee 0:1ad0e04b1bc5 582 value = *(const int64_t*)src;
youkee 0:1ad0e04b1bc5 583 else
youkee 0:1ad0e04b1bc5 584 PB_RETURN_ERROR(stream, "invalid data_size");
youkee 0:1ad0e04b1bc5 585
youkee 0:1ad0e04b1bc5 586 return pb_encode_varint(stream, (uint64_t)value);
youkee 0:1ad0e04b1bc5 587 }
youkee 0:1ad0e04b1bc5 588
youkee 0:1ad0e04b1bc5 589 static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
youkee 0:1ad0e04b1bc5 590 {
youkee 0:1ad0e04b1bc5 591 uint64_t value = 0;
youkee 0:1ad0e04b1bc5 592
youkee 0:1ad0e04b1bc5 593 if (field->data_size == sizeof(uint_least8_t))
youkee 0:1ad0e04b1bc5 594 value = *(const uint_least8_t*)src;
youkee 0:1ad0e04b1bc5 595 else if (field->data_size == sizeof(uint_least16_t))
youkee 0:1ad0e04b1bc5 596 value = *(const uint_least16_t*)src;
youkee 0:1ad0e04b1bc5 597 else if (field->data_size == sizeof(uint32_t))
youkee 0:1ad0e04b1bc5 598 value = *(const uint32_t*)src;
youkee 0:1ad0e04b1bc5 599 else if (field->data_size == sizeof(uint64_t))
youkee 0:1ad0e04b1bc5 600 value = *(const uint64_t*)src;
youkee 0:1ad0e04b1bc5 601 else
youkee 0:1ad0e04b1bc5 602 PB_RETURN_ERROR(stream, "invalid data_size");
youkee 0:1ad0e04b1bc5 603
youkee 0:1ad0e04b1bc5 604 return pb_encode_varint(stream, value);
youkee 0:1ad0e04b1bc5 605 }
youkee 0:1ad0e04b1bc5 606
youkee 0:1ad0e04b1bc5 607 static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
youkee 0:1ad0e04b1bc5 608 {
youkee 0:1ad0e04b1bc5 609 int64_t value = 0;
youkee 0:1ad0e04b1bc5 610
youkee 0:1ad0e04b1bc5 611 if (field->data_size == sizeof(int_least8_t))
youkee 0:1ad0e04b1bc5 612 value = *(const int_least8_t*)src;
youkee 0:1ad0e04b1bc5 613 else if (field->data_size == sizeof(int_least16_t))
youkee 0:1ad0e04b1bc5 614 value = *(const int_least16_t*)src;
youkee 0:1ad0e04b1bc5 615 else if (field->data_size == sizeof(int32_t))
youkee 0:1ad0e04b1bc5 616 value = *(const int32_t*)src;
youkee 0:1ad0e04b1bc5 617 else if (field->data_size == sizeof(int64_t))
youkee 0:1ad0e04b1bc5 618 value = *(const int64_t*)src;
youkee 0:1ad0e04b1bc5 619 else
youkee 0:1ad0e04b1bc5 620 PB_RETURN_ERROR(stream, "invalid data_size");
youkee 0:1ad0e04b1bc5 621
youkee 0:1ad0e04b1bc5 622 return pb_encode_svarint(stream, value);
youkee 0:1ad0e04b1bc5 623 }
youkee 0:1ad0e04b1bc5 624
youkee 0:1ad0e04b1bc5 625 static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src)
youkee 0:1ad0e04b1bc5 626 {
youkee 0:1ad0e04b1bc5 627 PB_UNUSED(field);
youkee 0:1ad0e04b1bc5 628 return pb_encode_fixed64(stream, src);
youkee 0:1ad0e04b1bc5 629 }
youkee 0:1ad0e04b1bc5 630
youkee 0:1ad0e04b1bc5 631 static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src)
youkee 0:1ad0e04b1bc5 632 {
youkee 0:1ad0e04b1bc5 633 PB_UNUSED(field);
youkee 0:1ad0e04b1bc5 634 return pb_encode_fixed32(stream, src);
youkee 0:1ad0e04b1bc5 635 }
youkee 0:1ad0e04b1bc5 636
youkee 0:1ad0e04b1bc5 637 static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src)
youkee 0:1ad0e04b1bc5 638 {
youkee 0:1ad0e04b1bc5 639 const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)src;
youkee 0:1ad0e04b1bc5 640
youkee 0:1ad0e04b1bc5 641 if (src == NULL)
youkee 0:1ad0e04b1bc5 642 {
youkee 0:1ad0e04b1bc5 643 /* Threat null pointer as an empty bytes field */
youkee 0:1ad0e04b1bc5 644 return pb_encode_string(stream, NULL, 0);
youkee 0:1ad0e04b1bc5 645 }
youkee 0:1ad0e04b1bc5 646
youkee 0:1ad0e04b1bc5 647 if (PB_ATYPE(field->type) == PB_ATYPE_STATIC &&
youkee 0:1ad0e04b1bc5 648 PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size)
youkee 0:1ad0e04b1bc5 649 {
youkee 0:1ad0e04b1bc5 650 PB_RETURN_ERROR(stream, "bytes size exceeded");
youkee 0:1ad0e04b1bc5 651 }
youkee 0:1ad0e04b1bc5 652
youkee 0:1ad0e04b1bc5 653 return pb_encode_string(stream, bytes->bytes, bytes->size);
youkee 0:1ad0e04b1bc5 654 }
youkee 0:1ad0e04b1bc5 655
youkee 0:1ad0e04b1bc5 656 static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src)
youkee 0:1ad0e04b1bc5 657 {
youkee 0:1ad0e04b1bc5 658 size_t size = 0;
youkee 0:1ad0e04b1bc5 659 size_t max_size = field->data_size;
youkee 0:1ad0e04b1bc5 660 const char *p = (const char*)src;
youkee 0:1ad0e04b1bc5 661
youkee 0:1ad0e04b1bc5 662 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
youkee 0:1ad0e04b1bc5 663 max_size = (size_t)-1;
youkee 0:1ad0e04b1bc5 664
youkee 0:1ad0e04b1bc5 665 if (src == NULL)
youkee 0:1ad0e04b1bc5 666 {
youkee 0:1ad0e04b1bc5 667 size = 0; /* Threat null pointer as an empty string */
youkee 0:1ad0e04b1bc5 668 }
youkee 0:1ad0e04b1bc5 669 else
youkee 0:1ad0e04b1bc5 670 {
youkee 0:1ad0e04b1bc5 671 /* strnlen() is not always available, so just use a loop */
youkee 0:1ad0e04b1bc5 672 while (size < max_size && *p != '\0')
youkee 0:1ad0e04b1bc5 673 {
youkee 0:1ad0e04b1bc5 674 size++;
youkee 0:1ad0e04b1bc5 675 p++;
youkee 0:1ad0e04b1bc5 676 }
youkee 0:1ad0e04b1bc5 677 }
youkee 0:1ad0e04b1bc5 678
youkee 0:1ad0e04b1bc5 679 return pb_encode_string(stream, (const pb_byte_t*)src, size);
youkee 0:1ad0e04b1bc5 680 }
youkee 0:1ad0e04b1bc5 681
youkee 0:1ad0e04b1bc5 682 static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src)
youkee 0:1ad0e04b1bc5 683 {
youkee 0:1ad0e04b1bc5 684 if (field->ptr == NULL)
youkee 0:1ad0e04b1bc5 685 PB_RETURN_ERROR(stream, "invalid field descriptor");
youkee 0:1ad0e04b1bc5 686
youkee 0:1ad0e04b1bc5 687 return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src);
youkee 0:1ad0e04b1bc5 688 }