1 /* 2 * Copyright 2010, Lloyd Hilaiel. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * 3. Neither the name of Lloyd Hilaiel nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /** 34 * \file yajl_parse.h 35 * Interface to YAJL's JSON parsing facilities. 36 */ 37 38 #include "yajl_common.h" 39 40 #ifndef __YAJL_PARSE_H__ 41 #define __YAJL_PARSE_H__ 42 43 #ifdef __cplusplus 44 extern "C" { 45 #endif 46 /** error codes returned from this interface */ 47 typedef enum { 48 /** no error was encountered */ 49 yajl_status_ok, 50 /** a client callback returned zero, stopping the parse */ 51 yajl_status_client_canceled, 52 /** The parse cannot yet complete because more json input text 53 * is required, call yajl_parse with the next buffer of input text. 54 * (pertinent only when stream parsing) */ 55 yajl_status_insufficient_data, 56 /** An error occured during the parse. Call yajl_get_error for 57 * more information about the encountered error */ 58 yajl_status_error 59 } yajl_status; 60 61 /** attain a human readable, english, string for an error */ 62 YAJL_API const char * yajl_status_to_string(yajl_status code); 63 64 /** an opaque handle to a parser */ 65 typedef struct yajl_handle_t * yajl_handle; 66 67 /** yajl is an event driven parser. this means as json elements are 68 * parsed, you are called back to do something with the data. The 69 * functions in this table indicate the various events for which 70 * you will be called back. Each callback accepts a "context" 71 * pointer, this is a void * that is passed into the yajl_parse 72 * function which the client code may use to pass around context. 73 * 74 * All callbacks return an integer. If non-zero, the parse will 75 * continue. If zero, the parse will be canceled and 76 * yajl_status_client_canceled will be returned from the parse. 77 * 78 * Note about handling of numbers: 79 * yajl will only convert numbers that can be represented in a double 80 * or a long int. All other numbers will be passed to the client 81 * in string form using the yajl_number callback. Furthermore, if 82 * yajl_number is not NULL, it will always be used to return numbers, 83 * that is yajl_integer and yajl_double will be ignored. If 84 * yajl_number is NULL but one of yajl_integer or yajl_double are 85 * defined, parsing of a number larger than is representable 86 * in a double or long int will result in a parse error. 87 */ 88 typedef struct { 89 int (* yajl_null)(void * ctx); 90 int (* yajl_boolean)(void * ctx, int boolVal); 91 int (* yajl_integer)(void * ctx, long integerVal); 92 int (* yajl_double)(void * ctx, double doubleVal); 93 /** A callback which passes the string representation of the number 94 * back to the client. Will be used for all numbers when present */ 95 int (* yajl_number)(void * ctx, const char * numberVal, 96 unsigned int numberLen); 97 98 /** strings are returned as pointers into the JSON text when, 99 * possible, as a result, they are _not_ null padded */ 100 int (* yajl_string)(void * ctx, const unsigned char * stringVal, 101 unsigned int stringLen); 102 103 int (* yajl_start_map)(void * ctx); 104 int (* yajl_map_key)(void * ctx, const unsigned char * key, 105 unsigned int stringLen); 106 int (* yajl_end_map)(void * ctx); 107 108 int (* yajl_start_array)(void * ctx); 109 int (* yajl_end_array)(void * ctx); 110 } yajl_callbacks; 111 112 /** configuration structure for the generator */ 113 typedef struct { 114 /** if nonzero, javascript style comments will be allowed in 115 * the json input, both slash star and slash slash */ 116 unsigned int allowComments; 117 /** if nonzero, invalid UTF8 strings will cause a parse 118 * error */ 119 unsigned int checkUTF8; 120 } yajl_parser_config; 121 122 /** allocate a parser handle 123 * \param callbacks a yajl callbacks structure specifying the 124 * functions to call when different JSON entities 125 * are encountered in the input text. May be NULL, 126 * which is only useful for validation. 127 * \param config configuration parameters for the parse. 128 * \param ctx a context pointer that will be passed to callbacks. 129 */ 130 YAJL_API yajl_handle yajl_alloc(const yajl_callbacks * callbacks, 131 const yajl_parser_config * config, 132 const yajl_alloc_funcs * allocFuncs, 133 void * ctx); 134 135 /** free a parser handle */ 136 YAJL_API void yajl_free(yajl_handle handle); 137 138 /** Parse some json! 139 * \param hand - a handle to the json parser allocated with yajl_alloc 140 * \param jsonText - a pointer to the UTF8 json text to be parsed 141 * \param jsonTextLength - the length, in bytes, of input text 142 */ 143 YAJL_API yajl_status yajl_parse(yajl_handle hand, 144 const unsigned char * jsonText, 145 unsigned int jsonTextLength); 146 147 /** Parse any remaining buffered json. 148 * Since yajl is a stream-based parser, without an explicit end of 149 * input, yajl sometimes can't decide if content at the end of the 150 * stream is valid or not. For example, if "1" has been fed in, 151 * yajl can't know whether another digit is next or some character 152 * that would terminate the integer token. 153 * 154 * \param hand - a handle to the json parser allocated with yajl_alloc 155 */ 156 YAJL_API yajl_status yajl_parse_complete(yajl_handle hand); 157 158 /** get an error string describing the state of the 159 * parse. 160 * 161 * If verbose is non-zero, the message will include the JSON 162 * text where the error occured, along with an arrow pointing to 163 * the specific char. 164 * 165 * \returns A dynamically allocated string will be returned which should 166 * be freed with yajl_free_error 167 */ 168 YAJL_API unsigned char * yajl_get_error(yajl_handle hand, int verbose, 169 const unsigned char * jsonText, 170 unsigned int jsonTextLength); 171 172 /** 173 * get the amount of data consumed from the last chunk passed to YAJL. 174 * 175 * In the case of a successful parse this can help you understand if 176 * the entire buffer was consumed (which will allow you to handle 177 * "junk at end of input". 178 * 179 * In the event an error is encountered during parsing, this function 180 * affords the client a way to get the offset into the most recent 181 * chunk where the error occured. 0 will be returned if no error 182 * was encountered. 183 */ 184 YAJL_API unsigned int yajl_get_bytes_consumed(yajl_handle hand); 185 186 /** free an error returned from yajl_get_error */ 187 YAJL_API void yajl_free_error(yajl_handle hand, unsigned char * str); 188 189 #ifdef __cplusplus 190 } 191 #endif 192 193 #endif 194