bool pb_field_iter_next(pb_field_iter_t *iter) { const pb_field_t *prev_field = iter->pos; if (prev_field->tag == 0) { /* Handle empty message types, where the first field is already the terminator. * In other cases, the iter->pos never points to the terminator. */ return false; } iter->pos++; if (iter->pos->tag == 0) { /* Wrapped back to beginning, reinitialize */ (void)pb_field_iter_begin(iter, iter->start, iter->dest_struct); return false; } else { /* Increment the pointers based on previous field size */ size_t prev_size = prev_field->data_size; if (PB_HTYPE(prev_field->type) == PB_HTYPE_ONEOF && PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF) { /* Don't advance pointers inside unions */ prev_size = 0; iter->pData = (char*)iter->pData - prev_field->data_offset; } else if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC && PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED) { /* In static arrays, the data_size tells the size of a single entry and * array_size is the number of entries */ prev_size *= prev_field->array_size; } else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER) { /* Pointer fields always have a constant size in the main structure. * The data_size only applies to the dynamically allocated area. */ prev_size = sizeof(void*); } if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED) { /* Count the required fields, in order to check their presence in the * decoder. */ iter->required_field_index++; } iter->pData = (char*)iter->pData + prev_size + iter->pos->data_offset; iter->pSize = (char*)iter->pData + iter->pos->size_offset; return true; } }
/* This function is the core of the union encoding process. It handles * the top-level pb_field_t array manually, in order to encode a correct * field tag before the message. The pointer to MsgType_fields array is * used as an unique identifier for the message type. */ bool encode_unionmessage(pb_ostream_t *stream, const pb_msgdesc_t *messagetype, void *message) { pb_field_iter_t iter; if (!pb_field_iter_begin(&iter, UnionMessage_fields, message)) return false; do { if (iter.submsg_desc == messagetype) { /* This is our field, encode the message using it. */ if (!pb_encode_tag_for_field(stream, &iter)) return false; return pb_encode_submessage(stream, messagetype, message); } } while (pb_field_iter_next(&iter)); /* Didn't find the field for messagetype */ return false; }
bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) { pb_field_iter_t iter; if (!pb_field_iter_begin(&iter, fields, remove_const(src_struct))) return true; /* Empty message type */ do { if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION) { /* Special case for the extension field placeholder */ if (!encode_extension_field(stream, iter.pos, iter.pData)) return false; } else { /* Regular field */ if (!encode_field(stream, iter.pos, iter.pData)) return false; } } while (pb_field_iter_next(&iter)); return true; }