le_json.h

Go to the documentation of this file.
1 //--------------------------------------------------------------------------------------------------
2 /**
3  * @page c_json JSON Parsing API
4  *
5  * @warning This API is experimental, and is therefore likely to change.
6  *
7  * @subpage le_json.h "API Reference" <br>
8  *
9  * <hr>
10  *
11  * The JSON Parsing API is intended to provide fast parsing of a JSON data stream with very
12  * little memory required. It is an event-driven API that uses callbacks (handlers) to report
13  * when things are found in the JSON document. The parser does not build a document structure
14  * for you. You build your structure as needed in response to callbacks from the parser.
15  * In this way, the JSON parser avoids potential memory fragmentation issues that can arise
16  * when document object models are constructed on the heap (e.g., using malloc()).
17  *
18  * @section c_json_start Starting and Stopping Parsing
19  *
20  * The function le_json_Parse() is used to start parsing a JSON document obtained from a
21  * file descriptor. This function returns immediately, and further parsing proceeds in an
22  * event-driven manner: As JSON data is received, asynchronous call-back functions are called
23  * to deliver parsed information or an error message.
24  *
25  * Parsing stops automatically when the end of the document is reached or an error is encountered.
26  *
27  * le_json_Cleanup() must be called to release memory resources allocated by the parser.
28  *
29  * If the document starts with a '{', then it will finish with the matching '}'.
30  *
31  * If it starts with a '[', then it will finish with the matching ']'.
32  *
33  * All documents must start with either '{' or '['.
34  *
35  * To stop parsing early, call le_json_Cleanup() early.
36  *
37  * @warning Be sure to stop parsing before closing the file descriptor.
38  *
39  * @section c_json_events Event Handling
40  *
41  * As parsing progresses and the parser finds things inside the JSON document, the parser calls
42  * the event handler function to report the findings.
43  *
44  * For example, when the parser finds an object member, it calls the event handler function
45  * with the event code LE_JSON_OBJECT_MEMBER; and when if finds a string value, an LE_JSON_STRING
46  * event is reported.
47  *
48  * The event handler function can call functions to fetch values, depending on the event:
49  * - LE_JSON_OBJECT_MEMBER: le_json_GetString() fetches the object member name.
50  * - LE_JSON_STRING: le_json_GetString() fetches the string value.
51  * - LE_JSON_NUMBER: le_json_GetNumber() fetches the number value.
52  *
53  * le_json_GetString() and le_json_GetNumber() can only be called from inside of a JSON parsing
54  * event handler function or any function being called (directly or indirectly) from a JSON
55  * parsing event handler. Calling these functions elsewhere will be fatal to the calling process.
56  *
57  * @section c_json_context Context
58  *
59  * Each JSON object, object member and array in the JSON document is a "context".
60  * Each context has an event handler function and an opaque pointer associated with it.
61  * The top level context's event handler and opaque pointer are passed into le_json_Parse().
62  * Sub-contexts (object members or array elements) will inherit their context from their parent.
63  *
64  * The current context's event handler can be changed from within an event handler function by
65  * calling le_json_SetEventHandler(). This will remain in effect until the parser finishes parsing
66  * that part of the document and returns back to its parent, at which time the current context
67  * will be automatically restored to the parent's context.
68  *
69  * @section c_json_errors Error Handling
70  *
71  * There is a global error handler that is also set when the parsing is started, and can be changed
72  * by calling le_json_SetErrorHandler(). Unlike other event handlers, this is not part of the
73  * context, and will therefore not get restored to a previous handler when the parsing of a member
74  * finishes. The error handler function is passed parameters that indicate what type of error
75  * occurred.
76  *
77  * @section c_json_otherFunctions Other Functions
78  *
79  * For diagnostic purposes, le_json_GetEventName() can be called to get a human-readable
80  * string containing the name of a given event.
81  *
82  * To get the number of bytes that have been read by the parser since le_json_Parse() was called,
83  * call le_json_GetBytesRead().
84  *
85  * @section c_json_example Example
86  *
87  * If the JSON document is
88  *
89  * @code
90  * { "x":1, "y":2, "name":"joe" }
91  * @endcode
92  *
93  * The following sequence of events will be reported by the parser:
94  * 1. LE_JSON_OBJECT_START
95  * 2. LE_JSON_OBJECT_MEMBER - If the event handler calls le_json_GetString(), it will return "x".
96  * 3. LE_JSON_NUMBER - If the event handler calls le_json_GetNumber(), it will return 1.
97  * 4. LE_JSON_OBJECT_MEMBER - If the event handler calls le_json_GetString(), it will return "y".
98  * 5. LE_JSON_NUMBER - If the event handler calls le_json_GetNumber(), it will return 2.
99  * 6. LE_JSON_OBJECT_MEMBER - If the event handler calls le_json_GetString(), it will return "name".
100  * 7. LE_JSON_STRING - If the event handler calls le_json_GetString(), it will return "joe".
101  * 8. LE_JSON_OBJECT_END
102  * 8. LE_JSON_DOC_END - At this point, parsing stops.
103  *
104  * If the handler function passed to le_json_Parse() is called "<c>TopLevelHandler()</c>",
105  * TopLevelHandler() will be called for the all events. But, when <c>TopLevelHandler()</c> gets
106  * the event LE_JSON_OBJECT_MEMBER for the member "x" and responds by calling
107  * <c>le_json_SetEventHandler(XHandler(), NULL)</c>, then the LE_JSON_NUMBER event for "x" will
108  * be passed to <c>XHandler()</c>. But, the following LE_JSON_OBJECT_MEMBER event for "y" will
109  * still go to <c>TopLevelHandler()</c>, because the context returns to the top level object
110  * after the parser finishes parsing member "x".
111  *
112  * @section c_json_threads Multi-Threading
113  *
114  * This API is not thread safe. DO NOT attempt to SHARE parsers between threads.
115  *
116  * If a thread dies, any parsers in use by that thread that have not been cleaned-up by calls to
117  * le_json_Cleanup() will be cleaned up automatically.
118  *
119  * <hr>
120  *
121  * Copyright (C) Sierra Wireless Inc.
122  */
123 //--------------------------------------------------------------------------------------------------
124 
125 /** @file le_json.h
126  *
127  * Legato @ref c_json include file.
128  *
129  * Copyright (C) Sierra Wireless Inc.
130  */
131 
132 #ifndef LEGATO_JSON_H_INCLUDE_GUARD
133 #define LEGATO_JSON_H_INCLUDE_GUARD
134 
135 
136 //--------------------------------------------------------------------------------------------------
137 /**
138  * Enumeration of all the different events that can be reported during JSON document parsing.
139  */
140 //--------------------------------------------------------------------------------------------------
141 typedef enum
142 {
143  LE_JSON_OBJECT_START, ///< object started, subsequent object members are part of this object
144  LE_JSON_OBJECT_MEMBER, ///< object member name received: Call le_json_GetString() to get name
145  LE_JSON_OBJECT_END, ///< object finished, subsequent members/values are outside this object
146  LE_JSON_ARRAY_START, ///< array started, upcoming values are elements of this array
147  LE_JSON_ARRAY_END, ///< array finished, subsequent values are outside this array
148  LE_JSON_STRING, ///< string value received: call le_json_GetString() to get value
149  LE_JSON_NUMBER, ///< number value received: call le_json_GetNumber() to get value
150  LE_JSON_TRUE, ///< true value received
151  LE_JSON_FALSE, ///< false value received
152  LE_JSON_NULL, ///< null value received
153  LE_JSON_DOC_END, ///< End of the document reached. Parsing has stopped.
154 }
156 
157 
158 //--------------------------------------------------------------------------------------------------
159 /**
160  * Callbacks for (non-error) parsing events look like this.
161  *
162  * @param event [in] Indicates what type of event occured.
163  */
164 //--------------------------------------------------------------------------------------------------
165 typedef void (* le_json_EventHandler_t)
166 (
167  le_json_Event_t event
168 );
169 
170 
171 //--------------------------------------------------------------------------------------------------
172 /**
173  * Enumeration of the different types of errors that can be reported during JSON document parsing.
174  */
175 //--------------------------------------------------------------------------------------------------
176 typedef enum
177 {
178  LE_JSON_SYNTAX_ERROR, ///< Syntax error, such as a missing comma or extra comma.
179  LE_JSON_READ_ERROR, ///< Error when reading from the input byte stream.
180 }
182 
183 
184 //--------------------------------------------------------------------------------------------------
185 /**
186  * Callbacks for errors look like this.
187  *
188  * @param error [in] Indicates what type of error occured.
189  *
190  * @param msg [in] Human-readable message describing the error. (Valid until handler returns.)
191  */
192 //--------------------------------------------------------------------------------------------------
193 typedef void (* le_json_ErrorHandler_t)
194 (
195  le_json_Error_t error,
196  const char* msg
197 );
198 
199 
200 //--------------------------------------------------------------------------------------------------
201 /**
202  * Parsing session reference. Refers to a parsing session started by le_json_Parse(). Pass this
203  * to le_json_Cleanup() to stop the parsing and clean up memory allocated by the parser.
204  */
205 //--------------------------------------------------------------------------------------------------
206 typedef struct le_json_ParsingSession* le_json_ParsingSessionRef_t;
207 
208 
209 //--------------------------------------------------------------------------------------------------
210 /**
211  * Parse a JSON document received via a file descriptor.
212  *
213  * @return Reference to the JSON parsing session started by this function call.
214  */
215 //--------------------------------------------------------------------------------------------------
217 (
218  int fd, ///< File descriptor to read the JSON document from.
219  le_json_EventHandler_t eventHandler, ///< Function to call when normal parsing events happen.
220  le_json_ErrorHandler_t errorHandler, ///< Function to call when errors happen.
221  void* opaquePtr ///< Opaque pointer to be fetched by handlers using le_json_GetOpaquePtr().
222 );
223 
224 //--------------------------------------------------------------------------------------------------
225 /**
226  * Parse a JSON document received via C string.
227  *
228  * @return Reference to the JSON parsing session started by this function call.
229  */
230 //--------------------------------------------------------------------------------------------------
232 (
233  const char *jsonString, ///< JSON string to parse.
234  le_json_EventHandler_t eventHandler, ///< Function to call when normal parsing events happen.
235  le_json_ErrorHandler_t errorHandler, ///< Function to call when errors happen.
236  void* opaquePtr ///< Opaque pointer to be fetched by handlers using le_json_GetOpaquePtr().
237 );
238 
239 //--------------------------------------------------------------------------------------------------
240 /**
241  * Stops parsing and cleans up memory allocated by the parser.
242  *
243  * @warning Be sure to stop parsing before closing the file descriptor.
244  */
245 //--------------------------------------------------------------------------------------------------
246 void le_json_Cleanup
247 (
248  le_json_ParsingSessionRef_t session ///< The parsing session to clean up (see le_json_Parse()).
249 );
250 
251 
252 //--------------------------------------------------------------------------------------------------
253 /**
254  * Set the current context's event handler function.
255  *
256  * @warning This function can only be called inside event or error handlers.
257  */
258 //--------------------------------------------------------------------------------------------------
260 (
261  le_json_EventHandler_t callbackFunc ///< Function to call when parsing events happen.
262 );
263 
264 
265 //--------------------------------------------------------------------------------------------------
266 /**
267  * Enumeration of the different types of "contexts" that can exist during a parsing session.
268  */
269 //--------------------------------------------------------------------------------------------------
270 typedef enum
271 {
272  LE_JSON_CONTEXT_DOC, ///< Top level of document, outside the main object/array.
273  LE_JSON_CONTEXT_OBJECT, ///< Parsing an object (set of named members).
274  LE_JSON_CONTEXT_MEMBER, ///< Parsing a member of an object.
275  LE_JSON_CONTEXT_ARRAY, ///< Parsing an array (list of unnamed elements).
276  LE_JSON_CONTEXT_STRING, ///< Parsing a string value.
277  LE_JSON_CONTEXT_NUMBER, ///< Parsing number value.
278  LE_JSON_CONTEXT_TRUE, ///< Parsing a true value.
279  LE_JSON_CONTEXT_FALSE, ///< Parsing a false value.
280  LE_JSON_CONTEXT_NULL, ///< Parsing a null value.
281 }
283 
284 
285 //--------------------------------------------------------------------------------------------------
286 /**
287  * Get the type of parsing context that the parser is currently in.
288  *
289  * @return The context type.
290  *
291  * @warning This function can only be called inside event or error handlers.
292  */
293 //--------------------------------------------------------------------------------------------------
295 (
296  void
297 );
298 
299 
300 //--------------------------------------------------------------------------------------------------
301 /**
302  * Set the opaque pointer attached to the parser.
303  *
304  * @warning This function can only be called inside event or error handlers.
305  */
306 //--------------------------------------------------------------------------------------------------
308 (
309  void* ptr ///< Opaque pointer to be fetched using le_json_GetOpaquePtr().
310 );
311 
312 
313 //--------------------------------------------------------------------------------------------------
314 /**
315  * Get the opaque pointer attached to the parser.
316  *
317  * @return The pointer previously set by le_json_Parse() or a subsequent call to
318  * le_json_SetOpaquePtr().
319  *
320  * @warning This function can only be called inside event or error handlers.
321  */
322 //--------------------------------------------------------------------------------------------------
324 (
325  void
326 );
327 
328 
329 //--------------------------------------------------------------------------------------------------
330 /**
331  * Set the error handler function
332  *
333  * @warning This function can only be called inside event or error handlers.
334  */
335 //--------------------------------------------------------------------------------------------------
337 (
338  le_json_ErrorHandler_t callbackFunc ///< Function to call when parsing errors happen.
339 );
340 
341 
342 //--------------------------------------------------------------------------------------------------
343 /**
344  * Fetches a pointer to a string value or object member name.
345  *
346  * This pointer is only valid until the event handler returns.
347  *
348  * @warning This function can only be called inside event handlers when LE_JSON_OBJECT_MEMBER
349  * or LE_JSON_STRING events are being handled.
350  */
351 //--------------------------------------------------------------------------------------------------
352 const char* le_json_GetString
353 (
354  void
355 );
356 
357 
358 //--------------------------------------------------------------------------------------------------
359 /**
360  * Fetches the value of a parsed number.
361  *
362  * @warning This function can only be called inside event handlers when LE_JSON_NUMBER events are
363  * being handled.
364  */
365 //--------------------------------------------------------------------------------------------------
366 double le_json_GetNumber
367 (
368  void
369 );
370 
371 
372 //--------------------------------------------------------------------------------------------------
373 /**
374  * @return Human readable string containing the name of a given JSON parsing event.
375  */
376 //--------------------------------------------------------------------------------------------------
377 const char* le_json_GetEventName
378 (
379  le_json_Event_t event
380 );
381 
382 
383 //--------------------------------------------------------------------------------------------------
384 /**
385  * @return Human readable string containing the name of a given JSON parsing context.
386  */
387 //--------------------------------------------------------------------------------------------------
388 const char* le_json_GetContextName
389 (
390  le_json_ContextType_t context
391 );
392 
393 
394 //--------------------------------------------------------------------------------------------------
395 /**
396  * @return The number of bytes that have been read from the input stream so far.
397  */
398 //--------------------------------------------------------------------------------------------------
400 (
401  le_json_ParsingSessionRef_t session ///< Parsing session.
402 );
403 
404 
405 //--------------------------------------------------------------------------------------------------
406 /**
407  * For use by an event handler or error handler to fetch the JSON parsing session reference for
408  * the session that called its handler function.
409  *
410  * @return The session reference of the JSON parsing session.
411  *
412  * @warning This function can only be called inside event or error handlers.
413  */
414 //--------------------------------------------------------------------------------------------------
416 (
417  void
418 );
419 
420 
421 #endif // LEGATO_JSON_H_INCLUDE_GUARD
array finished, subsequent values are outside this array
Definition: le_json.h:147
Syntax error, such as a missing comma or extra comma.
Definition: le_json.h:178
Parsing number value.
Definition: le_json.h:277
Parsing a member of an object.
Definition: le_json.h:274
void le_json_SetEventHandler(le_json_EventHandler_t callbackFunc)
void(* le_json_ErrorHandler_t)(le_json_Error_t error, const char *msg)
Definition: le_json.h:194
le_json_ParsingSessionRef_t le_json_GetSession(void)
object started, subsequent object members are part of this object
Definition: le_json.h:143
const char * le_json_GetString(void)
true value received
Definition: le_json.h:150
string value received: call le_json_GetString() to get value
Definition: le_json.h:148
Top level of document, outside the main object/array.
Definition: le_json.h:272
const char * le_json_GetEventName(le_json_Event_t event)
End of the document reached. Parsing has stopped.
Definition: le_json.h:153
object member name received: Call le_json_GetString() to get name
Definition: le_json.h:144
object finished, subsequent members/values are outside this object
Definition: le_json.h:145
Parsing a false value.
Definition: le_json.h:279
void * le_json_GetOpaquePtr(void)
Parsing a true value.
Definition: le_json.h:278
Error when reading from the input byte stream.
Definition: le_json.h:179
Parsing a string value.
Definition: le_json.h:276
number value received: call le_json_GetNumber() to get value
Definition: le_json.h:149
Parsing a null value.
Definition: le_json.h:280
Parsing an array (list of unnamed elements).
Definition: le_json.h:275
void le_json_SetErrorHandler(le_json_ErrorHandler_t callbackFunc)
le_json_ContextType_t le_json_GetContextType(void)
le_json_ParsingSessionRef_t le_json_ParseString(const char *jsonString, le_json_EventHandler_t eventHandler, le_json_ErrorHandler_t errorHandler, void *opaquePtr)
null value received
Definition: le_json.h:152
size_t le_json_GetBytesRead(le_json_ParsingSessionRef_t session)
struct le_json_ParsingSession * le_json_ParsingSessionRef_t
Definition: le_json.h:206
#define LE_FULL_API
Definition: le_apiFeatures.h:40
le_json_Event_t
Definition: le_json.h:141
le_json_Error_t
Definition: le_json.h:176
void le_json_SetOpaquePtr(void *ptr)
false value received
Definition: le_json.h:151
array started, upcoming values are elements of this array
Definition: le_json.h:146
le_json_ContextType_t
Definition: le_json.h:270
void(* le_json_EventHandler_t)(le_json_Event_t event)
Definition: le_json.h:166
Parsing an object (set of named members).
Definition: le_json.h:273
double le_json_GetNumber(void)
void le_json_Cleanup(le_json_ParsingSessionRef_t session)
LE_FULL_API le_json_ParsingSessionRef_t le_json_Parse(int fd, le_json_EventHandler_t eventHandler, le_json_ErrorHandler_t errorHandler, void *opaquePtr)
const char * le_json_GetContextName(le_json_ContextType_t context)