All in one solution demonstrating how to use nanopb Protocol Buffers library from within mbed environment. Test case is very simple. It works.
Original import was an all-in-one solution that only depends on mbed.
Current implementation extracted 2 librarires:
1) nanopb contains code required to use nanopb and Timestamp dependency. 2) protocol is a specific research protocol used by LCE at Itron at the moment of commit.
The application decodes Protocol Buffers message generated with GO application using the same 'protocol'. This test level application decodes message and validates that it matches expected.
It is simply a proof that nanopb library can be used.
source/protobuf/pb_common.c@0:fbdd0d307c19, 2017-07-12 (annotated)
- Committer:
- sgnezdov
- Date:
- Wed Jul 12 22:40:29 2017 +0000
- Revision:
- 0:fbdd0d307c19
initial import demonstrates how to decode Sample protocol buffers message.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
sgnezdov | 0:fbdd0d307c19 | 1 | /* pb_common.c: Common support functions for pb_encode.c and pb_decode.c. |
sgnezdov | 0:fbdd0d307c19 | 2 | * |
sgnezdov | 0:fbdd0d307c19 | 3 | * 2014 Petteri Aimonen <jpa@kapsi.fi> |
sgnezdov | 0:fbdd0d307c19 | 4 | */ |
sgnezdov | 0:fbdd0d307c19 | 5 | |
sgnezdov | 0:fbdd0d307c19 | 6 | #include "pb_common.h" |
sgnezdov | 0:fbdd0d307c19 | 7 | |
sgnezdov | 0:fbdd0d307c19 | 8 | bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct) |
sgnezdov | 0:fbdd0d307c19 | 9 | { |
sgnezdov | 0:fbdd0d307c19 | 10 | iter->start = fields; |
sgnezdov | 0:fbdd0d307c19 | 11 | iter->pos = fields; |
sgnezdov | 0:fbdd0d307c19 | 12 | iter->required_field_index = 0; |
sgnezdov | 0:fbdd0d307c19 | 13 | iter->dest_struct = dest_struct; |
sgnezdov | 0:fbdd0d307c19 | 14 | iter->pData = (char*)dest_struct + iter->pos->data_offset; |
sgnezdov | 0:fbdd0d307c19 | 15 | iter->pSize = (char*)iter->pData + iter->pos->size_offset; |
sgnezdov | 0:fbdd0d307c19 | 16 | |
sgnezdov | 0:fbdd0d307c19 | 17 | return (iter->pos->tag != 0); |
sgnezdov | 0:fbdd0d307c19 | 18 | } |
sgnezdov | 0:fbdd0d307c19 | 19 | |
sgnezdov | 0:fbdd0d307c19 | 20 | bool pb_field_iter_next(pb_field_iter_t *iter) |
sgnezdov | 0:fbdd0d307c19 | 21 | { |
sgnezdov | 0:fbdd0d307c19 | 22 | const pb_field_t *prev_field = iter->pos; |
sgnezdov | 0:fbdd0d307c19 | 23 | |
sgnezdov | 0:fbdd0d307c19 | 24 | if (prev_field->tag == 0) |
sgnezdov | 0:fbdd0d307c19 | 25 | { |
sgnezdov | 0:fbdd0d307c19 | 26 | /* Handle empty message types, where the first field is already the terminator. |
sgnezdov | 0:fbdd0d307c19 | 27 | * In other cases, the iter->pos never points to the terminator. */ |
sgnezdov | 0:fbdd0d307c19 | 28 | return false; |
sgnezdov | 0:fbdd0d307c19 | 29 | } |
sgnezdov | 0:fbdd0d307c19 | 30 | |
sgnezdov | 0:fbdd0d307c19 | 31 | iter->pos++; |
sgnezdov | 0:fbdd0d307c19 | 32 | |
sgnezdov | 0:fbdd0d307c19 | 33 | if (iter->pos->tag == 0) |
sgnezdov | 0:fbdd0d307c19 | 34 | { |
sgnezdov | 0:fbdd0d307c19 | 35 | /* Wrapped back to beginning, reinitialize */ |
sgnezdov | 0:fbdd0d307c19 | 36 | (void)pb_field_iter_begin(iter, iter->start, iter->dest_struct); |
sgnezdov | 0:fbdd0d307c19 | 37 | return false; |
sgnezdov | 0:fbdd0d307c19 | 38 | } |
sgnezdov | 0:fbdd0d307c19 | 39 | else |
sgnezdov | 0:fbdd0d307c19 | 40 | { |
sgnezdov | 0:fbdd0d307c19 | 41 | /* Increment the pointers based on previous field size */ |
sgnezdov | 0:fbdd0d307c19 | 42 | size_t prev_size = prev_field->data_size; |
sgnezdov | 0:fbdd0d307c19 | 43 | |
sgnezdov | 0:fbdd0d307c19 | 44 | if (PB_HTYPE(prev_field->type) == PB_HTYPE_ONEOF && |
sgnezdov | 0:fbdd0d307c19 | 45 | PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF && |
sgnezdov | 0:fbdd0d307c19 | 46 | iter->pos->data_offset == PB_SIZE_MAX) |
sgnezdov | 0:fbdd0d307c19 | 47 | { |
sgnezdov | 0:fbdd0d307c19 | 48 | /* Don't advance pointers inside unions */ |
sgnezdov | 0:fbdd0d307c19 | 49 | return true; |
sgnezdov | 0:fbdd0d307c19 | 50 | } |
sgnezdov | 0:fbdd0d307c19 | 51 | else if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC && |
sgnezdov | 0:fbdd0d307c19 | 52 | PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED) |
sgnezdov | 0:fbdd0d307c19 | 53 | { |
sgnezdov | 0:fbdd0d307c19 | 54 | /* In static arrays, the data_size tells the size of a single entry and |
sgnezdov | 0:fbdd0d307c19 | 55 | * array_size is the number of entries */ |
sgnezdov | 0:fbdd0d307c19 | 56 | prev_size *= prev_field->array_size; |
sgnezdov | 0:fbdd0d307c19 | 57 | } |
sgnezdov | 0:fbdd0d307c19 | 58 | else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER) |
sgnezdov | 0:fbdd0d307c19 | 59 | { |
sgnezdov | 0:fbdd0d307c19 | 60 | /* Pointer fields always have a constant size in the main structure. |
sgnezdov | 0:fbdd0d307c19 | 61 | * The data_size only applies to the dynamically allocated area. */ |
sgnezdov | 0:fbdd0d307c19 | 62 | prev_size = sizeof(void*); |
sgnezdov | 0:fbdd0d307c19 | 63 | } |
sgnezdov | 0:fbdd0d307c19 | 64 | |
sgnezdov | 0:fbdd0d307c19 | 65 | if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED) |
sgnezdov | 0:fbdd0d307c19 | 66 | { |
sgnezdov | 0:fbdd0d307c19 | 67 | /* Count the required fields, in order to check their presence in the |
sgnezdov | 0:fbdd0d307c19 | 68 | * decoder. */ |
sgnezdov | 0:fbdd0d307c19 | 69 | iter->required_field_index++; |
sgnezdov | 0:fbdd0d307c19 | 70 | } |
sgnezdov | 0:fbdd0d307c19 | 71 | |
sgnezdov | 0:fbdd0d307c19 | 72 | iter->pData = (char*)iter->pData + prev_size + iter->pos->data_offset; |
sgnezdov | 0:fbdd0d307c19 | 73 | iter->pSize = (char*)iter->pData + iter->pos->size_offset; |
sgnezdov | 0:fbdd0d307c19 | 74 | return true; |
sgnezdov | 0:fbdd0d307c19 | 75 | } |
sgnezdov | 0:fbdd0d307c19 | 76 | } |
sgnezdov | 0:fbdd0d307c19 | 77 | |
sgnezdov | 0:fbdd0d307c19 | 78 | bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) |
sgnezdov | 0:fbdd0d307c19 | 79 | { |
sgnezdov | 0:fbdd0d307c19 | 80 | const pb_field_t *start = iter->pos; |
sgnezdov | 0:fbdd0d307c19 | 81 | |
sgnezdov | 0:fbdd0d307c19 | 82 | do { |
sgnezdov | 0:fbdd0d307c19 | 83 | if (iter->pos->tag == tag && |
sgnezdov | 0:fbdd0d307c19 | 84 | PB_LTYPE(iter->pos->type) != PB_LTYPE_EXTENSION) |
sgnezdov | 0:fbdd0d307c19 | 85 | { |
sgnezdov | 0:fbdd0d307c19 | 86 | /* Found the wanted field */ |
sgnezdov | 0:fbdd0d307c19 | 87 | return true; |
sgnezdov | 0:fbdd0d307c19 | 88 | } |
sgnezdov | 0:fbdd0d307c19 | 89 | |
sgnezdov | 0:fbdd0d307c19 | 90 | (void)pb_field_iter_next(iter); |
sgnezdov | 0:fbdd0d307c19 | 91 | } while (iter->pos != start); |
sgnezdov | 0:fbdd0d307c19 | 92 | |
sgnezdov | 0:fbdd0d307c19 | 93 | /* Searched all the way back to start, and found nothing. */ |
sgnezdov | 0:fbdd0d307c19 | 94 | return false; |
sgnezdov | 0:fbdd0d307c19 | 95 | } |
sgnezdov | 0:fbdd0d307c19 | 96 | |
sgnezdov | 0:fbdd0d307c19 | 97 |