ffi-yajl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/README.md +17 -0
  4. data/Rakefile +62 -0
  5. data/bin/ffi-yajl-bench +36 -0
  6. data/ext/ffi_yajl/ext/encoder/encoder.c +240 -0
  7. data/ext/ffi_yajl/ext/encoder/extconf.rb +29 -0
  8. data/ext/ffi_yajl/ext/parser/extconf.rb +29 -0
  9. data/ext/ffi_yajl/ext/parser/parser.c +199 -0
  10. data/ext/libyajl2/extconf.rb +65 -0
  11. data/ext/libyajl2/vendored/.gitignore +3 -0
  12. data/ext/libyajl2/vendored/BUILDING +23 -0
  13. data/ext/libyajl2/vendored/BUILDING.win32 +27 -0
  14. data/ext/libyajl2/vendored/CMakeLists.txt +79 -0
  15. data/ext/libyajl2/vendored/COPYING +13 -0
  16. data/ext/libyajl2/vendored/ChangeLog +175 -0
  17. data/ext/libyajl2/vendored/README +74 -0
  18. data/ext/libyajl2/vendored/TODO +9 -0
  19. data/ext/libyajl2/vendored/YAJLDoc.cmake +26 -0
  20. data/ext/libyajl2/vendored/configure +79 -0
  21. data/ext/libyajl2/vendored/example/CMakeLists.txt +23 -0
  22. data/ext/libyajl2/vendored/example/README.md +7 -0
  23. data/ext/libyajl2/vendored/example/parse_config.c +69 -0
  24. data/ext/libyajl2/vendored/example/sample.config +101 -0
  25. data/ext/libyajl2/vendored/perf/CMakeLists.txt +23 -0
  26. data/ext/libyajl2/vendored/perf/documents.c +1418 -0
  27. data/ext/libyajl2/vendored/perf/documents.h +28 -0
  28. data/ext/libyajl2/vendored/perf/perftest.c +134 -0
  29. data/ext/libyajl2/vendored/reformatter/CMakeLists.txt +39 -0
  30. data/ext/libyajl2/vendored/reformatter/json_reformat.c +194 -0
  31. data/ext/libyajl2/vendored/src/CMakeLists.txt +86 -0
  32. data/ext/libyajl2/vendored/src/YAJL.dxy +1258 -0
  33. data/ext/libyajl2/vendored/src/api/yajl_common.h +75 -0
  34. data/ext/libyajl2/vendored/src/api/yajl_gen.h +157 -0
  35. data/ext/libyajl2/vendored/src/api/yajl_parse.h +226 -0
  36. data/ext/libyajl2/vendored/src/api/yajl_tree.h +185 -0
  37. data/ext/libyajl2/vendored/src/api/yajl_version.h.cmake +23 -0
  38. data/ext/libyajl2/vendored/src/yajl +33 -0
  39. data/ext/libyajl2/vendored/src/yajl.c +175 -0
  40. data/ext/libyajl2/vendored/src/yajl.pc.cmake +9 -0
  41. data/ext/libyajl2/vendored/src/yajl_alloc.c +52 -0
  42. data/ext/libyajl2/vendored/src/yajl_alloc.h +34 -0
  43. data/ext/libyajl2/vendored/src/yajl_buf.c +103 -0
  44. data/ext/libyajl2/vendored/src/yajl_buf.h +57 -0
  45. data/ext/libyajl2/vendored/src/yajl_bytestack.h +69 -0
  46. data/ext/libyajl2/vendored/src/yajl_encode.c +220 -0
  47. data/ext/libyajl2/vendored/src/yajl_encode.h +34 -0
  48. data/ext/libyajl2/vendored/src/yajl_gen.c +354 -0
  49. data/ext/libyajl2/vendored/src/yajl_lex.c +763 -0
  50. data/ext/libyajl2/vendored/src/yajl_lex.h +117 -0
  51. data/ext/libyajl2/vendored/src/yajl_parser.c +498 -0
  52. data/ext/libyajl2/vendored/src/yajl_parser.h +78 -0
  53. data/ext/libyajl2/vendored/src/yajl_tree.c +503 -0
  54. data/ext/libyajl2/vendored/src/yajl_version.c +7 -0
  55. data/ext/libyajl2/vendored/test/CMakeLists.txt +23 -0
  56. data/ext/libyajl2/vendored/test/cases/ac_difficult_json_c_test_case_with_comments.json +1 -0
  57. data/ext/libyajl2/vendored/test/cases/ac_difficult_json_c_test_case_with_comments.json.gold +36 -0
  58. data/ext/libyajl2/vendored/test/cases/ac_simple_with_comments.json +11 -0
  59. data/ext/libyajl2/vendored/test/cases/ac_simple_with_comments.json.gold +9 -0
  60. data/ext/libyajl2/vendored/test/cases/ag_false_then_garbage.json +1 -0
  61. data/ext/libyajl2/vendored/test/cases/ag_false_then_garbage.json.gold +2 -0
  62. data/ext/libyajl2/vendored/test/cases/ag_null_then_garbage.json +1 -0
  63. data/ext/libyajl2/vendored/test/cases/ag_null_then_garbage.json.gold +2 -0
  64. data/ext/libyajl2/vendored/test/cases/ag_true_then_garbage.json +1 -0
  65. data/ext/libyajl2/vendored/test/cases/ag_true_then_garbage.json.gold +2 -0
  66. data/ext/libyajl2/vendored/test/cases/am_eof.json +1 -0
  67. data/ext/libyajl2/vendored/test/cases/am_eof.json.gold +4 -0
  68. data/ext/libyajl2/vendored/test/cases/am_integers.json +1 -0
  69. data/ext/libyajl2/vendored/test/cases/am_integers.json.gold +3 -0
  70. data/ext/libyajl2/vendored/test/cases/am_multiple.json +3 -0
  71. data/ext/libyajl2/vendored/test/cases/am_multiple.json.gold +5 -0
  72. data/ext/libyajl2/vendored/test/cases/am_stuff.json +7 -0
  73. data/ext/libyajl2/vendored/test/cases/am_stuff.json.gold +14 -0
  74. data/ext/libyajl2/vendored/test/cases/ap_array_open.json +1 -0
  75. data/ext/libyajl2/vendored/test/cases/ap_array_open.json.gold +2 -0
  76. data/ext/libyajl2/vendored/test/cases/ap_eof_str.json +1 -0
  77. data/ext/libyajl2/vendored/test/cases/ap_eof_str.json.gold +1 -0
  78. data/ext/libyajl2/vendored/test/cases/ap_map_open.json +1 -0
  79. data/ext/libyajl2/vendored/test/cases/ap_map_open.json.gold +2 -0
  80. data/ext/libyajl2/vendored/test/cases/ap_partial_ok.json +1 -0
  81. data/ext/libyajl2/vendored/test/cases/ap_partial_ok.json.gold +4 -0
  82. data/ext/libyajl2/vendored/test/cases/array.json +6 -0
  83. data/ext/libyajl2/vendored/test/cases/array.json.gold +22 -0
  84. data/ext/libyajl2/vendored/test/cases/array_close.json +1 -0
  85. data/ext/libyajl2/vendored/test/cases/array_close.json.gold +2 -0
  86. data/ext/libyajl2/vendored/test/cases/bignums.json +1 -0
  87. data/ext/libyajl2/vendored/test/cases/bignums.json.gold +5 -0
  88. data/ext/libyajl2/vendored/test/cases/bogus_char.json +4 -0
  89. data/ext/libyajl2/vendored/test/cases/bogus_char.json.gold +10 -0
  90. data/ext/libyajl2/vendored/test/cases/codepoints_from_unicode_org.json +1 -0
  91. data/ext/libyajl2/vendored/test/cases/codepoints_from_unicode_org.json.gold +2 -0
  92. data/ext/libyajl2/vendored/test/cases/deep_arrays.json +1 -0
  93. data/ext/libyajl2/vendored/test/cases/deep_arrays.json.gold +2049 -0
  94. data/ext/libyajl2/vendored/test/cases/difficult_json_c_test_case.json +1 -0
  95. data/ext/libyajl2/vendored/test/cases/difficult_json_c_test_case.json.gold +36 -0
  96. data/ext/libyajl2/vendored/test/cases/doubles.json +1 -0
  97. data/ext/libyajl2/vendored/test/cases/doubles.json.gold +7 -0
  98. data/ext/libyajl2/vendored/test/cases/doubles_in_array.json +1 -0
  99. data/ext/libyajl2/vendored/test/cases/doubles_in_array.json.gold +8 -0
  100. data/ext/libyajl2/vendored/test/cases/empty_array.json +1 -0
  101. data/ext/libyajl2/vendored/test/cases/empty_array.json.gold +3 -0
  102. data/ext/libyajl2/vendored/test/cases/empty_string.json +1 -0
  103. data/ext/libyajl2/vendored/test/cases/empty_string.json.gold +2 -0
  104. data/ext/libyajl2/vendored/test/cases/escaped_bulgarian.json +4 -0
  105. data/ext/libyajl2/vendored/test/cases/escaped_bulgarian.json.gold +7 -0
  106. data/ext/libyajl2/vendored/test/cases/escaped_foobar.json +1 -0
  107. data/ext/libyajl2/vendored/test/cases/escaped_foobar.json.gold +2 -0
  108. data/ext/libyajl2/vendored/test/cases/false.json +1 -0
  109. data/ext/libyajl2/vendored/test/cases/false.json.gold +2 -0
  110. data/ext/libyajl2/vendored/test/cases/fg_false_then_garbage.json +1 -0
  111. data/ext/libyajl2/vendored/test/cases/fg_false_then_garbage.json.gold +3 -0
  112. data/ext/libyajl2/vendored/test/cases/fg_issue_7.json +1 -0
  113. data/ext/libyajl2/vendored/test/cases/fg_issue_7.json.gold +3 -0
  114. data/ext/libyajl2/vendored/test/cases/fg_null_then_garbage.json +1 -0
  115. data/ext/libyajl2/vendored/test/cases/fg_null_then_garbage.json.gold +3 -0
  116. data/ext/libyajl2/vendored/test/cases/fg_true_then_garbage.json +1 -0
  117. data/ext/libyajl2/vendored/test/cases/fg_true_then_garbage.json.gold +3 -0
  118. data/ext/libyajl2/vendored/test/cases/four_byte_utf8.json +2 -0
  119. data/ext/libyajl2/vendored/test/cases/four_byte_utf8.json.gold +5 -0
  120. data/ext/libyajl2/vendored/test/cases/high_overflow.json +1 -0
  121. data/ext/libyajl2/vendored/test/cases/high_overflow.json.gold +2 -0
  122. data/ext/libyajl2/vendored/test/cases/integers.json +3 -0
  123. data/ext/libyajl2/vendored/test/cases/integers.json.gold +14 -0
  124. data/ext/libyajl2/vendored/test/cases/invalid_utf8.json +1 -0
  125. data/ext/libyajl2/vendored/test/cases/invalid_utf8.json.gold +3 -0
  126. data/ext/libyajl2/vendored/test/cases/isolated_surrogate_marker.json +1 -0
  127. data/ext/libyajl2/vendored/test/cases/isolated_surrogate_marker.json.gold +2 -0
  128. data/ext/libyajl2/vendored/test/cases/leading_zero_in_number.json +1 -0
  129. data/ext/libyajl2/vendored/test/cases/leading_zero_in_number.json.gold +5 -0
  130. data/ext/libyajl2/vendored/test/cases/lonely_minus_sign.json +7 -0
  131. data/ext/libyajl2/vendored/test/cases/lonely_minus_sign.json.gold +9 -0
  132. data/ext/libyajl2/vendored/test/cases/lonely_number.json +1 -0
  133. data/ext/libyajl2/vendored/test/cases/lonely_number.json.gold +2 -0
  134. data/ext/libyajl2/vendored/test/cases/low_overflow.json +1 -0
  135. data/ext/libyajl2/vendored/test/cases/low_overflow.json.gold +2 -0
  136. data/ext/libyajl2/vendored/test/cases/map_close.json +1 -0
  137. data/ext/libyajl2/vendored/test/cases/map_close.json.gold +2 -0
  138. data/ext/libyajl2/vendored/test/cases/missing_integer_after_decimal_point.json +1 -0
  139. data/ext/libyajl2/vendored/test/cases/missing_integer_after_decimal_point.json.gold +2 -0
  140. data/ext/libyajl2/vendored/test/cases/missing_integer_after_exponent.json +1 -0
  141. data/ext/libyajl2/vendored/test/cases/missing_integer_after_exponent.json.gold +2 -0
  142. data/ext/libyajl2/vendored/test/cases/multiple.json +3 -0
  143. data/ext/libyajl2/vendored/test/cases/multiple.json.gold +4 -0
  144. data/ext/libyajl2/vendored/test/cases/non_utf8_char_in_string.json +1 -0
  145. data/ext/libyajl2/vendored/test/cases/non_utf8_char_in_string.json.gold +8 -0
  146. data/ext/libyajl2/vendored/test/cases/np_partial_bad.json +1 -0
  147. data/ext/libyajl2/vendored/test/cases/np_partial_bad.json.gold +5 -0
  148. data/ext/libyajl2/vendored/test/cases/null.json +1 -0
  149. data/ext/libyajl2/vendored/test/cases/null.json.gold +2 -0
  150. data/ext/libyajl2/vendored/test/cases/nulls_and_bools.json +5 -0
  151. data/ext/libyajl2/vendored/test/cases/nulls_and_bools.json.gold +9 -0
  152. data/ext/libyajl2/vendored/test/cases/simple.json +5 -0
  153. data/ext/libyajl2/vendored/test/cases/simple.json.gold +9 -0
  154. data/ext/libyajl2/vendored/test/cases/simple_with_comments.json +11 -0
  155. data/ext/libyajl2/vendored/test/cases/simple_with_comments.json.gold +5 -0
  156. data/ext/libyajl2/vendored/test/cases/string_invalid_escape.json +1 -0
  157. data/ext/libyajl2/vendored/test/cases/string_invalid_escape.json.gold +3 -0
  158. data/ext/libyajl2/vendored/test/cases/string_invalid_hex_char.json +1 -0
  159. data/ext/libyajl2/vendored/test/cases/string_invalid_hex_char.json.gold +2 -0
  160. data/ext/libyajl2/vendored/test/cases/string_with_escapes.json +3 -0
  161. data/ext/libyajl2/vendored/test/cases/string_with_escapes.json.gold +7 -0
  162. data/ext/libyajl2/vendored/test/cases/string_with_invalid_newline.json +2 -0
  163. data/ext/libyajl2/vendored/test/cases/string_with_invalid_newline.json.gold +2 -0
  164. data/ext/libyajl2/vendored/test/cases/three_byte_utf8.json +1 -0
  165. data/ext/libyajl2/vendored/test/cases/three_byte_utf8.json.gold +7 -0
  166. data/ext/libyajl2/vendored/test/cases/true.json +1 -0
  167. data/ext/libyajl2/vendored/test/cases/true.json.gold +2 -0
  168. data/ext/libyajl2/vendored/test/cases/unescaped_bulgarian.json +1 -0
  169. data/ext/libyajl2/vendored/test/cases/unescaped_bulgarian.json.gold +4 -0
  170. data/ext/libyajl2/vendored/test/cases/zerobyte.json +1 -0
  171. data/ext/libyajl2/vendored/test/cases/zerobyte.json.gold +0 -0
  172. data/ext/libyajl2/vendored/test/run_tests.sh +94 -0
  173. data/ext/libyajl2/vendored/test/yajl_test.c +281 -0
  174. data/ext/libyajl2/vendored/verify/CMakeLists.txt +39 -0
  175. data/ext/libyajl2/vendored/verify/json_verify.c +116 -0
  176. data/lib/ffi_yajl.rb +14 -0
  177. data/lib/ffi_yajl/benchmark.rb +7 -0
  178. data/lib/ffi_yajl/benchmark/MIT-LICENSE +20 -0
  179. data/lib/ffi_yajl/benchmark/encode.rb +135 -0
  180. data/lib/ffi_yajl/benchmark/encode_json_and_marshal.rb +42 -0
  181. data/lib/ffi_yajl/benchmark/encode_json_and_yaml.rb +53 -0
  182. data/lib/ffi_yajl/benchmark/encode_profile.rb +38 -0
  183. data/lib/ffi_yajl/benchmark/http.rb +32 -0
  184. data/lib/ffi_yajl/benchmark/parse.rb +133 -0
  185. data/lib/ffi_yajl/benchmark/parse_json_and_marshal.rb +50 -0
  186. data/lib/ffi_yajl/benchmark/parse_json_and_yaml.rb +55 -0
  187. data/lib/ffi_yajl/benchmark/parse_profile.rb +37 -0
  188. data/lib/ffi_yajl/benchmark/parse_profile_ruby_prof.rb +39 -0
  189. data/lib/ffi_yajl/benchmark/parse_stream.rb +54 -0
  190. data/lib/ffi_yajl/benchmark/subjects/item.json +1 -0
  191. data/lib/ffi_yajl/benchmark/subjects/ohai.json +1216 -0
  192. data/lib/ffi_yajl/benchmark/subjects/ohai.marshal_dump +0 -0
  193. data/lib/ffi_yajl/benchmark/subjects/ohai.yml +975 -0
  194. data/lib/ffi_yajl/benchmark/subjects/twitter_search.json +1 -0
  195. data/lib/ffi_yajl/benchmark/subjects/twitter_stream.json +430 -0
  196. data/lib/ffi_yajl/benchmark/subjects/unicode.json +1 -0
  197. data/lib/ffi_yajl/encoder.rb +53 -0
  198. data/lib/ffi_yajl/ext.rb +22 -0
  199. data/lib/ffi_yajl/ext/.keep +0 -0
  200. data/lib/ffi_yajl/ffi.rb +129 -0
  201. data/lib/ffi_yajl/ffi/encoder.rb +175 -0
  202. data/lib/ffi_yajl/ffi/parser.rb +145 -0
  203. data/lib/ffi_yajl/json_gem.rb +121 -0
  204. data/lib/ffi_yajl/parser.rb +23 -0
  205. data/lib/ffi_yajl/version.rb +3 -0
  206. data/lib/libyajl.so +0 -0
  207. data/lib/libyajl.so.2 +0 -0
  208. data/lib/libyajl.so.2.0.5 +0 -0
  209. data/lib/libyajl_s.a +0 -0
  210. data/spec/ffi_yajl/encoder_spec.rb +39 -0
  211. data/spec/ffi_yajl/json_gem_spec.rb +355 -0
  212. data/spec/ffi_yajl/parser_spec.rb +78 -0
  213. data/spec/spec_helper.rb +14 -0
  214. metadata +332 -0
@@ -0,0 +1,78 @@
1
+ /*
2
+ * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
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
+ #ifndef __YAJL_PARSER_H__
18
+ #define __YAJL_PARSER_H__
19
+
20
+ #include "api/yajl_parse.h"
21
+ #include "yajl_bytestack.h"
22
+ #include "yajl_buf.h"
23
+ #include "yajl_lex.h"
24
+
25
+
26
+ typedef enum {
27
+ yajl_state_start = 0,
28
+ yajl_state_parse_complete,
29
+ yajl_state_parse_error,
30
+ yajl_state_lexical_error,
31
+ yajl_state_map_start,
32
+ yajl_state_map_sep,
33
+ yajl_state_map_need_val,
34
+ yajl_state_map_got_val,
35
+ yajl_state_map_need_key,
36
+ yajl_state_array_start,
37
+ yajl_state_array_got_val,
38
+ yajl_state_array_need_val,
39
+ yajl_state_got_value,
40
+ } yajl_state;
41
+
42
+ struct yajl_handle_t {
43
+ const yajl_callbacks * callbacks;
44
+ void * ctx;
45
+ yajl_lexer lexer;
46
+ const char * parseError;
47
+ /* the number of bytes consumed from the last client buffer,
48
+ * in the case of an error this will be an error offset, in the
49
+ * case of an error this can be used as the error offset */
50
+ size_t bytesConsumed;
51
+ /* temporary storage for decoded strings */
52
+ yajl_buf decodeBuf;
53
+ /* a stack of states. access with yajl_state_XXX routines */
54
+ yajl_bytestack stateStack;
55
+ /* memory allocation routines */
56
+ yajl_alloc_funcs alloc;
57
+ /* bitfield */
58
+ unsigned int flags;
59
+ };
60
+
61
+ yajl_status
62
+ yajl_do_parse(yajl_handle handle, const unsigned char * jsonText,
63
+ size_t jsonTextLen);
64
+
65
+ yajl_status
66
+ yajl_do_finish(yajl_handle handle);
67
+
68
+ unsigned char *
69
+ yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText,
70
+ size_t jsonTextLen, int verbose);
71
+
72
+ /* A little built in integer parsing routine with the same semantics as strtol
73
+ * that's unaffected by LOCALE. */
74
+ long long
75
+ yajl_parse_integer(const unsigned char *number, unsigned int length);
76
+
77
+
78
+ #endif
@@ -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)
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
+ }