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 a file descriptor.
227  * This API Works Synchronously. This function returns when either parse is finished or there has
228  * been an error.
229  */
230 //--------------------------------------------------------------------------------------------------
231 LE_API_JSON void le_json_SyncParse
232 (
233  int fd, ///< File descriptor to read the JSON document from.
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  * Parse a JSON document received via C string.
242  *
243  * @return Reference to the JSON parsing session started by this function call.
244  */
245 //--------------------------------------------------------------------------------------------------
247 (
248  const char *jsonString, ///< JSON string to parse.
249  le_json_EventHandler_t eventHandler, ///< Function to call when normal parsing events happen.
250  le_json_ErrorHandler_t errorHandler, ///< Function to call when errors happen.
251  void* opaquePtr ///< Opaque pointer to be fetched by handlers using le_json_GetOpaquePtr().
252 );
253 
254 //--------------------------------------------------------------------------------------------------
255 /**
256  * Stops parsing and cleans up memory allocated by the parser.
257  *
258  * @warning Be sure to stop parsing before closing the file descriptor.
259  */
260 //--------------------------------------------------------------------------------------------------
261 LE_API_JSON void le_json_Cleanup
262 (
263  le_json_ParsingSessionRef_t session ///< The parsing session to clean up (see le_json_Parse()).
264 );
265 
266 
267 //--------------------------------------------------------------------------------------------------
268 /**
269  * Set the current context's event handler function.
270  *
271  * @warning This function can only be called inside event or error handlers.
272  */
273 //--------------------------------------------------------------------------------------------------
274 LE_API_JSON void le_json_SetEventHandler
275 (
276  le_json_EventHandler_t callbackFunc ///< Function to call when parsing events happen.
277 );
278 
279 
280 //--------------------------------------------------------------------------------------------------
281 /**
282  * Enumeration of the different types of "contexts" that can exist during a parsing session.
283  */
284 //--------------------------------------------------------------------------------------------------
285 typedef enum
286 {
287  LE_JSON_CONTEXT_DOC, ///< Top level of document, outside the main object/array.
288  LE_JSON_CONTEXT_OBJECT, ///< Parsing an object (set of named members).
289  LE_JSON_CONTEXT_MEMBER, ///< Parsing a member of an object.
290  LE_JSON_CONTEXT_ARRAY, ///< Parsing an array (list of unnamed elements).
291  LE_JSON_CONTEXT_STRING, ///< Parsing a string value.
292  LE_JSON_CONTEXT_NUMBER, ///< Parsing number value.
293  LE_JSON_CONTEXT_TRUE, ///< Parsing a true value.
294  LE_JSON_CONTEXT_FALSE, ///< Parsing a false value.
295  LE_JSON_CONTEXT_NULL, ///< Parsing a null value.
296 }
298 
299 
300 //--------------------------------------------------------------------------------------------------
301 /**
302  * Get the type of parsing context that the parser is currently in.
303  *
304  * @return The context type.
305  *
306  * @warning This function can only be called inside event or error handlers.
307  */
308 //--------------------------------------------------------------------------------------------------
310 (
311  void
312 );
313 
314 
315 //--------------------------------------------------------------------------------------------------
316 /**
317  * Set the opaque pointer attached to the parser.
318  *
319  * @warning This function can only be called inside event or error handlers.
320  */
321 //--------------------------------------------------------------------------------------------------
322 LE_API_JSON void le_json_SetOpaquePtr
323 (
324  void* ptr ///< Opaque pointer to be fetched using le_json_GetOpaquePtr().
325 );
326 
327 
328 //--------------------------------------------------------------------------------------------------
329 /**
330  * Get the opaque pointer attached to the parser.
331  *
332  * @return The pointer previously set by le_json_Parse() or a subsequent call to
333  * le_json_SetOpaquePtr().
334  *
335  * @warning This function can only be called inside event or error handlers.
336  */
337 //--------------------------------------------------------------------------------------------------
338 LE_API_JSON void* le_json_GetOpaquePtr
339 (
340  void
341 );
342 
343 
344 //--------------------------------------------------------------------------------------------------
345 /**
346  * Set the error handler function
347  *
348  * @warning This function can only be called inside event or error handlers.
349  */
350 //--------------------------------------------------------------------------------------------------
351 LE_API_JSON void le_json_SetErrorHandler
352 (
353  le_json_ErrorHandler_t callbackFunc ///< Function to call when parsing errors happen.
354 );
355 
356 
357 //--------------------------------------------------------------------------------------------------
358 /**
359  * Fetches a pointer to a string value or object member name.
360  *
361  * This pointer is only valid until the event handler returns.
362  *
363  * @warning This function can only be called inside event handlers when LE_JSON_OBJECT_MEMBER
364  * or LE_JSON_STRING events are being handled.
365  */
366 //--------------------------------------------------------------------------------------------------
367 LE_API_JSON const char* le_json_GetString
368 (
369  void
370 );
371 
372 
373 //--------------------------------------------------------------------------------------------------
374 /**
375  * Fetches the value of a parsed number.
376  *
377  * @warning This function can only be called inside event handlers when LE_JSON_NUMBER events are
378  * being handled.
379  */
380 //--------------------------------------------------------------------------------------------------
381 LE_API_JSON double le_json_GetNumber
382 (
383  void
384 );
385 
386 
387 //--------------------------------------------------------------------------------------------------
388 /**
389  * @return Human readable string containing the name of a given JSON parsing event.
390  */
391 //--------------------------------------------------------------------------------------------------
392 LE_API_JSON const char* le_json_GetEventName
393 (
394  le_json_Event_t event
395 );
396 
397 
398 //--------------------------------------------------------------------------------------------------
399 /**
400  * @return Human readable string containing the name of a given JSON parsing context.
401  */
402 //--------------------------------------------------------------------------------------------------
403 LE_API_JSON const char* le_json_GetContextName
404 (
405  le_json_ContextType_t context
406 );
407 
408 
409 //--------------------------------------------------------------------------------------------------
410 /**
411  * @return The number of bytes that have been read from the input stream so far.
412  */
413 //--------------------------------------------------------------------------------------------------
414 LE_API_JSON size_t le_json_GetBytesRead
415 (
416  le_json_ParsingSessionRef_t session ///< Parsing session.
417 );
418 
419 
420 //--------------------------------------------------------------------------------------------------
421 /**
422  * For use by an event handler or error handler to fetch the JSON parsing session reference for
423  * the session that called its handler function.
424  *
425  * @return The session reference of the JSON parsing session.
426  *
427  * @warning This function can only be called inside event or error handlers.
428  */
429 //--------------------------------------------------------------------------------------------------
431 (
432  void
433 );
434 
435 
436 #endif // LEGATO_JSON_H_INCLUDE_GUARD
array finished, subsequent values are outside this array
Definition: le_json.h:147
LE_API_JSON double le_json_GetNumber(void)
Syntax error, such as a missing comma or extra comma.
Definition: le_json.h:178
Parsing number value.
Definition: le_json.h:292
Parsing a member of an object.
Definition: le_json.h:289
void(* le_json_ErrorHandler_t)(le_json_Error_t error, const char *msg)
Definition: le_json.h:194
object started, subsequent object members are part of this object
Definition: le_json.h:143
true value received
Definition: le_json.h:150
LE_API_JSON void le_json_SyncParse(int fd, le_json_EventHandler_t eventHandler, le_json_ErrorHandler_t errorHandler, void *opaquePtr)
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:287
LE_API_JSON void * le_json_GetOpaquePtr(void)
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:294
Parsing a true value.
Definition: le_json.h:293
Error when reading from the input byte stream.
Definition: le_json.h:179
LE_API_JSON const char * le_json_GetString(void)
Parsing a string value.
Definition: le_json.h:291
number value received: call le_json_GetNumber() to get value
Definition: le_json.h:149
Parsing a null value.
Definition: le_json.h:295
Parsing an array (list of unnamed elements).
Definition: le_json.h:290
LE_API_JSON const char * le_json_GetEventName(le_json_Event_t event)
LE_API_JSON void le_json_SetErrorHandler(le_json_ErrorHandler_t callbackFunc)
LE_API_JSON le_json_ContextType_t le_json_GetContextType(void)
LE_API_JSON void le_json_SetOpaquePtr(void *ptr)
LE_API_JSON void le_json_Cleanup(le_json_ParsingSessionRef_t session)
null value received
Definition: le_json.h:152
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
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:285
void(* le_json_EventHandler_t)(le_json_Event_t event)
Definition: le_json.h:166
LE_API_JSON le_json_ParsingSessionRef_t le_json_ParseString(const char *jsonString, le_json_EventHandler_t eventHandler, le_json_ErrorHandler_t errorHandler, void *opaquePtr)
Parsing an object (set of named members).
Definition: le_json.h:288
LE_API_JSON le_json_ParsingSessionRef_t le_json_GetSession(void)
LE_API_JSON const char * le_json_GetContextName(le_json_ContextType_t context)
LE_API_JSON size_t le_json_GetBytesRead(le_json_ParsingSessionRef_t session)
LE_API_JSON void le_json_SetEventHandler(le_json_EventHandler_t callbackFunc)
LE_FULL_API le_json_ParsingSessionRef_t le_json_Parse(int fd, le_json_EventHandler_t eventHandler, le_json_ErrorHandler_t errorHandler, void *opaquePtr)