Reorganize the field decoder interface.
[apps/agl-service-can-low-level.git] / example_unions / decode.c
1 /* This program reads a message from stdin, detects its type and decodes it.
2  */
3  
4 #include <stdio.h>
5 #include <string.h>
6 #include <stdlib.h>
7
8 #include <pb_decode.h>
9 #include "unionproto.pb.h"
10
11 /* This function reads manually the first tag from the stream and finds the
12  * corresponding message type. It doesn't yet decode the actual message.
13  *
14  * Returns a pointer to the MsgType_fields array, as an identifier for the
15  * message type. Returns null if the tag is of unknown type or an error occurs.
16  */
17 const pb_field_t* decode_unionmessage_type(pb_istream_t *stream)
18 {
19     pb_wire_type_t wire_type;
20     uint32_t tag;
21     bool eof;
22
23     while (pb_decode_tag(stream, &wire_type, &tag, &eof))
24     {
25         if (wire_type == PB_WT_STRING)
26         {
27             const pb_field_t *field;
28             for (field = UnionMessage_fields; field->tag != 0; field++)
29             {
30                 if (field->tag == tag && (field->type & PB_LTYPE_SUBMESSAGE))
31                 {
32                     /* Found our field. */
33                     return field->ptr;
34                 }
35             }
36         }
37         
38         /* Wasn't our field.. */
39         pb_skip_field(stream, wire_type);
40     }
41     
42     return NULL;
43 }
44
45 bool decode_unionmessage_contents(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
46 {
47     pb_istream_t substream;
48     if (!pb_make_string_substream(stream, &substream))
49         return false;
50     
51     return pb_decode(&substream, fields, dest_struct);
52 }
53
54 int main()
55 {
56     /* Read the data into buffer */
57     uint8_t buffer[512];
58     size_t count = fread(buffer, 1, sizeof(buffer), stdin);
59     pb_istream_t stream = pb_istream_from_buffer(buffer, count);
60     
61     const pb_field_t *type = decode_unionmessage_type(&stream);
62     bool status = false;
63     
64     if (type == MsgType1_fields)
65     {
66         MsgType1 msg = {};
67         status = decode_unionmessage_contents(&stream, MsgType1_fields, &msg);
68         printf("Got MsgType1: %d\n", msg.value);
69     }
70     else if (type == MsgType2_fields)
71     {
72         MsgType2 msg = {};
73         status = decode_unionmessage_contents(&stream, MsgType2_fields, &msg);
74         printf("Got MsgType2: %s\n", msg.value ? "true" : "false");
75     }
76     else if (type == MsgType3_fields)
77     {
78         MsgType3 msg = {};
79         status = decode_unionmessage_contents(&stream, MsgType3_fields, &msg);
80         printf("Got MsgType3: %d %d\n", msg.value1, msg.value2);    
81     }
82     
83     if (!status)
84     {
85         printf("Decoding failed.\n");
86         return 1;
87     }
88     
89     return 0;
90 }
91
92
93