MOS Source Code
Loading...
Searching...
No Matches
encode_cyclic_callback.c
Go to the documentation of this file.
1/* This program parses an input string in a format a bit like JSON:
2 * {'foobar': 1234, 'xyz': 'abc', 'tree': [[[1, 2], 3], [4, 5]]}
3 * and encodes it as protobuf
4 *
5 * Note: The string parsing here is not in any way intended to be robust
6 * nor safe against buffer overflows. It is just for this test.
7 */
8
9#include <pb_encode.h>
10#include <stdlib.h>
11#include <stdio.h>
12#include <string.h>
13#include "cyclic_callback.pb.h"
14
15static char *find_end_of_item(char *p)
16{
17 int depth = 0;
18 do {
19 if (*p == '[' || *p == '{') depth++;
20 if (*p == ']' || *p == '}') depth--;
21 p++;
22 } while (depth > 0 || (*p != ',' && *p != '}'));
23
24 if (*p == '}')
25 return p; /* End of parent dict */
26
27 p++;
28 while (*p == ' ') p++;
29 return p;
30}
31
32/* Parse a tree in format [[1 2] 3] and encode it directly to protobuf */
33static bool encode_tree(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
34{
35 TreeNode tree = TreeNode_init_zero;
36 char *p = (char*)*arg;
37
38 if (*p == '[')
39 {
40 /* This is a tree branch */
41 p++;
42 tree.left.funcs.encode = encode_tree;
43 tree.left.arg = p;
44
45 p = find_end_of_item(p);
46 tree.right.funcs.encode = encode_tree;
47 tree.right.arg = p;
48 }
49 else
50 {
51 /* This is a leaf node */
52 tree.has_leaf = true;
53 tree.leaf = atoi(p);
54 }
55
56 return pb_encode_tag_for_field(stream, field) &&
57 pb_encode_submessage(stream, TreeNode_fields, &tree);
58}
59
60/* Parse a dictionary in format {'name': value} and encode it directly to protobuf */
61static bool encode_dictionary(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
62{
63 int textlen;
64 char *p = (char*)*arg;
65 if (*p == '{') p++;
66 while (*p != '}')
67 {
68 KeyValuePair pair = KeyValuePair_init_zero;
69
70 if (*p != '\'')
71 PB_RETURN_ERROR(stream, "invalid key, missing quote");
72
73 p++; /* Starting quote of key */
74 textlen = strchr(p, '\'') - p;
75 strncpy(pair.key, p, textlen);
76 pair.key[textlen] = 0;
77 p += textlen + 2;
78
79 while (*p == ' ') p++;
80
81 if (*p == '[')
82 {
83 /* Value is a tree */
84 pair.treeValue.funcs.encode = encode_tree;
85 pair.treeValue.arg = p;
86 }
87 else if (*p == '\'')
88 {
89 /* Value is a string */
90 pair.has_stringValue = true;
91 p++;
92 textlen = strchr(p, '\'') - p;
93 strncpy(pair.stringValue, p, textlen);
94 pair.stringValue[textlen] = 0;
95 }
96 else if (*p == '{')
97 {
98 /* Value is a dictionary */
99 pair.has_dictValue = true;
100 pair.dictValue.dictItem.funcs.encode = encode_dictionary;
101 pair.dictValue.dictItem.arg = p;
102 }
103 else
104 {
105 /* Value is integer */
106 pair.has_intValue = true;
107 pair.intValue = atoi(p);
108 }
109
110 p = find_end_of_item(p);
111
112 if (!pb_encode_tag_for_field(stream, field))
113 return false;
114
115 if (!pb_encode_submessage(stream, KeyValuePair_fields, &pair))
116 return false;
117 }
118
119 return true;
120}
121
122
123int main(int argc, char *argv[])
124{
125 uint8_t buffer[256];
126 pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
127 Dictionary dict = Dictionary_init_zero;
128
129 if (argc <= 1)
130 {
131 fprintf(stderr, "Usage: %s \"{'foobar': 1234, ...}\"\n", argv[0]);
132 return 1;
133 }
134
135 dict.dictItem.funcs.encode = encode_dictionary;
136 dict.dictItem.arg = argv[1];
137
138 if (!pb_encode(&stream, Dictionary_fields, &dict))
139 {
140 fprintf(stderr, "Encoding error: %s\n", PB_GET_ERROR(&stream));
141 return 1;
142 }
143
144 fwrite(buffer, 1, stream.bytes_written, stdout);
145 return 0;
146}
147
148
static bool encode_tree(pb_ostream_t *stream, const pb_field_t *field, void *const *arg)
static bool encode_dictionary(pb_ostream_t *stream, const pb_field_t *field, void *const *arg)
static char * find_end_of_item(char *p)
MOSAPI char * strchr(const char *s, int c)
Definition mos_string.c:236
MOSAPI char * strncpy(char *__restrict dest, const char *__restrict src, size_t n)
Definition mos_string.c:202
#define stdout
Definition mos_stdio.h:31
#define stderr
Definition mos_stdio.h:32
size_t fwrite(const void *__restrict ptr, size_t size, size_t nmemb, FILE *__restrict stream)
MOSAPI s32 atoi(const char *nptr)
Definition mos_stdlib.c:36
const char ** argv
Definition kmain.c:44
size_t argc
Definition kmain.c:43
#define PB_GET_ERROR(stream)
Definition pb.h:891
pb_field_iter_t pb_field_t
Definition pb.h:359
#define PB_RETURN_ERROR(stream, msg)
Definition pb.h:894
bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_iter_t *field)
Definition pb_encode.c:681
bool pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct)
Definition pb_encode.c:724
pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize)
Definition pb_encode.c:63
bool pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct)
Definition pb_encode.c:512
unsigned char uint8_t
Definition pb_syshdr.h:20
int main()
Definition simple.cpp:6
static char buffer[2048]
Definition test_printf.c:7