1d4afb5ceSopenharmony_ci# LEJP JSON Stream Parser
2d4afb5ceSopenharmony_ci
3d4afb5ceSopenharmony_ci|||
4d4afb5ceSopenharmony_ci|---|---|---|
5d4afb5ceSopenharmony_ci|cmake| `LWS_WITH_LEJP`|
6d4afb5ceSopenharmony_ci|Header| ./include/libwebsockets/lws-lejp.h|
7d4afb5ceSopenharmony_ci|api-test| ./minimal-examples/api-tests/api-test-lejp/|
8d4afb5ceSopenharmony_ci|test app| ./test-apps/test-lejp.c -> libwebsockets-test-lejp|
9d4afb5ceSopenharmony_ci
10d4afb5ceSopenharmony_ciLEJP is a lightweight JSON stream parser.
11d4afb5ceSopenharmony_ci
12d4afb5ceSopenharmony_ciThe features are:
13d4afb5ceSopenharmony_ci
14d4afb5ceSopenharmony_ci - completely immune to input fragmentation, give it any size blocks of JSON as
15d4afb5ceSopenharmony_ci   they become available, 1 byte, or 100K at a time give identical parsing
16d4afb5ceSopenharmony_ci   results
17d4afb5ceSopenharmony_ci - input chunks discarded as they are parsed, whole JSON never needed in memory
18d4afb5ceSopenharmony_ci - nonrecursive, fixed stack usage of a few dozen bytes
19d4afb5ceSopenharmony_ci - no heap allocations at all, just requires ~500 byte context usually on
20d4afb5ceSopenharmony_ci   caller stack
21d4afb5ceSopenharmony_ci - creates callbacks to a user-provided handler as members are parsed out
22d4afb5ceSopenharmony_ci - no payload size limit, supports huge / endless strings bigger than
23d4afb5ceSopenharmony_ci   system memory
24d4afb5ceSopenharmony_ci - collates utf-8 text payloads into a 250-byte chunk buffer in the json parser
25d4afb5ceSopenharmony_ci   context object for ease of access
26d4afb5ceSopenharmony_ci
27d4afb5ceSopenharmony_ci## Type handling
28d4afb5ceSopenharmony_ci
29d4afb5ceSopenharmony_ciLEJP leaves all numbers in text form, they are signalled in different callbacks
30d4afb5ceSopenharmony_ciaccording to int or float, but delivered as text strings in the first
31d4afb5ceSopenharmony_ci`ctx->npos` chars of `ctx->buf`.
32d4afb5ceSopenharmony_ci
33d4afb5ceSopenharmony_ciFor numeric types, you would typically use `atoi()` or similar to recover the
34d4afb5ceSopenharmony_cinumber as a host type.
35d4afb5ceSopenharmony_ci
36d4afb5ceSopenharmony_ci## Callback reasons
37d4afb5ceSopenharmony_ci
38d4afb5ceSopenharmony_ciThe user callback does not have to handle any callbacks, it only needs to
39d4afb5ceSopenharmony_ciprocess the data for the ones it is interested in.
40d4afb5ceSopenharmony_ci
41d4afb5ceSopenharmony_ci|Callback reason|JSON structure|Associated data|
42d4afb5ceSopenharmony_ci|---|---|---|
43d4afb5ceSopenharmony_ci|`LEJPCB_CONSTRUCTED`|Created the parse context||
44d4afb5ceSopenharmony_ci|`LEJPCB_DESTRUCTED`|Destroyed the parse context||
45d4afb5ceSopenharmony_ci|`LEJPCB_COMPLETE`|The parsing completed OK||
46d4afb5ceSopenharmony_ci|`LEJPCB_FAILED`|The parsing failed||
47d4afb5ceSopenharmony_ci|`LEJPCB_VAL_TRUE`|boolean true||
48d4afb5ceSopenharmony_ci|`LEJPCB_VAL_FALSE`|boolean false||
49d4afb5ceSopenharmony_ci|`LEJPCB_VAL_NULL`|explicit NULL||
50d4afb5ceSopenharmony_ci|`LEJPCB_PAIR_NAME`|The name part of a JSON `key: value` map pair|`ctx->buf`|
51d4afb5ceSopenharmony_ci|`LEJPCB_VAL_STR_START`|A UTF-8 string is starting||
52d4afb5ceSopenharmony_ci|`LEJPCB_VAL_STR_CHUNK`|The next string chunk|`ctx->npos` bytes in `ctx->buf`|
53d4afb5ceSopenharmony_ci|`LEJPCB_VAL_STR_END`|The last string chunk|`ctx->npos` bytes in `ctx->buf`|
54d4afb5ceSopenharmony_ci|`LEJPCB_ARRAY_START`|An array is starting||
55d4afb5ceSopenharmony_ci|`LEJPCB_ARRAY_END`|An array has ended||
56d4afb5ceSopenharmony_ci|`LEJPCB_OBJECT_START`|A JSON object is starting||
57d4afb5ceSopenharmony_ci|`LEJPCB_OBJECT_END`|A JSON object has ended||
58d4afb5ceSopenharmony_ci
59d4afb5ceSopenharmony_ci## Handling JSON UTF-8 strings
60d4afb5ceSopenharmony_ci
61d4afb5ceSopenharmony_ciWhen a string is parsed, an advisory callback of `LECPCB_VAL_STR_START` occurs
62d4afb5ceSopenharmony_cifirst.  No payload is delivered with the START callback.
63d4afb5ceSopenharmony_ci
64d4afb5ceSopenharmony_ciPayload is collated into `ctx->buf[]`, the valid length is in `ctx->npos`.
65d4afb5ceSopenharmony_ci
66d4afb5ceSopenharmony_ciFor short strings or blobs where the length is known, the whole payload is
67d4afb5ceSopenharmony_cidelivered in a single `LECPCB_VAL_STR_END` callback.
68d4afb5ceSopenharmony_ci
69d4afb5ceSopenharmony_ciFor payloads larger than the size of `ctx->buf[]`, `LECPCB_VAL_STR_CHUNK`
70d4afb5ceSopenharmony_cicallbacks occur delivering each sequential bufferload.
71d4afb5ceSopenharmony_ci
72d4afb5ceSopenharmony_ciThe last chunk (which may be zero length) is delievered by `LECPCB_VAL_STR_END`.
73d4afb5ceSopenharmony_ci
74d4afb5ceSopenharmony_ci## Parsing paths
75d4afb5ceSopenharmony_ci
76d4afb5ceSopenharmony_ciLEJP maintains a "parsing path" in `ctx->path` that represents the context of
77d4afb5ceSopenharmony_cithe callback events.  As a convenience, at LEJP context creation time, you can
78d4afb5ceSopenharmony_cipass in an array of path strings you want to match on, and have any match
79d4afb5ceSopenharmony_cicheckable in the callback using `ctx->path_match`, it's 0 if no active match,
80d4afb5ceSopenharmony_cior the match index from your path array starting from 1 for the first entry.
81d4afb5ceSopenharmony_ci
82d4afb5ceSopenharmony_ci|CBOR element|Representation in path|
83d4afb5ceSopenharmony_ci|---|---|
84d4afb5ceSopenharmony_ci|JSON Array|`[]`|
85d4afb5ceSopenharmony_ci|JSON Map|`.`|
86d4afb5ceSopenharmony_ci|JSON Map entry key string|`keystring`|
87d4afb5ceSopenharmony_ci
88d4afb5ceSopenharmony_ci
89d4afb5ceSopenharmony_ci
90d4afb5ceSopenharmony_ci## Comparison with LECP (CBOR parser)
91d4afb5ceSopenharmony_ci
92d4afb5ceSopenharmony_ciLECP is based on the same principles as LEJP and shares most of the callbacks.
93d4afb5ceSopenharmony_ciThe major differences:
94d4afb5ceSopenharmony_ci
95d4afb5ceSopenharmony_ci - LEJP value callbacks all appear in `ctx->buf[]`, ie, floating-point is
96d4afb5ceSopenharmony_ci   provided to the callback in ascii form like `"1.0"`.  CBOR provides a more
97d4afb5ceSopenharmony_ci   strict typing system, and the different type values are provided either in
98d4afb5ceSopenharmony_ci   `ctx->buf[]` for blobs or utf-8 text strtings, or the `item.u` union for
99d4afb5ceSopenharmony_ci   converted types, with additional callback reasons specific to each type.
100d4afb5ceSopenharmony_ci
101d4afb5ceSopenharmony_ci - CBOR "maps" use `_OBJECT_START` and `_END` parsing callbacks around the
102d4afb5ceSopenharmony_ci   key / value pairs.  LEJP has a special callback type `PAIR_NAME` for the
103d4afb5ceSopenharmony_ci   key string / integer, but in LECP these are provided as generic callbacks
104d4afb5ceSopenharmony_ci   dependent on type, ie, generic string callbacks or integer ones, and the
105d4afb5ceSopenharmony_ci   value part is represented according to whatever comes.
106d4afb5ceSopenharmony_ci
107d4afb5ceSopenharmony_ci
108