File: test2.c

package info (click to toggle)
libwebsockets 4.3.5-2
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 31,288 kB
  • sloc: ansic: 194,407; javascript: 1,550; sh: 1,387; cpp: 505; java: 461; perl: 405; xml: 118; makefile: 76; awk: 5
file content (236 lines) | stat: -rw-r--r-- 5,992 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
/*
 * lws-api-test-lws_struct-json
 *
 * Written in 2010-2020 by Andy Green <andy@warmcat.com>
 *
 * This file is made available under the Creative Commons CC0 1.0
 * Universal Public Domain Dedication.
 *
 * lws_struct apis are used to serialize and deserialize your C structs and
 * linked-lists in a standardized way that's very modest on memory but
 * convenient and easy to maintain.
 *
 * This second test file shows a worked example for how to express a schema
 * and both consume JSON -> struct and struct -> JSON for it.
 */

#include <libwebsockets.h>

static const char * const test2_json =
"{"
	"\"config\":["
		"{"
			"\"id1\":"		"null,"
			"\"creds\":{"
				"\"key1\":"	"\"\\\"xxxxxxxxx\\\"\","
				"\"key2\":"	"null"
			"},"
			"\"frequency\":"	"0,"
			"\"arg1\":"		"\"val1\","
			"\"arg2\":"		"0,"
			"\"priority\":"		"1,"
			"\"ssid\":"		"\"\\\"nw2\\\"\""
		"}, {"
			"\"id2\":"		"null,"
			"\"creds\": {"
				"\"key1\":"	"\"\\\"xxxxxxxxxxxxx\\\"\","
				"\"key2\":"	"null"
			"},"
			"\"frequency\":"	"11,"
			"\"arg1\":"		"\"val2\","
			"\"arg2\":"		"1420887242594,"
			"\"priority\":"		"3,"
			"\"ssid\":"		"\"\\\"nw1\\\"\""
		"}"
	"]"
"}";

static const char * const test2_json_expected =
	"{\"config\":[{\"creds\":{\"key1\":\"\\u0022xxxxxxxxx\\u0022\"},"
	 "\"arg1\":\"val1\",\"ssid\":\"\\u0022nw2\\u0022\","
	 "\"frequency\":0,\"arg2\":0,\"priority\":1},"
	 "{\"creds\":{\"key1\":\"\\u0022xxxxxxxxxxxxx\\u0022\"},"
	 "\"arg1\":\"val2\",\"ssid\":\"\\u0022nw1\\u0022\","
	 "\"frequency\":11,\"arg2\":1420887242594,\"priority\":3}]}"
;

/*
 * level 3: Credentials object
 */

typedef struct t2_cred {
	const char				*key1;
	const char				*key2;
} t2_cred_t;

static const lws_struct_map_t lsm_t2_cred[] = {
	LSM_STRING_PTR	(t2_cred_t, key1, "key1"),
	LSM_STRING_PTR	(t2_cred_t, key2, "key2"),
};

/*
 * level 2: Configuration object, containing a child credentials object
 */

typedef struct t2_config {
	lws_dll2_t				list;
	t2_cred_t 				*creds;
	const char				*id1;
	const char				*arg1;
	const char				*ssid;
	unsigned int				frequency;
	unsigned long long			arg2;
	unsigned int				priority;
} t2_config_t;

static const lws_struct_map_t lsm_t2_config[] = {
	LSM_CHILD_PTR	(t2_config_t,
			 creds,			/* the child pointer member */
			 t2_cred_t,		/* the child type */
			 NULL, lsm_t2_cred,	/* map object for item type */
			 "creds"),		/* outer json object name */
	LSM_STRING_PTR	(t2_config_t, id1, 	 "id1"),
	LSM_STRING_PTR	(t2_config_t, arg1,	 "arg1"),
	LSM_STRING_PTR	(t2_config_t, ssid,	 "ssid"),

	LSM_UNSIGNED	(t2_config_t, frequency, "frequency"),
	LSM_UNSIGNED	(t2_config_t, arg2,	 "arg2"),
	LSM_UNSIGNED	(t2_config_t, priority,	 "priority"),
};

/*
 * level 1: list-of-configurations object
 */

typedef struct t2_configs {
	lws_dll2_owner_t 			configs;
} t2_configs_t;

static const lws_struct_map_t lsm_t2_configs[] = {
	LSM_LIST	(t2_configs_t, configs, /* the list owner type/member */
			 t2_config_t,  list,	/* the list item type/member */
			 NULL, lsm_t2_config,	/* map object for item type */
			 "config"),		/* outer json object name */
};

/*
 * For parsing, this lists the kind of object we expect to parse so the struct
 * can be allocated polymorphically.
 *
 * Lws uses an explicit "schema" member so the type is known unambiguously.  If
 * in the incoming JSON the first member is not "schema", it will scan the
 * maps listed here and instantiate the first object that has a member of that
 * name.
 */

static const lws_struct_map_t lsm_schema[] = {
	LSM_SCHEMA	(t2_configs_t, NULL, lsm_t2_configs, "t2"),
	/* other schemata that might need parsing... */
};



static int
t2_config_dump(struct lws_dll2 *d, void *user)
{
#if !defined(LWS_WITH_NO_LOGS)
	t2_config_t *c = lws_container_of(d, t2_config_t, list);

	lwsl_notice("%s:   id1 '%s'\n", __func__, c->id1);
	lwsl_notice("%s:   arg1 '%s'\n", __func__, c->arg1);
	lwsl_notice("%s:   ssid '%s'\n", __func__, c->ssid);

	lwsl_notice("%s:   freq %d\n", __func__, c->frequency);
	lwsl_notice("%s:   arg2 %llu\n", __func__, c->arg2);
	lwsl_notice("%s:   priority %d\n", __func__, c->priority);

	lwsl_notice("%s:      key1: %s, key2: %s\n", __func__,
			     c->creds->key1, c->creds->key2);
#endif

	return 0;
}

static int
t2_configs_dump(t2_configs_t *t2cs)
{
	lwsl_notice("%s: number of configs: %d\n", __func__,
		    t2cs->configs.count);

	lws_dll2_foreach_safe(&t2cs->configs, NULL, t2_config_dump);

	return 0;
}


int
test2(void)
{
	lws_struct_serialize_t *ser;
	struct lejp_ctx ctx;
	lws_struct_args_t a;
	t2_configs_t *top;
	uint8_t buf[4096];
	size_t written;
	int n, bad = 1;

	lwsl_notice("%s: start \n", __func__);

	memset(&a, 0, sizeof(a));
	a.map_st[0] = lsm_schema;
	a.map_entries_st[0] = LWS_ARRAY_SIZE(lsm_schema);
	a.ac_block_size = 512;
	lws_struct_json_init_parse(&ctx, NULL, &a);

	n = lejp_parse(&ctx, (uint8_t *)test2_json, (int)strlen(test2_json));
	lwsl_notice("%s: lejp_parse %d\n", __func__, n);
	if (n < 0) {
		lwsl_err("%s: test2 JSON decode failed '%s'\n",
				__func__, lejp_error_to_string(n));
		goto bail;
	}
	lwsac_info(a.ac);

	top = (t2_configs_t *)a.dest; /* the top level object */

	if (!top) {
		lwsl_err("%s: no top level object\n", __func__);
		goto bail;
	}
	t2_configs_dump(top);

	/* 2. Let's reserialize the top level object and see what comes out */

	ser = lws_struct_json_serialize_create(&lsm_schema[0], 1,
					       LSSERJ_FLAG_OMIT_SCHEMA, top);
	if (!ser) {
		lwsl_err("%s: unable to init serialization\n", __func__);
		goto bail;
	}

	do {
		n = (int)lws_struct_json_serialize(ser, buf, sizeof(buf), &written);
		switch (n) {
		case LSJS_RESULT_FINISH:
			puts((const char *)buf);
			break;
		case LSJS_RESULT_CONTINUE:
		case LSJS_RESULT_ERROR:
			goto bail;
		}
	} while (n == LSJS_RESULT_CONTINUE);

	if (strcmp(test2_json_expected, (char *)buf)) {
		lwsl_err("%s: expected %s\n", __func__, test2_json_expected);
		goto bail;
	}

	lws_struct_json_serialize_destroy(&ser);

	bad = 0;

bail:
	lwsac_free(&a.ac);

	return bad;
}