/src/yajl-ruby/ext/yajl/yajl.c
Line | Count | Source (jump to first uncovered line) |
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 | | #include "api/yajl_parse.h" |
34 | | #include "yajl_lex.h" |
35 | | #include "yajl_parser.h" |
36 | | #include "yajl_alloc.h" |
37 | | |
38 | | #include <stdlib.h> |
39 | | #include <string.h> |
40 | | #include <assert.h> |
41 | | |
42 | | const char * |
43 | | yajl_status_to_string(yajl_status stat) |
44 | 0 | { |
45 | 0 | const char * statStr = "unknown"; |
46 | 0 | switch (stat) { |
47 | 0 | case yajl_status_ok: |
48 | 0 | statStr = "ok, no error"; |
49 | 0 | break; |
50 | 0 | case yajl_status_client_canceled: |
51 | 0 | statStr = "client canceled parse"; |
52 | 0 | break; |
53 | 0 | case yajl_status_insufficient_data: |
54 | 0 | statStr = "eof was met before the parse could complete"; |
55 | 0 | break; |
56 | 0 | case yajl_status_error: |
57 | 0 | statStr = "parse error"; |
58 | 0 | break; |
59 | 0 | case yajl_status_alloc_failed: |
60 | 0 | statStr = "allocation failed"; |
61 | 0 | break; |
62 | 0 | } |
63 | 0 | return statStr; |
64 | 0 | } |
65 | | |
66 | | yajl_handle |
67 | | yajl_alloc(const yajl_callbacks * callbacks, |
68 | | const yajl_parser_config * config, |
69 | | const yajl_alloc_funcs * afs, |
70 | | void * ctx) |
71 | 2.40k | { |
72 | 2.40k | unsigned int allowComments = 0; |
73 | 2.40k | unsigned int validateUTF8 = 0; |
74 | 2.40k | yajl_handle hand = NULL; |
75 | 2.40k | yajl_alloc_funcs afsBuffer; |
76 | | |
77 | | /* first order of business is to set up memory allocation routines */ |
78 | 2.40k | if (afs != NULL) { |
79 | 0 | if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL) |
80 | 0 | { |
81 | 0 | return NULL; |
82 | 0 | } |
83 | 2.40k | } else { |
84 | 2.40k | yajl_set_default_alloc_funcs(&afsBuffer); |
85 | 2.40k | afs = &afsBuffer; |
86 | 2.40k | } |
87 | | |
88 | 2.40k | hand = (yajl_handle) YA_MALLOC(afs, sizeof(struct yajl_handle_t)); |
89 | 2.40k | if (hand == NULL) |
90 | 0 | return NULL; |
91 | | |
92 | | /* copy in pointers to allocation routines */ |
93 | 2.40k | memcpy((void *) &(hand->alloc), (void *) afs, sizeof(yajl_alloc_funcs)); |
94 | | |
95 | 2.40k | if (config != NULL) { |
96 | 2.40k | allowComments = config->allowComments; |
97 | 2.40k | validateUTF8 = config->checkUTF8; |
98 | 2.40k | } |
99 | | |
100 | 2.40k | hand->callbacks = callbacks; |
101 | 2.40k | hand->ctx = ctx; |
102 | 2.40k | hand->lexer = yajl_lex_alloc(&(hand->alloc), allowComments, validateUTF8); |
103 | 2.40k | if (!hand->lexer) { |
104 | 0 | YA_FREE(afs, hand); |
105 | 0 | return NULL; |
106 | 0 | } |
107 | 2.40k | hand->bytesConsumed = 0; |
108 | 2.40k | hand->decodeBuf = yajl_buf_alloc(&(hand->alloc)); |
109 | 2.40k | yajl_bs_init(hand->stateStack, &(hand->alloc)); |
110 | | |
111 | 2.40k | if (yajl_bs_push(hand->stateStack, yajl_state_start)) { |
112 | 0 | return NULL; |
113 | 0 | } |
114 | | |
115 | 2.40k | return hand; |
116 | 2.40k | } |
117 | | |
118 | | void |
119 | 550k | yajl_reset_parser(yajl_handle hand) { |
120 | 550k | assert(hand); |
121 | 550k | hand->lexer = yajl_lex_realloc(hand->lexer); |
122 | 550k | } |
123 | | |
124 | | void |
125 | | yajl_free(yajl_handle handle) |
126 | 2.40k | { |
127 | 2.40k | assert(handle); |
128 | 2.40k | yajl_bs_free(handle->stateStack); |
129 | 2.40k | yajl_buf_free(handle->decodeBuf); |
130 | 2.40k | yajl_lex_free(handle->lexer); |
131 | 2.40k | YA_FREE(&(handle->alloc), handle); |
132 | 2.40k | } |
133 | | |
134 | | yajl_status |
135 | | yajl_parse(yajl_handle hand, const unsigned char * jsonText, |
136 | | unsigned int jsonTextLen) |
137 | 2.40k | { |
138 | 2.40k | assert(hand); |
139 | 2.40k | yajl_status status; |
140 | 2.40k | status = yajl_do_parse(hand, jsonText, jsonTextLen); |
141 | 2.40k | return status; |
142 | 2.40k | } |
143 | | |
144 | | yajl_status |
145 | | yajl_parse_complete(yajl_handle hand) |
146 | 0 | { |
147 | 0 | assert(hand); |
148 | | /* The particular case we want to handle is a trailing number. |
149 | | * Further input consisting of digits could cause our interpretation |
150 | | * of the number to change (buffered "1" but "2" comes in). |
151 | | * A very simple approach to this is to inject whitespace to terminate |
152 | | * any number in the lex buffer. |
153 | | */ |
154 | 0 | return yajl_parse(hand, (const unsigned char *)" ", 1); |
155 | 0 | } |
156 | | |
157 | | unsigned char * |
158 | | yajl_get_error(yajl_handle hand, int verbose, |
159 | | const unsigned char * jsonText, unsigned int jsonTextLen) |
160 | 0 | { |
161 | 0 | assert(hand); |
162 | 0 | return yajl_render_error_string(hand, jsonText, jsonTextLen, verbose); |
163 | 0 | } |
164 | | |
165 | | unsigned int |
166 | | yajl_get_bytes_consumed(yajl_handle hand) |
167 | 0 | { |
168 | 0 | if (!hand) return 0; |
169 | 0 | else return hand->bytesConsumed; |
170 | 0 | } |
171 | | |
172 | | |
173 | | void |
174 | | yajl_free_error(yajl_handle hand, unsigned char * str) |
175 | 0 | { |
176 | | /* use memory allocation functions if set */ |
177 | 0 | YA_FREE(&(hand->alloc), str); |
178 | 0 | } |
179 | | |
180 | | /* XXX: add utility routines to parse from file */ |