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  * @ref 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 /**
227  * Stops parsing and cleans up memory allocated by the parser.
228  *
229  * @warning Be sure to stop parsing before closing the file descriptor.
230  */
231 //--------------------------------------------------------------------------------------------------
232 void le_json_Cleanup
233 (
234  le_json_ParsingSessionRef_t session ///< The parsing session to clean up (see le_json_Parse()).
235 );
236 
237 
238 //--------------------------------------------------------------------------------------------------
239 /**
240  * Set the current context's event handler function.
241  *
242  * @warning This function can only be called inside event or error handlers.
243  */
244 //--------------------------------------------------------------------------------------------------
246 (
247  le_json_EventHandler_t callbackFunc ///< Function to call when parsing events happen.
248 );
249 
250 
251 //--------------------------------------------------------------------------------------------------
252 /**
253  * Enumeration of the different types of "contexts" that can exist during a parsing session.
254  */
255 //--------------------------------------------------------------------------------------------------
256 typedef enum
257 {
258  LE_JSON_CONTEXT_DOC, ///< Top level of document, outside the main object/array.
259  LE_JSON_CONTEXT_OBJECT, ///< Parsing an object (set of named members).
260  LE_JSON_CONTEXT_MEMBER, ///< Parsing a member of an object.
261  LE_JSON_CONTEXT_ARRAY, ///< Parsing an array (list of unnamed elements).
262  LE_JSON_CONTEXT_STRING, ///< Parsing a string value.
263  LE_JSON_CONTEXT_NUMBER, ///< Parsing number value.
264  LE_JSON_CONTEXT_TRUE, ///< Parsing a true value.
265  LE_JSON_CONTEXT_FALSE, ///< Parsing a false value.
266  LE_JSON_CONTEXT_NULL, ///< Parsing a null value.
267 }
269 
270 
271 //--------------------------------------------------------------------------------------------------
272 /**
273  * Get the type of parsing context that the parser is currently in.
274  *
275  * @return The context type.
276  *
277  * @warning This function can only be called inside event or error handlers.
278  */
279 //--------------------------------------------------------------------------------------------------
281 (
282  void
283 );
284 
285 
286 //--------------------------------------------------------------------------------------------------
287 /**
288  * Set the opaque pointer attached to the parser.
289  *
290  * @warning This function can only be called inside event or error handlers.
291  */
292 //--------------------------------------------------------------------------------------------------
294 (
295  void* ptr ///< Opaque pointer to be fetched using le_json_GetOpaquePtr().
296 );
297 
298 
299 //--------------------------------------------------------------------------------------------------
300 /**
301  * Get the opaque pointer attached to the parser.
302  *
303  * @return The pointer previously set by le_json_Parse() or a subsequent call to
304  * le_json_SetOpaquePtr().
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 error handler function
318  *
319  * @warning This function can only be called inside event or error handlers.
320  */
321 //--------------------------------------------------------------------------------------------------
323 (
324  le_json_ErrorHandler_t callbackFunc ///< Function to call when parsing errors happen.
325 );
326 
327 
328 //--------------------------------------------------------------------------------------------------
329 /**
330  * Fetches a pointer to a string value or object member name.
331  *
332  * This pointer is only valid until the event handler returns.
333  *
334  * @warning This function can only be called inside event handlers when LE_JSON_OBJECT_MEMBER
335  * or LE_JSON_STRING events are being handled.
336  */
337 //--------------------------------------------------------------------------------------------------
338 const char* le_json_GetString
339 (
340  void
341 );
342 
343 
344 //--------------------------------------------------------------------------------------------------
345 /**
346  * Fetches the value of a parsed number.
347  *
348  * @warning This function can only be called inside event handlers when LE_JSON_NUMBER events are
349  * being handled.
350  */
351 //--------------------------------------------------------------------------------------------------
352 double le_json_GetNumber
353 (
354  void
355 );
356 
357 
358 //--------------------------------------------------------------------------------------------------
359 /**
360  * @return Human readable string containing the name of a given JSON parsing event.
361  */
362 //--------------------------------------------------------------------------------------------------
363 const char* le_json_GetEventName
364 (
365  le_json_Event_t event
366 );
367 
368 
369 //--------------------------------------------------------------------------------------------------
370 /**
371  * @return Human readable string containing the name of a given JSON parsing context.
372  */
373 //--------------------------------------------------------------------------------------------------
374 const char* le_json_GetContextName
375 (
376  le_json_ContextType_t context
377 );
378 
379 
380 //--------------------------------------------------------------------------------------------------
381 /**
382  * @return The number of bytes that have been read from the input stream so far.
383  */
384 //--------------------------------------------------------------------------------------------------
386 (
387  le_json_ParsingSessionRef_t session ///< Parsing session.
388 );
389 
390 
391 //--------------------------------------------------------------------------------------------------
392 /**
393  * For use by an event handler or error handler to fetch the JSON parsing session reference for
394  * the session that called its handler function.
395  *
396  * @return The session reference of the JSON parsing session.
397  *
398  * @warning This function can only be called inside event or error handlers.
399  */
400 //--------------------------------------------------------------------------------------------------
402 (
403  void
404 );
405 
406 
407 #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:263
Parsing a member of an object.
Definition: le_json.h:260
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:258
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:265
void * le_json_GetOpaquePtr(void)
Parsing a true value.
Definition: le_json.h:264
Error when reading from the input byte stream.
Definition: le_json.h:179
Parsing a string value.
Definition: le_json.h:262
number value received: call le_json_GetNumber() to get value
Definition: le_json.h:149
Parsing a null value.
Definition: le_json.h:266
le_json_ParsingSessionRef_t le_json_Parse(int fd, le_json_EventHandler_t eventHandler, le_json_ErrorHandler_t errorHandler, void *opaquePtr)
Parsing an array (list of unnamed elements).
Definition: le_json.h:261
void le_json_SetErrorHandler(le_json_ErrorHandler_t callbackFunc)
le_json_ContextType_t le_json_GetContextType(void)
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
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:256
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:259
double le_json_GetNumber(void)
void le_json_Cleanup(le_json_ParsingSessionRef_t session)
const char * le_json_GetContextName(le_json_ContextType_t context)