xref: /5.5.2/couchdb/src/ejson/yajl/yajl_parse.h (revision 3925e856)
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
44extern "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