]> Dogcows Code - chaz/yoink/blob - yajl/test/yajl_test.c
new classes; yajl library
[chaz/yoink] / yajl / test / yajl_test.c
1 /*
2 * Copyright 2007-2009, 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 <yajl/yajl_parse.h>
34 #include <yajl/yajl_gen.h>
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include <assert.h>
41
42 /* memory debugging routines */
43 typedef struct
44 {
45 unsigned int numFrees;
46 unsigned int numMallocs;
47 /* XXX: we really need a hash table here with per-allocation
48 * information */
49 } yajlTestMemoryContext;
50
51 /* cast void * into context */
52 #define TEST_CTX(vptr) ((yajlTestMemoryContext *) (vptr))
53
54 static void yajlTestFree(void * ctx, void * ptr)
55 {
56 assert(ptr != NULL);
57 TEST_CTX(ctx)->numFrees++;
58 free(ptr);
59 }
60
61 static void * yajlTestMalloc(void * ctx, unsigned int sz)
62 {
63 assert(sz != 0);
64 TEST_CTX(ctx)->numMallocs++;
65 return malloc(sz);
66 }
67
68 static void * yajlTestRealloc(void * ctx, void * ptr, unsigned int sz)
69 {
70 if (ptr == NULL) {
71 assert(sz != 0);
72 TEST_CTX(ctx)->numMallocs++;
73 } else if (sz == 0) {
74 TEST_CTX(ctx)->numFrees++;
75 }
76
77 return realloc(ptr, sz);
78 }
79
80
81 /* begin parsing callback routines */
82 #define BUF_SIZE 2048
83
84 static int test_yajl_null(void *ctx)
85 {
86 printf("null\n");
87 return 1;
88 }
89
90 static int test_yajl_boolean(void * ctx, int boolVal)
91 {
92 printf("bool: %s\n", boolVal ? "true" : "false");
93 return 1;
94 }
95
96 static int test_yajl_integer(void *ctx, long integerVal)
97 {
98 printf("integer: %ld\n", integerVal);
99 return 1;
100 }
101
102 static int test_yajl_double(void *ctx, double doubleVal)
103 {
104 printf("double: %g\n", doubleVal);
105 return 1;
106 }
107
108 static int test_yajl_string(void *ctx, const unsigned char * stringVal,
109 unsigned int stringLen)
110 {
111 printf("string: '");
112 fwrite(stringVal, 1, stringLen, stdout);
113 printf("'\n");
114 return 1;
115 }
116
117 static int test_yajl_map_key(void *ctx, const unsigned char * stringVal,
118 unsigned int stringLen)
119 {
120 char * str = (char *) malloc(stringLen + 1);
121 str[stringLen] = 0;
122 memcpy(str, stringVal, stringLen);
123 printf("key: '%s'\n", str);
124 free(str);
125 return 1;
126 }
127
128 static int test_yajl_start_map(void *ctx)
129 {
130 printf("map open '{'\n");
131 return 1;
132 }
133
134
135 static int test_yajl_end_map(void *ctx)
136 {
137 printf("map close '}'\n");
138 return 1;
139 }
140
141 static int test_yajl_start_array(void *ctx)
142 {
143 printf("array open '['\n");
144 return 1;
145 }
146
147 static int test_yajl_end_array(void *ctx)
148 {
149 printf("array close ']'\n");
150 return 1;
151 }
152
153 static yajl_callbacks callbacks = {
154 test_yajl_null,
155 test_yajl_boolean,
156 test_yajl_integer,
157 test_yajl_double,
158 NULL,
159 test_yajl_string,
160 test_yajl_start_map,
161 test_yajl_map_key,
162 test_yajl_end_map,
163 test_yajl_start_array,
164 test_yajl_end_array
165 };
166
167 static void usage(const char * progname)
168 {
169 fprintf(stderr,
170 "usage: %s [options] <filename>\n"
171 " -c allow comments\n"
172 " -b set the read buffer size\n",
173 progname);
174 exit(1);
175 }
176
177 int
178 main(int argc, char ** argv)
179 {
180 yajl_handle hand;
181 const char * fileName;
182 static unsigned char * fileData = NULL;
183 unsigned int bufSize = BUF_SIZE;
184 yajl_status stat;
185 size_t rd;
186 yajl_parser_config cfg = { 0, 1 };
187 int i, j, done;
188
189 /* memory allocation debugging: allocate a structure which collects
190 * statistics */
191 yajlTestMemoryContext memCtx = { 0,0 };
192
193 /* memory allocation debugging: allocate a structure which holds
194 * allocation routines */
195 yajl_alloc_funcs allocFuncs = {
196 yajlTestMalloc,
197 yajlTestRealloc,
198 yajlTestFree,
199 (void *) NULL
200 };
201
202 allocFuncs.ctx = (void *) &memCtx;
203
204 /* check arguments. We expect exactly one! */
205 for (i=1;i<argc;i++) {
206 if (!strcmp("-c", argv[i])) {
207 cfg.allowComments = 1;
208 } else if (!strcmp("-b", argv[i])) {
209 if (++i >= argc) usage(argv[0]);
210
211 /* validate integer */
212 for (j=0;j<(int)strlen(argv[i]);j++) {
213 if (argv[i][j] <= '9' && argv[i][j] >= '0') continue;
214 fprintf(stderr, "-b requires an integer argument. '%s' "
215 "is invalid\n", argv[i]);
216 usage(argv[0]);
217 }
218
219 bufSize = atoi(argv[i]);
220 if (!bufSize) {
221 fprintf(stderr, "%d is an invalid buffer size\n",
222 bufSize);
223 }
224 } else {
225 fprintf(stderr, "invalid command line option: '%s'\n",
226 argv[i]);
227 usage(argv[0]);
228 }
229 }
230
231 fileData = (unsigned char *) malloc(bufSize);
232
233 if (fileData == NULL) {
234 fprintf(stderr,
235 "failed to allocate read buffer of %u bytes, exiting.",
236 bufSize);
237 exit(2);
238 }
239
240 fileName = argv[argc-1];
241
242 /* ok. open file. let's read and parse */
243 hand = yajl_alloc(&callbacks, &cfg, &allocFuncs, NULL);
244
245 done = 0;
246 while (!done) {
247 rd = fread((void *) fileData, 1, bufSize, stdin);
248
249 if (rd == 0) {
250 if (!feof(stdin)) {
251 fprintf(stderr, "error reading from '%s'\n", fileName);
252 break;
253 }
254 done = 1;
255 }
256
257 if (done)
258 /* parse any remaining buffered data */
259 stat = yajl_parse_complete(hand);
260 else
261 /* read file data, pass to parser */
262 stat = yajl_parse(hand, fileData, rd);
263
264 if (stat != yajl_status_insufficient_data &&
265 stat != yajl_status_ok)
266 {
267 unsigned char * str = yajl_get_error(hand, 0, fileData, rd);
268 fflush(stdout);
269 fprintf(stderr, (char *) str);
270 yajl_free_error(hand, str);
271 break;
272 }
273 }
274
275 yajl_free(hand);
276 free(fileData);
277
278 /* finally, print out some memory statistics */
279
280 /* (lth) only print leaks here, as allocations and frees may vary depending
281 * on read buffer size, causing false failures.
282 *
283 * printf("allocations:\t%u\n", memCtx.numMallocs);
284 * printf("frees:\t\t%u\n", memCtx.numFrees);
285 */
286 fflush(stderr);
287 fflush(stdout);
288 printf("memory leaks:\t%u\n", memCtx.numMallocs - memCtx.numFrees);
289
290 return 0;
291 }
This page took 0.045288 seconds and 4 git commands to generate.