1/*
2 * lejp test app
3 *
4 * Written in 2010-2019 by Andy Green <andy@warmcat.com>
5 *
6 * This file is made available under the Creative Commons CC0 1.0
7 * Universal Public Domain Dedication.
8 *
9 * This demonstrates a minimal http server that performs a form GET with a couple
10 * of parameters.  It dumps the parameters to the console log and redirects
11 * to another page.
12 */
13
14#include <libwebsockets.h>
15#include <string.h>
16
17
18static const char * const reason_names[] = {
19	"LECPCB_CONSTRUCTED",
20	"LECPCB_DESTRUCTED",
21	"LECPCB_START",
22	"LECPCB_COMPLETE",
23	"LECPCB_FAILED",
24	"LECPCB_PAIR_NAME",
25	"LECPCB_VAL_TRUE",
26	"LECPCB_VAL_FALSE",
27	"LECPCB_VAL_NULL",
28	"LECPCB_VAL_NUM_INT",
29	"LECPCB_VAL_RESERVED", /* float in lejp */
30	"LECPCB_VAL_STR_START",
31	"LECPCB_VAL_STR_CHUNK",
32	"LECPCB_VAL_STR_END",
33	"LECPCB_ARRAY_START",
34	"LECPCB_ARRAY_END",
35	"LECPCB_OBJECT_START",
36	"LECPCB_OBJECT_END",
37	"LECPCB_TAG_START",
38	"LECPCB_TAG_END",
39	"LECPCB_VAL_NUM_UINT",
40	"LECPCB_VAL_UNDEFINED",
41	"LECPCB_VAL_FLOAT16",
42	"LECPCB_VAL_FLOAT32",
43	"LECPCB_VAL_FLOAT64",
44	"LECPCB_VAL_SIMPLE",
45	"LECPCB_VAL_BLOB_START",
46	"LECPCB_VAL_BLOB_CHUNK",
47	"LECPCB_VAL_BLOB_END",
48};
49
50static const char * const tok[] = {
51	"dummy___"
52};
53
54static signed char
55cb(struct lecp_ctx *ctx, char reason)
56{
57	char buf[1024], *p = buf, *end = &buf[sizeof(buf)];
58	int n;
59
60	for (n = 0; n < ctx->sp; n++)
61		*p++ = ' ';
62	*p = '\0';
63
64	lwsl_notice("%s%s: path %s match %d statckp %d\r\n", buf,
65			reason_names[(unsigned int)(reason) &
66			             (LEJP_FLAG_CB_IS_VALUE - 1)], ctx->path,
67			ctx->path_match, ctx->pst[ctx->pst_sp].ppos);
68
69	if (reason & LECP_FLAG_CB_IS_VALUE) {
70
71		switch (reason) {
72		case LECPCB_VAL_NUM_UINT:
73			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
74					  "   value %llu ",
75					  (unsigned long long)ctx->item.u.u64);
76			break;
77		case LECPCB_VAL_STR_START:
78		case LECPCB_VAL_STR_CHUNK:
79		case LECPCB_VAL_STR_END:
80			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
81					  "   value '%s' ", ctx->buf);
82			break;
83
84		case LECPCB_VAL_BLOB_START:
85		case LECPCB_VAL_BLOB_CHUNK:
86		case LECPCB_VAL_BLOB_END:
87			if (ctx->npos)
88				lwsl_hexdump_notice(ctx->buf, (size_t)ctx->npos);
89			break;
90
91		case LECPCB_VAL_NUM_INT:
92			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
93					  "   value %lld ",
94					  (long long)ctx->item.u.i64);
95			break;
96		case LECPCB_VAL_FLOAT16:
97		case LECPCB_VAL_FLOAT32:
98		case LECPCB_VAL_FLOAT64:
99			break;
100
101		case LECPCB_VAL_SIMPLE:
102			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
103					  "   simple %llu ",
104					  (unsigned long long)ctx->item.u.u64);
105			break;
106		}
107		if (ctx->ipos) {
108			int n;
109
110			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "(array indexes: ");
111			for (n = 0; n < ctx->ipos; n++)
112				p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "%d ", ctx->i[n]);
113			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), ") ");
114		}
115
116		lwsl_notice("%s \r\n", buf);
117
118		(void)reason_names; /* NO_LOGS... */
119		return 0;
120	}
121
122	switch (reason) {
123	case LECPCB_COMPLETE:
124		lwsl_notice("%sParsing Completed (LEJPCB_COMPLETE)\n", buf);
125		break;
126	case LECPCB_PAIR_NAME:
127		lwsl_notice("%spath: '%s' (LEJPCB_PAIR_NAME)\n", buf, ctx->path);
128		break;
129	case LECPCB_TAG_START:
130		lwsl_notice("LECPCB_TAG_START: %llu\r\n", (unsigned long long)ctx->item.u.u64);
131		return 0;
132	}
133
134	return 0;
135}
136
137int
138main(int argc, char *argv[])
139{
140	int fd, n = 1, ret = 1, m = 0;
141	struct lecp_ctx ctx;
142	char buf[128];
143
144	lws_set_log_level(7, NULL);
145
146	lwsl_notice("libwebsockets-test-lecp  (C) 2017 - 2021 andy@warmcat.com\n");
147	lwsl_notice("  usage: cat my.cbor | libwebsockets-test-lecp\n\n");
148
149	lecp_construct(&ctx, cb, NULL, tok, LWS_ARRAY_SIZE(tok));
150
151	fd = 0;
152
153	while (n > 0) {
154		n = (int)read(fd, buf, sizeof(buf));
155		if (n <= 0)
156			continue;
157
158		m = lecp_parse(&ctx, (uint8_t *)buf, (size_t)n);
159		if (m < 0 && m != LEJP_CONTINUE) {
160			lwsl_err("parse failed %d\n", m);
161			goto bail;
162		}
163	}
164	lwsl_notice("okay (%d)\n", m);
165	ret = 0;
166bail:
167	lecp_destruct(&ctx);
168
169	return ret;
170}
171