static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter) { pb_callback_t *pCallback = (pb_callback_t*)iter->pData; #ifdef PB_OLD_CALLBACK_STYLE void *arg = pCallback->arg; #else void **arg = &(pCallback->arg); #endif if (pCallback->funcs.decode == NULL) return pb_skip_field(stream, wire_type); if (wire_type == PB_WT_STRING) { pb_istream_t substream; if (!pb_make_string_substream(stream, &substream)) return false; do { if (!pCallback->funcs.decode(&substream, iter->pos, arg)) PB_RETURN_ERROR(stream, "callback failed"); } while (substream.bytes_left); pb_close_string_substream(stream, &substream); return true; } else { /* Copy the single scalar value to stack. * This is required so that we can limit the stream length, * which in turn allows to use same callback for packed and * not-packed fields. */ pb_istream_t substream; uint8_t buffer[10]; size_t size = sizeof(buffer); if (!read_raw_value(stream, wire_type, buffer, &size)) return false; substream = pb_istream_from_buffer(buffer, size); return pCallback->funcs.decode(&substream, iter->pos, arg); } }
const pb_field_t* decodeMotorMsgType(pb_istream_t *stream) { pb_wire_type_t wire_type; uint32_t tag; bool eof; while (pb_decode_tag(stream, &wire_type, &tag, &eof)) { if (wire_type == PB_WT_STRING) { const pb_field_t *field; for (field = MotorMsg_fields; field->tag != 0; field++) { if (field->tag == tag && ((field->type & PB_LTYPE_MASK) == PB_LTYPE_SUBMESSAGE)) { return field->ptr; } } } pb_skip_field(stream, wire_type); } return NULL; }
bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) { uint8_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 7) / 8] = {0}; /* Used to check for required fields */ pb_field_iterator_t iter; pb_field_init(&iter, fields, dest_struct); while (stream->bytes_left) { uint32_t tag; pb_wire_type_t wire_type; bool eof; if (!pb_decode_tag(stream, &wire_type, &tag, &eof)) { if (eof) break; else return false; } if (!pb_field_find(&iter, tag)) { /* No match found, skip data */ if (!pb_skip_field(stream, wire_type)) return false; continue; } if (PB_HTYPE(iter.current->type) == PB_HTYPE_REQUIRED && iter.required_field_index < PB_MAX_REQUIRED_FIELDS) { fields_seen[iter.required_field_index >> 3] |= (uint8_t)(1 << (iter.required_field_index & 7)); } if (!decode_field(stream, wire_type, &iter)) return false; }
static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter) { pb_decoder_t func = PB_DECODERS[PB_LTYPE(iter->current->type)]; switch (PB_HTYPE(iter->current->type)) { case PB_HTYPE_REQUIRED: return func(stream, iter->current, iter->pData); case PB_HTYPE_OPTIONAL: *(bool*)iter->pSize = true; return func(stream, iter->current, iter->pData); case PB_HTYPE_ARRAY: if (wire_type == PB_WT_STRING && PB_LTYPE(iter->current->type) <= PB_LTYPE_LAST_PACKABLE) { /* Packed array */ bool status; size_t *size = (size_t*)iter->pSize; pb_istream_t substream; if (!pb_make_string_substream(stream, &substream)) return false; while (substream.bytes_left && *size < iter->current->array_size) { void *pItem = (uint8_t*)iter->pData + iter->current->data_size * (*size); if (!func(&substream, iter->current, pItem)) return false; (*size)++; } status = (substream.bytes_left == 0); pb_close_string_substream(stream, &substream); return status; } else { /* Repeated field */ size_t *size = (size_t*)iter->pSize; void *pItem = (uint8_t*)iter->pData + iter->current->data_size * (*size); if (*size >= iter->current->array_size) PB_RETURN_ERROR(stream, "array overflow"); (*size)++; return func(stream, iter->current, pItem); } case PB_HTYPE_CALLBACK: { pb_callback_t *pCallback = (pb_callback_t*)iter->pData; if (pCallback->funcs.decode == NULL) return pb_skip_field(stream, wire_type); if (wire_type == PB_WT_STRING) { pb_istream_t substream; if (!pb_make_string_substream(stream, &substream)) return false; while (substream.bytes_left) { if (!pCallback->funcs.decode(&substream, iter->current, pCallback->arg)) PB_RETURN_ERROR(stream, "callback failed"); } pb_close_string_substream(stream, &substream); return true; } else { /* Copy the single scalar value to stack. * This is required so that we can limit the stream length, * which in turn allows to use same callback for packed and * not-packed fields. */ pb_istream_t substream; uint8_t buffer[10]; size_t size = sizeof(buffer); if (!read_raw_value(stream, wire_type, buffer, &size)) return false; substream = pb_istream_from_buffer(buffer, size); return pCallback->funcs.decode(&substream, iter->current, pCallback->arg); } } default: PB_RETURN_ERROR(stream, "invalid field type"); } }
bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) { uint8_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 7) / 8] = {0}; /* Used to check for required fields */ uint32_t extension_range_start = 0; pb_field_iterator_t iter; pb_field_init(&iter, fields, dest_struct); while (stream->bytes_left) { uint32_t tag; pb_wire_type_t wire_type; bool eof; if (!pb_decode_tag(stream, &wire_type, &tag, &eof)) { if (eof) break; else return false; } if (!pb_field_find(&iter, tag)) { /* No match found, check if it matches an extension. */ if (tag >= extension_range_start) { if (!find_extension_field(&iter)) extension_range_start = (uint32_t)-1; else extension_range_start = iter.pos->tag; if (tag >= extension_range_start) { size_t pos = stream->bytes_left; if (!decode_extension(stream, tag, wire_type, &iter)) return false; if (pos != stream->bytes_left) { /* The field was handled */ continue; } } } /* No match found, skip data */ if (!pb_skip_field(stream, wire_type)) return false; continue; } if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REQUIRED && iter.required_field_index < PB_MAX_REQUIRED_FIELDS) { fields_seen[iter.required_field_index >> 3] |= (uint8_t)(1 << (iter.required_field_index & 7)); } if (!decode_field(stream, wire_type, &iter)) return false; }