Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of LinkNode-Test by
pb_encode.c
00001 /* pb_encode.c -- encode a protobuf using minimal resources 00002 * 00003 * 2011 Petteri Aimonen <jpa@kapsi.fi> 00004 */ 00005 00006 #include "pb.h" 00007 #include "pb_encode.h" 00008 #include "pb_common.h" 00009 00010 /* Use the GCC warn_unused_result attribute to check that all return values 00011 * are propagated correctly. On other compilers and gcc before 3.4.0 just 00012 * ignore the annotation. 00013 */ 00014 #if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) 00015 #define checkreturn 00016 #else 00017 #define checkreturn __attribute__((warn_unused_result)) 00018 #endif 00019 00020 /************************************** 00021 * Declarations internal to this file * 00022 **************************************/ 00023 typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn; 00024 00025 static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); 00026 static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func); 00027 static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); 00028 static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension); 00029 static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); 00030 static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src); 00031 static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); 00032 static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); 00033 static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src); 00034 static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src); 00035 static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); 00036 static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src); 00037 static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src); 00038 00039 /* --- Function pointers to field encoders --- 00040 * Order in the array must match pb_action_t LTYPE numbering. 00041 */ 00042 static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = { 00043 &pb_enc_varint, 00044 &pb_enc_uvarint, 00045 &pb_enc_svarint, 00046 &pb_enc_fixed32, 00047 &pb_enc_fixed64, 00048 00049 &pb_enc_bytes, 00050 &pb_enc_string, 00051 &pb_enc_submessage, 00052 NULL /* extensions */ 00053 }; 00054 00055 /******************************* 00056 * pb_ostream_t implementation * 00057 *******************************/ 00058 00059 static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) 00060 { 00061 pb_byte_t *dest = (pb_byte_t*)stream->state; 00062 stream->state = dest + count; 00063 00064 while (count--) 00065 *dest++ = *buf++; 00066 00067 return true; 00068 } 00069 00070 pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize) 00071 { 00072 pb_ostream_t stream; 00073 #ifdef PB_BUFFER_ONLY 00074 stream.callback = (void*)1; /* Just a marker value */ 00075 #else 00076 stream.callback = &buf_write; 00077 #endif 00078 stream.state = buf; 00079 stream.max_size = bufsize; 00080 stream.bytes_written = 0; 00081 #ifndef PB_NO_ERRMSG 00082 stream.errmsg = NULL; 00083 #endif 00084 return stream; 00085 } 00086 00087 bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) 00088 { 00089 if (stream->callback != NULL) 00090 { 00091 if (stream->bytes_written + count > stream->max_size) 00092 PB_RETURN_ERROR(stream, "stream full"); 00093 00094 #ifdef PB_BUFFER_ONLY 00095 if (!buf_write(stream, buf, count)) 00096 PB_RETURN_ERROR(stream, "io error"); 00097 #else 00098 if (!stream->callback(stream, buf, count)) 00099 PB_RETURN_ERROR(stream, "io error"); 00100 #endif 00101 } 00102 00103 stream->bytes_written += count; 00104 return true; 00105 } 00106 00107 /************************* 00108 * Encode a single field * 00109 *************************/ 00110 00111 /* Encode a static array. Handles the size calculations and possible packing. */ 00112 static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, 00113 const void *pData, size_t count, pb_encoder_t func) 00114 { 00115 size_t i; 00116 const void *p; 00117 size_t size; 00118 00119 if (count == 0) 00120 return true; 00121 00122 if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) 00123 PB_RETURN_ERROR(stream, "array max size exceeded"); 00124 00125 /* We always pack arrays if the datatype allows it. */ 00126 if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) 00127 { 00128 if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) 00129 return false; 00130 00131 /* Determine the total size of packed array. */ 00132 if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) 00133 { 00134 size = 4 * count; 00135 } 00136 else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) 00137 { 00138 size = 8 * count; 00139 } 00140 else 00141 { 00142 pb_ostream_t sizestream = PB_OSTREAM_SIZING; 00143 p = pData; 00144 for (i = 0; i < count; i++) 00145 { 00146 if (!func(&sizestream, field, p)) 00147 return false; 00148 p = (const char*)p + field->data_size; 00149 } 00150 size = sizestream.bytes_written; 00151 } 00152 00153 if (!pb_encode_varint(stream, (uint64_t)size)) 00154 return false; 00155 00156 if (stream->callback == NULL) 00157 return pb_write(stream, NULL, size); /* Just sizing.. */ 00158 00159 /* Write the data */ 00160 p = pData; 00161 for (i = 0; i < count; i++) 00162 { 00163 if (!func(stream, field, p)) 00164 return false; 00165 p = (const char*)p + field->data_size; 00166 } 00167 } 00168 else 00169 { 00170 p = pData; 00171 for (i = 0; i < count; i++) 00172 { 00173 if (!pb_encode_tag_for_field(stream, field)) 00174 return false; 00175 00176 /* Normally the data is stored directly in the array entries, but 00177 * for pointer-type string and bytes fields, the array entries are 00178 * actually pointers themselves also. So we have to dereference once 00179 * more to get to the actual data. */ 00180 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER && 00181 (PB_LTYPE(field->type) == PB_LTYPE_STRING || 00182 PB_LTYPE(field->type) == PB_LTYPE_BYTES)) 00183 { 00184 if (!func(stream, field, *(const void* const*)p)) 00185 return false; 00186 } 00187 else 00188 { 00189 if (!func(stream, field, p)) 00190 return false; 00191 } 00192 p = (const char*)p + field->data_size; 00193 } 00194 } 00195 00196 return true; 00197 } 00198 00199 /* Encode a field with static or pointer allocation, i.e. one whose data 00200 * is available to the encoder directly. */ 00201 static bool checkreturn encode_basic_field(pb_ostream_t *stream, 00202 const pb_field_t *field, const void *pData) 00203 { 00204 pb_encoder_t func; 00205 const void *pSize; 00206 bool implicit_has = true; 00207 00208 func = PB_ENCODERS[PB_LTYPE(field->type)]; 00209 00210 if (field->size_offset) 00211 pSize = (const char*)pData + field->size_offset; 00212 else 00213 pSize = &implicit_has; 00214 00215 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) 00216 { 00217 /* pData is a pointer to the field, which contains pointer to 00218 * the data. If the 2nd pointer is NULL, it is interpreted as if 00219 * the has_field was false. 00220 */ 00221 00222 pData = *(const void* const*)pData; 00223 implicit_has = (pData != NULL); 00224 } 00225 00226 switch (PB_HTYPE(field->type)) 00227 { 00228 case PB_HTYPE_REQUIRED: 00229 if (!pData) 00230 PB_RETURN_ERROR(stream, "missing required field"); 00231 if (!pb_encode_tag_for_field(stream, field)) 00232 return false; 00233 if (!func(stream, field, pData)) 00234 return false; 00235 break; 00236 00237 case PB_HTYPE_OPTIONAL: 00238 if (*(const bool*)pSize) 00239 { 00240 if (!pb_encode_tag_for_field(stream, field)) 00241 return false; 00242 00243 if (!func(stream, field, pData)) 00244 return false; 00245 } 00246 break; 00247 00248 case PB_HTYPE_REPEATED: 00249 if (!encode_array(stream, field, pData, *(const pb_size_t*)pSize, func)) 00250 return false; 00251 break; 00252 00253 case PB_HTYPE_ONEOF: 00254 if (*(const pb_size_t*)pSize == field->tag) 00255 { 00256 if (!pb_encode_tag_for_field(stream, field)) 00257 return false; 00258 00259 if (!func(stream, field, pData)) 00260 return false; 00261 } 00262 break; 00263 00264 default: 00265 PB_RETURN_ERROR(stream, "invalid field type"); 00266 } 00267 00268 return true; 00269 } 00270 00271 /* Encode a field with callback semantics. This means that a user function is 00272 * called to provide and encode the actual data. */ 00273 static bool checkreturn encode_callback_field(pb_ostream_t *stream, 00274 const pb_field_t *field, const void *pData) 00275 { 00276 const pb_callback_t *callback = (const pb_callback_t*)pData; 00277 00278 #ifdef PB_OLD_CALLBACK_STYLE 00279 const void *arg = callback->arg; 00280 #else 00281 void * const *arg = &(callback->arg); 00282 #endif 00283 00284 if (callback->funcs.encode != NULL) 00285 { 00286 if (!callback->funcs.encode(stream, field, arg)) 00287 PB_RETURN_ERROR(stream, "callback error"); 00288 } 00289 return true; 00290 } 00291 00292 /* Encode a single field of any callback or static type. */ 00293 static bool checkreturn encode_field(pb_ostream_t *stream, 00294 const pb_field_t *field, const void *pData) 00295 { 00296 switch (PB_ATYPE(field->type)) 00297 { 00298 case PB_ATYPE_STATIC: 00299 case PB_ATYPE_POINTER: 00300 return encode_basic_field(stream, field, pData); 00301 00302 case PB_ATYPE_CALLBACK: 00303 return encode_callback_field(stream, field, pData); 00304 00305 default: 00306 PB_RETURN_ERROR(stream, "invalid field type"); 00307 } 00308 } 00309 00310 /* Default handler for extension fields. Expects to have a pb_field_t 00311 * pointer in the extension->type->arg field. */ 00312 static bool checkreturn default_extension_encoder(pb_ostream_t *stream, 00313 const pb_extension_t *extension) 00314 { 00315 const pb_field_t *field = (const pb_field_t*)extension->type->arg; 00316 00317 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) 00318 { 00319 /* For pointer extensions, the pointer is stored directly 00320 * in the extension structure. This avoids having an extra 00321 * indirection. */ 00322 return encode_field(stream, field, &extension->dest); 00323 } 00324 else 00325 { 00326 return encode_field(stream, field, extension->dest); 00327 } 00328 } 00329 00330 /* Walk through all the registered extensions and give them a chance 00331 * to encode themselves. */ 00332 static bool checkreturn encode_extension_field(pb_ostream_t *stream, 00333 const pb_field_t *field, const void *pData) 00334 { 00335 const pb_extension_t *extension = *(const pb_extension_t* const *)pData; 00336 PB_UNUSED(field); 00337 00338 while (extension) 00339 { 00340 bool status; 00341 if (extension->type->encode) 00342 status = extension->type->encode(stream, extension); 00343 else 00344 status = default_extension_encoder(stream, extension); 00345 00346 if (!status) 00347 return false; 00348 00349 extension = extension->next; 00350 } 00351 00352 return true; 00353 } 00354 00355 /********************* 00356 * Encode all fields * 00357 *********************/ 00358 00359 static void *remove_const(const void *p) 00360 { 00361 /* Note: this casts away const, in order to use the common field iterator 00362 * logic for both encoding and decoding. */ 00363 union { 00364 void *p1; 00365 const void *p2; 00366 } t; 00367 t.p2 = p; 00368 return t.p1; 00369 } 00370 00371 bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) 00372 { 00373 pb_field_iter_t iter; 00374 if (!pb_field_iter_begin(&iter, fields, remove_const(src_struct))) 00375 return true; /* Empty message type */ 00376 00377 do { 00378 if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION) 00379 { 00380 /* Special case for the extension field placeholder */ 00381 if (!encode_extension_field(stream, iter.pos, iter.pData)) 00382 return false; 00383 } 00384 else 00385 { 00386 /* Regular field */ 00387 if (!encode_field(stream, iter.pos, iter.pData)) 00388 return false; 00389 } 00390 } while (pb_field_iter_next(&iter)); 00391 00392 return true; 00393 } 00394 00395 bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) 00396 { 00397 return pb_encode_submessage(stream, fields, src_struct); 00398 } 00399 00400 bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct) 00401 { 00402 pb_ostream_t stream = PB_OSTREAM_SIZING; 00403 00404 if (!pb_encode(&stream, fields, src_struct)) 00405 return false; 00406 00407 *size = stream.bytes_written; 00408 return true; 00409 } 00410 00411 /******************** 00412 * Helper functions * 00413 ********************/ 00414 bool checkreturn pb_encode_varint(pb_ostream_t *stream, uint64_t value) 00415 { 00416 pb_byte_t buffer[10]; 00417 size_t i = 0; 00418 00419 if (value <= 0x7F) 00420 { 00421 pb_byte_t v = (pb_byte_t)value; 00422 return pb_write(stream, &v, 1); 00423 } 00424 00425 while (value) 00426 { 00427 buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); 00428 value >>= 7; 00429 i++; 00430 } 00431 buffer[i-1] &= 0x7F; /* Unset top bit on last byte */ 00432 00433 return pb_write(stream, buffer, i); 00434 } 00435 00436 bool checkreturn pb_encode_svarint(pb_ostream_t *stream, int64_t value) 00437 { 00438 uint64_t zigzagged; 00439 if (value < 0) 00440 zigzagged = ~((uint64_t)value << 1); 00441 else 00442 zigzagged = (uint64_t)value << 1; 00443 00444 return pb_encode_varint(stream, zigzagged); 00445 } 00446 00447 bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) 00448 { 00449 uint32_t val = *(const uint32_t*)value; 00450 pb_byte_t bytes[4]; 00451 bytes[0] = (pb_byte_t)(val & 0xFF); 00452 bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); 00453 bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); 00454 bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); 00455 return pb_write(stream, bytes, 4); 00456 } 00457 00458 bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) 00459 { 00460 uint64_t val = *(const uint64_t*)value; 00461 pb_byte_t bytes[8]; 00462 bytes[0] = (pb_byte_t)(val & 0xFF); 00463 bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); 00464 bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); 00465 bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); 00466 bytes[4] = (pb_byte_t)((val >> 32) & 0xFF); 00467 bytes[5] = (pb_byte_t)((val >> 40) & 0xFF); 00468 bytes[6] = (pb_byte_t)((val >> 48) & 0xFF); 00469 bytes[7] = (pb_byte_t)((val >> 56) & 0xFF); 00470 return pb_write(stream, bytes, 8); 00471 } 00472 00473 bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number) 00474 { 00475 uint64_t tag = ((uint64_t)field_number << 3) | wiretype; 00476 return pb_encode_varint(stream, tag); 00477 } 00478 00479 bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field) 00480 { 00481 pb_wire_type_t wiretype; 00482 switch (PB_LTYPE(field->type)) 00483 { 00484 case PB_LTYPE_VARINT: 00485 case PB_LTYPE_UVARINT: 00486 case PB_LTYPE_SVARINT: 00487 wiretype = PB_WT_VARINT; 00488 break; 00489 00490 case PB_LTYPE_FIXED32: 00491 wiretype = PB_WT_32BIT; 00492 break; 00493 00494 case PB_LTYPE_FIXED64: 00495 wiretype = PB_WT_64BIT; 00496 break; 00497 00498 case PB_LTYPE_BYTES: 00499 case PB_LTYPE_STRING: 00500 case PB_LTYPE_SUBMESSAGE: 00501 wiretype = PB_WT_STRING; 00502 break; 00503 00504 default: 00505 PB_RETURN_ERROR(stream, "invalid field type"); 00506 } 00507 00508 return pb_encode_tag(stream, wiretype, field->tag); 00509 } 00510 00511 bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size) 00512 { 00513 if (!pb_encode_varint(stream, (uint64_t)size)) 00514 return false; 00515 00516 return pb_write(stream, buffer, size); 00517 } 00518 00519 bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) 00520 { 00521 /* First calculate the message size using a non-writing substream. */ 00522 pb_ostream_t substream = PB_OSTREAM_SIZING; 00523 size_t size; 00524 bool status; 00525 00526 if (!pb_encode(&substream, fields, src_struct)) 00527 { 00528 #ifndef PB_NO_ERRMSG 00529 stream->errmsg = substream.errmsg; 00530 #endif 00531 return false; 00532 } 00533 00534 size = substream.bytes_written; 00535 00536 if (!pb_encode_varint(stream, (uint64_t)size)) 00537 return false; 00538 00539 if (stream->callback == NULL) 00540 return pb_write(stream, NULL, size); /* Just sizing */ 00541 00542 if (stream->bytes_written + size > stream->max_size) 00543 PB_RETURN_ERROR(stream, "stream full"); 00544 00545 /* Use a substream to verify that a callback doesn't write more than 00546 * what it did the first time. */ 00547 substream.callback = stream->callback; 00548 substream.state = stream->state; 00549 substream.max_size = size; 00550 substream.bytes_written = 0; 00551 #ifndef PB_NO_ERRMSG 00552 substream.errmsg = NULL; 00553 #endif 00554 00555 status = pb_encode(&substream, fields, src_struct); 00556 00557 stream->bytes_written += substream.bytes_written; 00558 stream->state = substream.state; 00559 #ifndef PB_NO_ERRMSG 00560 stream->errmsg = substream.errmsg; 00561 #endif 00562 00563 if (substream.bytes_written != size) 00564 PB_RETURN_ERROR(stream, "submsg size changed"); 00565 00566 return status; 00567 } 00568 00569 /* Field encoders */ 00570 00571 static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src) 00572 { 00573 int64_t value = 0; 00574 00575 if (field->data_size == sizeof(int_least8_t)) 00576 value = *(const int_least8_t*)src; 00577 else if (field->data_size == sizeof(int_least16_t)) 00578 value = *(const int_least16_t*)src; 00579 else if (field->data_size == sizeof(int32_t)) 00580 value = *(const int32_t*)src; 00581 else if (field->data_size == sizeof(int64_t)) 00582 value = *(const int64_t*)src; 00583 else 00584 PB_RETURN_ERROR(stream, "invalid data_size"); 00585 00586 return pb_encode_varint(stream, (uint64_t)value); 00587 } 00588 00589 static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) 00590 { 00591 uint64_t value = 0; 00592 00593 if (field->data_size == sizeof(uint_least8_t)) 00594 value = *(const uint_least8_t*)src; 00595 else if (field->data_size == sizeof(uint_least16_t)) 00596 value = *(const uint_least16_t*)src; 00597 else if (field->data_size == sizeof(uint32_t)) 00598 value = *(const uint32_t*)src; 00599 else if (field->data_size == sizeof(uint64_t)) 00600 value = *(const uint64_t*)src; 00601 else 00602 PB_RETURN_ERROR(stream, "invalid data_size"); 00603 00604 return pb_encode_varint(stream, value); 00605 } 00606 00607 static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) 00608 { 00609 int64_t value = 0; 00610 00611 if (field->data_size == sizeof(int_least8_t)) 00612 value = *(const int_least8_t*)src; 00613 else if (field->data_size == sizeof(int_least16_t)) 00614 value = *(const int_least16_t*)src; 00615 else if (field->data_size == sizeof(int32_t)) 00616 value = *(const int32_t*)src; 00617 else if (field->data_size == sizeof(int64_t)) 00618 value = *(const int64_t*)src; 00619 else 00620 PB_RETURN_ERROR(stream, "invalid data_size"); 00621 00622 return pb_encode_svarint(stream, value); 00623 } 00624 00625 static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src) 00626 { 00627 PB_UNUSED(field); 00628 return pb_encode_fixed64(stream, src); 00629 } 00630 00631 static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src) 00632 { 00633 PB_UNUSED(field); 00634 return pb_encode_fixed32(stream, src); 00635 } 00636 00637 static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) 00638 { 00639 const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)src; 00640 00641 if (src == NULL) 00642 { 00643 /* Threat null pointer as an empty bytes field */ 00644 return pb_encode_string(stream, NULL, 0); 00645 } 00646 00647 if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && 00648 PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size) 00649 { 00650 PB_RETURN_ERROR(stream, "bytes size exceeded"); 00651 } 00652 00653 return pb_encode_string(stream, bytes->bytes, bytes->size); 00654 } 00655 00656 static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src) 00657 { 00658 size_t size = 0; 00659 size_t max_size = field->data_size; 00660 const char *p = (const char*)src; 00661 00662 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) 00663 max_size = (size_t)-1; 00664 00665 if (src == NULL) 00666 { 00667 size = 0; /* Threat null pointer as an empty string */ 00668 } 00669 else 00670 { 00671 /* strnlen() is not always available, so just use a loop */ 00672 while (size < max_size && *p != '\0') 00673 { 00674 size++; 00675 p++; 00676 } 00677 } 00678 00679 return pb_encode_string(stream, (const pb_byte_t*)src, size); 00680 } 00681 00682 static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src) 00683 { 00684 if (field->ptr == NULL) 00685 PB_RETURN_ERROR(stream, "invalid field descriptor"); 00686 00687 return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src); 00688 }
Generated on Tue Jul 12 2022 16:00:22 by
