libyajl2 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,503 @@
1
+ /*
2
+ * Copyright (c) 2010-2011 Florian Forster <ff at octo.it>
3
+ *
4
+ * Permission to use, copy, modify, and/or distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+ #include <stdlib.h>
18
+ #include <stdio.h>
19
+ #include <string.h>
20
+ #include <errno.h>
21
+ #include <assert.h>
22
+
23
+ #include "api/yajl_tree.h"
24
+ #include "api/yajl_parse.h"
25
+
26
+ #include "yajl_parser.h"
27
+
28
+ #if ( defined(_WIN32) || defined(WIN32) ) && !defined(__GCC__)
29
+ #define snprintf sprintf_s
30
+ #endif
31
+
32
+ #define STATUS_CONTINUE 1
33
+ #define STATUS_ABORT 0
34
+
35
+ struct stack_elem_s;
36
+ typedef struct stack_elem_s stack_elem_t;
37
+ struct stack_elem_s
38
+ {
39
+ char * key;
40
+ yajl_val value;
41
+ stack_elem_t *next;
42
+ };
43
+
44
+ struct context_s
45
+ {
46
+ stack_elem_t *stack;
47
+ yajl_val root;
48
+ char *errbuf;
49
+ size_t errbuf_size;
50
+ };
51
+ typedef struct context_s context_t;
52
+
53
+ #define RETURN_ERROR(ctx,retval,...) { \
54
+ if ((ctx)->errbuf != NULL) \
55
+ snprintf ((ctx)->errbuf, (ctx)->errbuf_size, __VA_ARGS__); \
56
+ return (retval); \
57
+ }
58
+
59
+ static yajl_val value_alloc (yajl_type type)
60
+ {
61
+ yajl_val v;
62
+
63
+ v = malloc (sizeof (*v));
64
+ if (v == NULL) return (NULL);
65
+ memset (v, 0, sizeof (*v));
66
+ v->type = type;
67
+
68
+ return (v);
69
+ }
70
+
71
+ static void yajl_object_free (yajl_val v)
72
+ {
73
+ size_t i;
74
+
75
+ if (!YAJL_IS_OBJECT(v)) return;
76
+
77
+ for (i = 0; i < v->u.object.len; i++)
78
+ {
79
+ free((char *) v->u.object.keys[i]);
80
+ v->u.object.keys[i] = NULL;
81
+ yajl_tree_free (v->u.object.values[i]);
82
+ v->u.object.values[i] = NULL;
83
+ }
84
+
85
+ free((void*) v->u.object.keys);
86
+ free(v->u.object.values);
87
+ free(v);
88
+ }
89
+
90
+ static void yajl_array_free (yajl_val v)
91
+ {
92
+ size_t i;
93
+
94
+ if (!YAJL_IS_ARRAY(v)) return;
95
+
96
+ for (i = 0; i < v->u.array.len; i++)
97
+ {
98
+ yajl_tree_free (v->u.array.values[i]);
99
+ v->u.array.values[i] = NULL;
100
+ }
101
+
102
+ free(v->u.array.values);
103
+ free(v);
104
+ }
105
+
106
+ /*
107
+ * Parsing nested objects and arrays is implemented using a stack. When a new
108
+ * object or array starts (a curly or a square opening bracket is read), an
109
+ * appropriate value is pushed on the stack. When the end of the object is
110
+ * reached (an appropriate closing bracket has been read), the value is popped
111
+ * off the stack and added to the enclosing object using "context_add_value".
112
+ */
113
+ static int context_push(context_t *ctx, yajl_val v)
114
+ {
115
+ stack_elem_t *stack;
116
+
117
+ stack = malloc (sizeof (*stack));
118
+ if (stack == NULL)
119
+ RETURN_ERROR (ctx, ENOMEM, "Out of memory");
120
+ memset (stack, 0, sizeof (*stack));
121
+
122
+ assert ((ctx->stack == NULL)
123
+ || YAJL_IS_OBJECT (v)
124
+ || YAJL_IS_ARRAY (v));
125
+
126
+ stack->value = v;
127
+ stack->next = ctx->stack;
128
+ ctx->stack = stack;
129
+
130
+ return (0);
131
+ }
132
+
133
+ static yajl_val context_pop(context_t *ctx)
134
+ {
135
+ stack_elem_t *stack;
136
+ yajl_val v;
137
+
138
+ if (ctx->stack == NULL)
139
+ RETURN_ERROR (ctx, NULL, "context_pop: "
140
+ "Bottom of stack reached prematurely");
141
+
142
+ stack = ctx->stack;
143
+ ctx->stack = stack->next;
144
+
145
+ v = stack->value;
146
+
147
+ free (stack);
148
+
149
+ return (v);
150
+ }
151
+
152
+ static int object_add_keyval(context_t *ctx,
153
+ yajl_val obj, char *key, yajl_val value)
154
+ {
155
+ const char **tmpk;
156
+ yajl_val *tmpv;
157
+
158
+ /* We're checking for NULL in "context_add_value" or its callers. */
159
+ assert (ctx != NULL);
160
+ assert (obj != NULL);
161
+ assert (key != NULL);
162
+ assert (value != NULL);
163
+
164
+ /* We're assuring that "obj" is an object in "context_add_value". */
165
+ assert(YAJL_IS_OBJECT(obj));
166
+
167
+ tmpk = realloc((void *) obj->u.object.keys, sizeof(*(obj->u.object.keys)) * (obj->u.object.len + 1));
168
+ if (tmpk == NULL)
169
+ RETURN_ERROR(ctx, ENOMEM, "Out of memory");
170
+ obj->u.object.keys = tmpk;
171
+
172
+ tmpv = realloc(obj->u.object.values, sizeof (*obj->u.object.values) * (obj->u.object.len + 1));
173
+ if (tmpv == NULL)
174
+ RETURN_ERROR(ctx, ENOMEM, "Out of memory");
175
+ obj->u.object.values = tmpv;
176
+
177
+ obj->u.object.keys[obj->u.object.len] = key;
178
+ obj->u.object.values[obj->u.object.len] = value;
179
+ obj->u.object.len++;
180
+
181
+ return (0);
182
+ }
183
+
184
+ static int array_add_value (context_t *ctx,
185
+ yajl_val array, yajl_val value)
186
+ {
187
+ yajl_val *tmp;
188
+
189
+ /* We're checking for NULL pointers in "context_add_value" or its
190
+ * callers. */
191
+ assert (ctx != NULL);
192
+ assert (array != NULL);
193
+ assert (value != NULL);
194
+
195
+ /* "context_add_value" will only call us with array values. */
196
+ assert(YAJL_IS_ARRAY(array));
197
+
198
+ tmp = realloc(array->u.array.values,
199
+ sizeof(*(array->u.array.values)) * (array->u.array.len + 1));
200
+ if (tmp == NULL)
201
+ RETURN_ERROR(ctx, ENOMEM, "Out of memory");
202
+ array->u.array.values = tmp;
203
+ array->u.array.values[array->u.array.len] = value;
204
+ array->u.array.len++;
205
+
206
+ return 0;
207
+ }
208
+
209
+ /*
210
+ * Add a value to the value on top of the stack or the "root" member in the
211
+ * context if the end of the parsing process is reached.
212
+ */
213
+ static int context_add_value (context_t *ctx, yajl_val v)
214
+ {
215
+ /* We're checking for NULL values in all the calling functions. */
216
+ assert (ctx != NULL);
217
+ assert (v != NULL);
218
+
219
+ /*
220
+ * There are three valid states in which this function may be called:
221
+ * - There is no value on the stack => This is the only value. This is the
222
+ * last step done when parsing a document. We assign the value to the
223
+ * "root" member and return.
224
+ * - The value on the stack is an object. In this case store the key on the
225
+ * stack or, if the key has already been read, add key and value to the
226
+ * object.
227
+ * - The value on the stack is an array. In this case simply add the value
228
+ * and return.
229
+ */
230
+ if (ctx->stack == NULL)
231
+ {
232
+ assert (ctx->root == NULL);
233
+ ctx->root = v;
234
+ return (0);
235
+ }
236
+ else if (YAJL_IS_OBJECT (ctx->stack->value))
237
+ {
238
+ if (ctx->stack->key == NULL)
239
+ {
240
+ if (!YAJL_IS_STRING (v))
241
+ RETURN_ERROR (ctx, EINVAL, "context_add_value: "
242
+ "Object key is not a string (%#04x)",
243
+ v->type);
244
+
245
+ ctx->stack->key = v->u.string;
246
+ v->u.string = NULL;
247
+ free(v);
248
+ return (0);
249
+ }
250
+ else /* if (ctx->key != NULL) */
251
+ {
252
+ char * key;
253
+
254
+ key = ctx->stack->key;
255
+ ctx->stack->key = NULL;
256
+ return (object_add_keyval (ctx, ctx->stack->value, key, v));
257
+ }
258
+ }
259
+ else if (YAJL_IS_ARRAY (ctx->stack->value))
260
+ {
261
+ return (array_add_value (ctx, ctx->stack->value, v));
262
+ }
263
+ else
264
+ {
265
+ RETURN_ERROR (ctx, EINVAL, "context_add_value: Cannot add value to "
266
+ "a value of type %#04x (not a composite type)",
267
+ ctx->stack->value->type);
268
+ }
269
+ }
270
+
271
+ static int handle_string (void *ctx,
272
+ const unsigned char *string, size_t string_length)
273
+ {
274
+ yajl_val v;
275
+
276
+ v = value_alloc (yajl_t_string);
277
+ if (v == NULL)
278
+ RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory");
279
+
280
+ v->u.string = malloc (string_length + 1);
281
+ if (v->u.string == NULL)
282
+ {
283
+ free (v);
284
+ RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory");
285
+ }
286
+ memcpy(v->u.string, string, string_length);
287
+ v->u.string[string_length] = 0;
288
+
289
+ return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
290
+ }
291
+
292
+ static int handle_number (void *ctx, const char *string, size_t string_length)
293
+ {
294
+ yajl_val v;
295
+ char *endptr;
296
+
297
+ v = value_alloc(yajl_t_number);
298
+ if (v == NULL)
299
+ RETURN_ERROR((context_t *) ctx, STATUS_ABORT, "Out of memory");
300
+
301
+ v->u.number.r = malloc(string_length + 1);
302
+ if (v->u.number.r == NULL)
303
+ {
304
+ free(v);
305
+ RETURN_ERROR((context_t *) ctx, STATUS_ABORT, "Out of memory");
306
+ }
307
+ memcpy(v->u.number.r, string, string_length);
308
+ v->u.number.r[string_length] = 0;
309
+
310
+ v->u.number.flags = 0;
311
+
312
+ errno = 0;
313
+ v->u.number.i = yajl_parse_integer((const unsigned char *) v->u.number.r,
314
+ strlen(v->u.number.r));
315
+ if (errno == 0)
316
+ v->u.number.flags |= YAJL_NUMBER_INT_VALID;
317
+
318
+ endptr = NULL;
319
+ errno = 0;
320
+ v->u.number.d = strtod(v->u.number.r, &endptr);
321
+ if ((errno == 0) && (endptr != NULL) && (*endptr == 0))
322
+ v->u.number.flags |= YAJL_NUMBER_DOUBLE_VALID;
323
+
324
+ return ((context_add_value(ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
325
+ }
326
+
327
+ static int handle_start_map (void *ctx)
328
+ {
329
+ yajl_val v;
330
+
331
+ v = value_alloc(yajl_t_object);
332
+ if (v == NULL)
333
+ RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory");
334
+
335
+ v->u.object.keys = NULL;
336
+ v->u.object.values = NULL;
337
+ v->u.object.len = 0;
338
+
339
+ return ((context_push (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
340
+ }
341
+
342
+ static int handle_end_map (void *ctx)
343
+ {
344
+ yajl_val v;
345
+
346
+ v = context_pop (ctx);
347
+ if (v == NULL)
348
+ return (STATUS_ABORT);
349
+
350
+ return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
351
+ }
352
+
353
+ static int handle_start_array (void *ctx)
354
+ {
355
+ yajl_val v;
356
+
357
+ v = value_alloc(yajl_t_array);
358
+ if (v == NULL)
359
+ RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory");
360
+
361
+ v->u.array.values = NULL;
362
+ v->u.array.len = 0;
363
+
364
+ return ((context_push (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
365
+ }
366
+
367
+ static int handle_end_array (void *ctx)
368
+ {
369
+ yajl_val v;
370
+
371
+ v = context_pop (ctx);
372
+ if (v == NULL)
373
+ return (STATUS_ABORT);
374
+
375
+ return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
376
+ }
377
+
378
+ static int handle_boolean (void *ctx, int boolean_value)
379
+ {
380
+ yajl_val v;
381
+
382
+ v = value_alloc (boolean_value ? yajl_t_true : yajl_t_false);
383
+ if (v == NULL)
384
+ RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory");
385
+
386
+ return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
387
+ }
388
+
389
+ static int handle_null (void *ctx)
390
+ {
391
+ yajl_val v;
392
+
393
+ v = value_alloc (yajl_t_null);
394
+ if (v == NULL)
395
+ RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory");
396
+
397
+ return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
398
+ }
399
+
400
+ /*
401
+ * Public functions
402
+ */
403
+ yajl_val yajl_tree_parse (const char *input,
404
+ char *error_buffer, size_t error_buffer_size)
405
+ {
406
+ static const yajl_callbacks callbacks =
407
+ {
408
+ /* null = */ handle_null,
409
+ /* boolean = */ handle_boolean,
410
+ /* integer = */ NULL,
411
+ /* double = */ NULL,
412
+ /* number = */ handle_number,
413
+ /* string = */ handle_string,
414
+ /* start map = */ handle_start_map,
415
+ /* map key = */ handle_string,
416
+ /* end map = */ handle_end_map,
417
+ /* start array = */ handle_start_array,
418
+ /* end array = */ handle_end_array
419
+ };
420
+
421
+ yajl_handle handle;
422
+ yajl_status status;
423
+ char * internal_err_str;
424
+ context_t ctx = { NULL, NULL, NULL, 0 };
425
+
426
+ ctx.errbuf = error_buffer;
427
+ ctx.errbuf_size = error_buffer_size;
428
+
429
+ if (error_buffer != NULL)
430
+ memset (error_buffer, 0, error_buffer_size);
431
+
432
+ handle = yajl_alloc (&callbacks, NULL, &ctx);
433
+ yajl_config(handle, yajl_allow_comments, 1);
434
+
435
+ status = yajl_parse(handle,
436
+ (unsigned char *) input,
437
+ strlen (input));
438
+ status = yajl_complete_parse (handle);
439
+ if (status != yajl_status_ok) {
440
+ if (error_buffer != NULL && error_buffer_size > 0) {
441
+ internal_err_str = (char *) yajl_get_error(handle, 1,
442
+ (const unsigned char *) input,
443
+ strlen(input));
444
+ snprintf(error_buffer, error_buffer_size, "%s", internal_err_str);
445
+ YA_FREE(&(handle->alloc), internal_err_str);
446
+ }
447
+ yajl_free (handle);
448
+ return NULL;
449
+ }
450
+
451
+ yajl_free (handle);
452
+ return (ctx.root);
453
+ }
454
+
455
+ yajl_val yajl_tree_get(yajl_val n, const char ** path, yajl_type type)
456
+ {
457
+ if (!path) return NULL;
458
+ while (n && *path) {
459
+ size_t i;
460
+ size_t len;
461
+
462
+ if (n->type != yajl_t_object) return NULL;
463
+ len = n->u.object.len;
464
+ for (i = 0; i < len; i++) {
465
+ if (!strcmp(*path, n->u.object.keys[i])) {
466
+ n = n->u.object.values[i];
467
+ break;
468
+ }
469
+ }
470
+ if (i == len) return NULL;
471
+ path++;
472
+ }
473
+ if (n && type != yajl_t_any && type != n->type) n = NULL;
474
+ return n;
475
+ }
476
+
477
+ void yajl_tree_free (yajl_val v)
478
+ {
479
+ if (v == NULL) return;
480
+
481
+ if (YAJL_IS_STRING(v))
482
+ {
483
+ free(v->u.string);
484
+ free(v);
485
+ }
486
+ else if (YAJL_IS_NUMBER(v))
487
+ {
488
+ free(v->u.number.r);
489
+ free(v);
490
+ }
491
+ else if (YAJL_GET_OBJECT(v))
492
+ {
493
+ yajl_object_free(v);
494
+ }
495
+ else if (YAJL_GET_ARRAY(v))
496
+ {
497
+ yajl_array_free(v);
498
+ }
499
+ else /* if (yajl_t_true or yajl_t_false or yajl_t_null) */
500
+ {
501
+ free(v);
502
+ }
503
+ }
@@ -0,0 +1,7 @@
1
+ #include <yajl/yajl_version.h>
2
+
3
+ int yajl_version(void)
4
+ {
5
+ return YAJL_VERSION;
6
+ }
7
+
@@ -1,3 +1,3 @@
1
1
  module Libyajl2
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libyajl2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - lamont-granquist
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-16 00:00:00.000000000 Z
11
+ date: 2014-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -108,8 +108,13 @@ files:
108
108
  - README.md
109
109
  - Rakefile
110
110
  - bootstrap.sh
111
- - ext/libyajl2/Makefile
111
+ - ext/libyajl2/api/yajl_common.h
112
+ - ext/libyajl2/api/yajl_gen.h
113
+ - ext/libyajl2/api/yajl_parse.h
114
+ - ext/libyajl2/api/yajl_tree.h
115
+ - ext/libyajl2/api/yajl_version.h
112
116
  - ext/libyajl2/extconf.rb
117
+ - ext/libyajl2/patches/000-mingw-gcc.patch
113
118
  - ext/libyajl2/vendor/yajl/BUILDING
114
119
  - ext/libyajl2/vendor/yajl/BUILDING.win32
115
120
  - ext/libyajl2/vendor/yajl/CMakeLists.txt
@@ -278,6 +283,26 @@ files:
278
283
  - ext/libyajl2/vendor/yajl/test/parsing/yajl_test.c
279
284
  - ext/libyajl2/vendor/yajl/verify/CMakeLists.txt
280
285
  - ext/libyajl2/vendor/yajl/verify/json_verify.c
286
+ - ext/libyajl2/yajl.c
287
+ - ext/libyajl2/yajl/yajl_common.h
288
+ - ext/libyajl2/yajl/yajl_gen.h
289
+ - ext/libyajl2/yajl/yajl_parse.h
290
+ - ext/libyajl2/yajl/yajl_tree.h
291
+ - ext/libyajl2/yajl/yajl_version.h
292
+ - ext/libyajl2/yajl_alloc.c
293
+ - ext/libyajl2/yajl_alloc.h
294
+ - ext/libyajl2/yajl_buf.c
295
+ - ext/libyajl2/yajl_buf.h
296
+ - ext/libyajl2/yajl_bytestack.h
297
+ - ext/libyajl2/yajl_encode.c
298
+ - ext/libyajl2/yajl_encode.h
299
+ - ext/libyajl2/yajl_gen.c
300
+ - ext/libyajl2/yajl_lex.c
301
+ - ext/libyajl2/yajl_lex.h
302
+ - ext/libyajl2/yajl_parser.c
303
+ - ext/libyajl2/yajl_parser.h
304
+ - ext/libyajl2/yajl_tree.c
305
+ - ext/libyajl2/yajl_version.c
281
306
  - lib/libyajl2.rb
282
307
  - lib/libyajl2/version.rb
283
308
  - libyajl2.gemspec
@@ -1,9 +0,0 @@
1
- TARGET = libyajl
2
- DLLIB = $(TARGET).bundle
3
- all:
4
- cd /Users/lamont/git/libyajl2-gem/ext/libyajl2/vendor/yajl/src && make
5
- cp /Users/lamont/git/libyajl2-gem/ext/libyajl2/vendor/yajl/src/$(DLLIB) .
6
- install:
7
- cp $(DLLIB) /Users/lamont/git/libyajl2-gem/lib/libyajl2/vendored-libyajl2
8
- clean:
9
- cd /Users/lamont/git/libyajl2-gem/ext/libyajl2/vendor/yajl/src && make clean