bool print_container(pb_istream_t *stream) { uint64_t type, msgtype; uint32_t length, tag; pb_wire_type_t wiretype; bool eof; // decode the type tag if (!pb_decode_tag(stream, &wiretype, &tag, &eof)) { printf("Parsing tag#1 failed: %s\n", PB_GET_ERROR(stream)); } if (!pb_decode_varint(stream, &type)) { printf("Parsing required type field#1 failed: %s\n", PB_GET_ERROR(stream)); } if (!pb_decode_tag(stream, &wiretype, &tag, &eof)) { printf("Parsing tag#2 failed: %s\n", PB_GET_ERROR(stream)); } assert(tag == 1); // tag number of length field assert(wiretype == 5); // encoding of length field = fixed32 if (!pb_decode_fixed32(stream, &length)) { printf("Parsing field#1 failed: %s\n", PB_GET_ERROR(stream)); } printf("wiretype=%d tag=%d fixed32=%d (total message length)\n", wiretype, tag, length); if (!pb_decode_tag(stream, &wiretype, &tag, &eof)) { printf("Parsing tag#2 failed: %s\n", PB_GET_ERROR(stream)); } assert(tag == 2); // tag number of type field assert(wiretype == 0); // encoding of length field = varint if (!pb_decode_varint(stream, &msgtype)) { printf("Parsing field#2 failed: %s\n", PB_GET_ERROR(stream)); } printf("wiretype=%d tag=%d varint=%llu (msgtype)\n", wiretype, tag, msgtype); // the actual message follows. // It is a submessage encoded in length-delimited format if (!pb_decode_tag(stream, &wiretype, &tag, &eof)) { printf("Parsing tag#3 failed: %s\n", PB_GET_ERROR(stream)); } printf("wiretype=%d tag=%d (submessage type)\n", wiretype, tag); assert(wiretype == 2); // length-delimited format printf("submessage: %s NML; %s Motion\n", is_NML_container(tag) ? "is" : "not", is_Motion_container(tag) ? "is" : "not"); // decoding the submessage left as exercise return true; }
pb_field_t *pb_begin(pb_field_t *f, const void *data, int dlen) { f->start = f->ptr = (char *)data; f->size = f->left = dlen; f->eom = 0; f->errmsg = NULL; if(pb_decode_tag(f)) return NULL; return f; }
void decode(thinger_message& message, size_t size){ size_t start_read = bytes_read(); while(size-(bytes_read()-start_read)>0) { protoson::pb_wire_type wire_type; uint32_t field_number; pb_decode_tag(wire_type, field_number); switch (wire_type) { case protoson::length_delimited:{ uint32_t size = pb_decode_varint32(); pb_skip(size); } break; case protoson::varint: { switch (field_number) { case thinger_message::SIGNAL_FLAG: message.set_signal_flag((thinger_message::signal_flag)pb_decode_varint32()); break; case thinger_message::STREAM_ID: message.set_stream_id(pb_decode_varint32()); break; default: pb_skip_varint(); break; } break; } case protoson::pson_type: switch(field_number){ case thinger_message::RESOURCE: protoson::pson_decoder::decode(message.get_resources()); break; case thinger_message::PSON_PAYLOAD: protoson::pson_decoder::decode(((protoson::pson&) message)); break; default: break; } break; case protoson::fixed_32: pb_skip(4); break; case protoson::fixed_64: pb_skip(8); break; default: break; } } }
pb_field_t *pb_begin_delimited(pb_field_t *f, const void *data, int dlen) { f->start = f->ptr = (char *)data; f->size = f->left = dlen; f->eom = 0; if (pb_decode_varint(f)) return NULL; if(f->val.i64 > (uint64_t)f->left) PB_RETURN_ERROR(f, NULL, "delimited overflow"); f->left = f->val.i64; if(pb_decode_tag(f)) return NULL; return f; }
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; }
pb_field_t *pb_next(pb_field_t *f) { if(pb_decode_tag(f)) return NULL; return f; }
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; }