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,117 @@
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_LEX_H__
18
+ #define __YAJL_LEX_H__
19
+
20
+ #include "api/yajl_common.h"
21
+
22
+ typedef enum {
23
+ yajl_tok_bool,
24
+ yajl_tok_colon,
25
+ yajl_tok_comma,
26
+ yajl_tok_eof,
27
+ yajl_tok_error,
28
+ yajl_tok_left_brace,
29
+ yajl_tok_left_bracket,
30
+ yajl_tok_null,
31
+ yajl_tok_right_brace,
32
+ yajl_tok_right_bracket,
33
+
34
+ /* we differentiate between integers and doubles to allow the
35
+ * parser to interpret the number without re-scanning */
36
+ yajl_tok_integer,
37
+ yajl_tok_double,
38
+
39
+ /* we differentiate between strings which require further processing,
40
+ * and strings that do not */
41
+ yajl_tok_string,
42
+ yajl_tok_string_with_escapes,
43
+
44
+ /* comment tokens are not currently returned to the parser, ever */
45
+ yajl_tok_comment
46
+ } yajl_tok;
47
+
48
+ typedef struct yajl_lexer_t * yajl_lexer;
49
+
50
+ yajl_lexer yajl_lex_alloc(yajl_alloc_funcs * alloc,
51
+ unsigned int allowComments,
52
+ unsigned int validateUTF8);
53
+
54
+ void yajl_lex_free(yajl_lexer lexer);
55
+
56
+ /**
57
+ * run/continue a lex. "offset" is an input/output parameter.
58
+ * It should be initialized to zero for a
59
+ * new chunk of target text, and upon subsetquent calls with the same
60
+ * target text should passed with the value of the previous invocation.
61
+ *
62
+ * the client may be interested in the value of offset when an error is
63
+ * returned from the lexer. This allows the client to render useful
64
+ n * error messages.
65
+ *
66
+ * When you pass the next chunk of data, context should be reinitialized
67
+ * to zero.
68
+ *
69
+ * Finally, the output buffer is usually just a pointer into the jsonText,
70
+ * however in cases where the entity being lexed spans multiple chunks,
71
+ * the lexer will buffer the entity and the data returned will be
72
+ * a pointer into that buffer.
73
+ *
74
+ * This behavior is abstracted from client code except for the performance
75
+ * implications which require that the client choose a reasonable chunk
76
+ * size to get adequate performance.
77
+ */
78
+ yajl_tok yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText,
79
+ size_t jsonTextLen, size_t * offset,
80
+ const unsigned char ** outBuf, size_t * outLen);
81
+
82
+ /** have a peek at the next token, but don't move the lexer forward */
83
+ yajl_tok yajl_lex_peek(yajl_lexer lexer, const unsigned char * jsonText,
84
+ size_t jsonTextLen, size_t offset);
85
+
86
+
87
+ typedef enum {
88
+ yajl_lex_e_ok = 0,
89
+ yajl_lex_string_invalid_utf8,
90
+ yajl_lex_string_invalid_escaped_char,
91
+ yajl_lex_string_invalid_json_char,
92
+ yajl_lex_string_invalid_hex_char,
93
+ yajl_lex_invalid_char,
94
+ yajl_lex_invalid_string,
95
+ yajl_lex_missing_integer_after_decimal,
96
+ yajl_lex_missing_integer_after_exponent,
97
+ yajl_lex_missing_integer_after_minus,
98
+ yajl_lex_unallowed_comment
99
+ } yajl_lex_error;
100
+
101
+ const char * yajl_lex_error_to_string(yajl_lex_error error);
102
+
103
+ /** allows access to more specific information about the lexical
104
+ * error when yajl_lex_lex returns yajl_tok_error. */
105
+ yajl_lex_error yajl_lex_get_error(yajl_lexer lexer);
106
+
107
+ /** get the current offset into the most recently lexed json string. */
108
+ size_t yajl_lex_current_offset(yajl_lexer lexer);
109
+
110
+ /** get the number of lines lexed by this lexer instance */
111
+ size_t yajl_lex_current_line(yajl_lexer lexer);
112
+
113
+ /** get the number of chars lexed by this lexer instance since the last
114
+ * \n or \r */
115
+ size_t yajl_lex_current_char(yajl_lexer lexer);
116
+
117
+ #endif
@@ -0,0 +1,498 @@
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
+ #include "api/yajl_parse.h"
18
+ #include "yajl_lex.h"
19
+ #include "yajl_parser.h"
20
+ #include "yajl_encode.h"
21
+ #include "yajl_bytestack.h"
22
+
23
+ #include <stdlib.h>
24
+ #include <limits.h>
25
+ #include <errno.h>
26
+ #include <stdio.h>
27
+ #include <string.h>
28
+ #include <ctype.h>
29
+ #include <assert.h>
30
+ #include <math.h>
31
+
32
+ #define MAX_VALUE_TO_MULTIPLY ((LLONG_MAX / 10) + (LLONG_MAX % 10))
33
+
34
+ /* same semantics as strtol */
35
+ long long
36
+ yajl_parse_integer(const unsigned char *number, unsigned int length)
37
+ {
38
+ long long ret = 0;
39
+ long sign = 1;
40
+ const unsigned char *pos = number;
41
+ if (*pos == '-') { pos++; sign = -1; }
42
+ if (*pos == '+') { pos++; }
43
+
44
+ while (pos < number + length) {
45
+ if ( ret > MAX_VALUE_TO_MULTIPLY ) {
46
+ errno = ERANGE;
47
+ return sign == 1 ? LLONG_MAX : LLONG_MIN;
48
+ }
49
+ ret *= 10;
50
+ if (LLONG_MAX - ret < (*pos - '0')) {
51
+ errno = ERANGE;
52
+ return sign == 1 ? LLONG_MAX : LLONG_MIN;
53
+ }
54
+ if (*pos < '0' || *pos > '9') {
55
+ errno = ERANGE;
56
+ return sign == 1 ? LLONG_MAX : LLONG_MIN;
57
+ }
58
+ ret += (*pos++ - '0');
59
+ }
60
+
61
+ return sign * ret;
62
+ }
63
+
64
+ unsigned char *
65
+ yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText,
66
+ size_t jsonTextLen, int verbose)
67
+ {
68
+ size_t offset = hand->bytesConsumed;
69
+ unsigned char * str;
70
+ const char * errorType = NULL;
71
+ const char * errorText = NULL;
72
+ char text[72];
73
+ const char * arrow = " (right here) ------^\n";
74
+
75
+ if (yajl_bs_current(hand->stateStack) == yajl_state_parse_error) {
76
+ errorType = "parse";
77
+ errorText = hand->parseError;
78
+ } else if (yajl_bs_current(hand->stateStack) == yajl_state_lexical_error) {
79
+ errorType = "lexical";
80
+ errorText = yajl_lex_error_to_string(yajl_lex_get_error(hand->lexer));
81
+ } else {
82
+ errorType = "unknown";
83
+ }
84
+
85
+ {
86
+ size_t memneeded = 0;
87
+ memneeded += strlen(errorType);
88
+ memneeded += strlen(" error");
89
+ if (errorText != NULL) {
90
+ memneeded += strlen(": ");
91
+ memneeded += strlen(errorText);
92
+ }
93
+ str = (unsigned char *) YA_MALLOC(&(hand->alloc), memneeded + 2);
94
+ if (!str) return NULL;
95
+ str[0] = 0;
96
+ strcat((char *) str, errorType);
97
+ strcat((char *) str, " error");
98
+ if (errorText != NULL) {
99
+ strcat((char *) str, ": ");
100
+ strcat((char *) str, errorText);
101
+ }
102
+ strcat((char *) str, "\n");
103
+ }
104
+
105
+ /* now we append as many spaces as needed to make sure the error
106
+ * falls at char 41, if verbose was specified */
107
+ if (verbose) {
108
+ size_t start, end, i;
109
+ size_t spacesNeeded;
110
+
111
+ spacesNeeded = (offset < 30 ? 40 - offset : 10);
112
+ start = (offset >= 30 ? offset - 30 : 0);
113
+ end = (offset + 30 > jsonTextLen ? jsonTextLen : offset + 30);
114
+
115
+ for (i=0;i<spacesNeeded;i++) text[i] = ' ';
116
+
117
+ for (;start < end;start++, i++) {
118
+ if (jsonText[start] != '\n' && jsonText[start] != '\r')
119
+ {
120
+ text[i] = jsonText[start];
121
+ }
122
+ else
123
+ {
124
+ text[i] = ' ';
125
+ }
126
+ }
127
+ assert(i <= 71);
128
+ text[i++] = '\n';
129
+ text[i] = 0;
130
+ {
131
+ char * newStr = (char *)
132
+ YA_MALLOC(&(hand->alloc), (unsigned int)(strlen((char *) str) +
133
+ strlen((char *) text) +
134
+ strlen(arrow) + 1));
135
+ if (newStr) {
136
+ newStr[0] = 0;
137
+ strcat((char *) newStr, (char *) str);
138
+ strcat((char *) newStr, text);
139
+ strcat((char *) newStr, arrow);
140
+ }
141
+ YA_FREE(&(hand->alloc), str);
142
+ str = (unsigned char *) newStr;
143
+ }
144
+ }
145
+ return str;
146
+ }
147
+
148
+ /* check for client cancelation */
149
+ #define _CC_CHK(x) \
150
+ if (!(x)) { \
151
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error); \
152
+ hand->parseError = \
153
+ "client cancelled parse via callback return value"; \
154
+ return yajl_status_client_canceled; \
155
+ }
156
+
157
+
158
+ yajl_status
159
+ yajl_do_finish(yajl_handle hand)
160
+ {
161
+ yajl_status stat;
162
+ stat = yajl_do_parse(hand,(const unsigned char *) " ",1);
163
+
164
+ if (stat != yajl_status_ok) return stat;
165
+
166
+ switch(yajl_bs_current(hand->stateStack))
167
+ {
168
+ case yajl_state_parse_error:
169
+ case yajl_state_lexical_error:
170
+ return yajl_status_error;
171
+ case yajl_state_got_value:
172
+ case yajl_state_parse_complete:
173
+ return yajl_status_ok;
174
+ default:
175
+ if (!(hand->flags & yajl_allow_partial_values))
176
+ {
177
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error);
178
+ hand->parseError = "premature EOF";
179
+ return yajl_status_error;
180
+ }
181
+ return yajl_status_ok;
182
+ }
183
+ }
184
+
185
+ yajl_status
186
+ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
187
+ size_t jsonTextLen)
188
+ {
189
+ yajl_tok tok;
190
+ const unsigned char * buf;
191
+ size_t bufLen;
192
+ size_t * offset = &(hand->bytesConsumed);
193
+
194
+ *offset = 0;
195
+
196
+ around_again:
197
+ switch (yajl_bs_current(hand->stateStack)) {
198
+ case yajl_state_parse_complete:
199
+ if (hand->flags & yajl_allow_multiple_values) {
200
+ yajl_bs_set(hand->stateStack, yajl_state_got_value);
201
+ goto around_again;
202
+ }
203
+ if (!(hand->flags & yajl_allow_trailing_garbage)) {
204
+ if (*offset != jsonTextLen) {
205
+ tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
206
+ offset, &buf, &bufLen);
207
+ if (tok != yajl_tok_eof) {
208
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error);
209
+ hand->parseError = "trailing garbage";
210
+ }
211
+ goto around_again;
212
+ }
213
+ }
214
+ return yajl_status_ok;
215
+ case yajl_state_lexical_error:
216
+ case yajl_state_parse_error:
217
+ return yajl_status_error;
218
+ case yajl_state_start:
219
+ case yajl_state_got_value:
220
+ case yajl_state_map_need_val:
221
+ case yajl_state_array_need_val:
222
+ case yajl_state_array_start: {
223
+ /* for arrays and maps, we advance the state for this
224
+ * depth, then push the state of the next depth.
225
+ * If an error occurs during the parsing of the nesting
226
+ * enitity, the state at this level will not matter.
227
+ * a state that needs pushing will be anything other
228
+ * than state_start */
229
+
230
+ yajl_state stateToPush = yajl_state_start;
231
+
232
+ tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
233
+ offset, &buf, &bufLen);
234
+
235
+ switch (tok) {
236
+ case yajl_tok_eof:
237
+ return yajl_status_ok;
238
+ case yajl_tok_error:
239
+ yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
240
+ goto around_again;
241
+ case yajl_tok_string:
242
+ if (hand->callbacks && hand->callbacks->yajl_string) {
243
+ _CC_CHK(hand->callbacks->yajl_string(hand->ctx,
244
+ buf, bufLen));
245
+ }
246
+ break;
247
+ case yajl_tok_string_with_escapes:
248
+ if (hand->callbacks && hand->callbacks->yajl_string) {
249
+ yajl_buf_clear(hand->decodeBuf);
250
+ yajl_string_decode(hand->decodeBuf, buf, bufLen);
251
+ _CC_CHK(hand->callbacks->yajl_string(
252
+ hand->ctx, yajl_buf_data(hand->decodeBuf),
253
+ yajl_buf_len(hand->decodeBuf)));
254
+ }
255
+ break;
256
+ case yajl_tok_bool:
257
+ if (hand->callbacks && hand->callbacks->yajl_boolean) {
258
+ _CC_CHK(hand->callbacks->yajl_boolean(hand->ctx,
259
+ *buf == 't'));
260
+ }
261
+ break;
262
+ case yajl_tok_null:
263
+ if (hand->callbacks && hand->callbacks->yajl_null) {
264
+ _CC_CHK(hand->callbacks->yajl_null(hand->ctx));
265
+ }
266
+ break;
267
+ case yajl_tok_left_bracket:
268
+ if (hand->callbacks && hand->callbacks->yajl_start_map) {
269
+ _CC_CHK(hand->callbacks->yajl_start_map(hand->ctx));
270
+ }
271
+ stateToPush = yajl_state_map_start;
272
+ break;
273
+ case yajl_tok_left_brace:
274
+ if (hand->callbacks && hand->callbacks->yajl_start_array) {
275
+ _CC_CHK(hand->callbacks->yajl_start_array(hand->ctx));
276
+ }
277
+ stateToPush = yajl_state_array_start;
278
+ break;
279
+ case yajl_tok_integer:
280
+ if (hand->callbacks) {
281
+ if (hand->callbacks->yajl_number) {
282
+ _CC_CHK(hand->callbacks->yajl_number(
283
+ hand->ctx,(const char *) buf, bufLen));
284
+ } else if (hand->callbacks->yajl_integer) {
285
+ long long int i = 0;
286
+ errno = 0;
287
+ i = yajl_parse_integer(buf, bufLen);
288
+ if ((i == LLONG_MIN || i == LLONG_MAX) &&
289
+ errno == ERANGE)
290
+ {
291
+ yajl_bs_set(hand->stateStack,
292
+ yajl_state_parse_error);
293
+ hand->parseError = "integer overflow" ;
294
+ /* try to restore error offset */
295
+ if (*offset >= bufLen) *offset -= bufLen;
296
+ else *offset = 0;
297
+ goto around_again;
298
+ }
299
+ _CC_CHK(hand->callbacks->yajl_integer(hand->ctx,
300
+ i));
301
+ }
302
+ }
303
+ break;
304
+ case yajl_tok_double:
305
+ if (hand->callbacks) {
306
+ if (hand->callbacks->yajl_number) {
307
+ _CC_CHK(hand->callbacks->yajl_number(
308
+ hand->ctx, (const char *) buf, bufLen));
309
+ } else if (hand->callbacks->yajl_double) {
310
+ double d = 0.0;
311
+ yajl_buf_clear(hand->decodeBuf);
312
+ yajl_buf_append(hand->decodeBuf, buf, bufLen);
313
+ buf = yajl_buf_data(hand->decodeBuf);
314
+ errno = 0;
315
+ d = strtod((char *) buf, NULL);
316
+ if ((d == HUGE_VAL || d == -HUGE_VAL) &&
317
+ errno == ERANGE)
318
+ {
319
+ yajl_bs_set(hand->stateStack,
320
+ yajl_state_parse_error);
321
+ hand->parseError = "numeric (floating point) "
322
+ "overflow";
323
+ /* try to restore error offset */
324
+ if (*offset >= bufLen) *offset -= bufLen;
325
+ else *offset = 0;
326
+ goto around_again;
327
+ }
328
+ _CC_CHK(hand->callbacks->yajl_double(hand->ctx,
329
+ d));
330
+ }
331
+ }
332
+ break;
333
+ case yajl_tok_right_brace: {
334
+ if (yajl_bs_current(hand->stateStack) ==
335
+ yajl_state_array_start)
336
+ {
337
+ if (hand->callbacks &&
338
+ hand->callbacks->yajl_end_array)
339
+ {
340
+ _CC_CHK(hand->callbacks->yajl_end_array(hand->ctx));
341
+ }
342
+ yajl_bs_pop(hand->stateStack);
343
+ goto around_again;
344
+ }
345
+ /* intentional fall-through */
346
+ }
347
+ case yajl_tok_colon:
348
+ case yajl_tok_comma:
349
+ case yajl_tok_right_bracket:
350
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error);
351
+ hand->parseError =
352
+ "unallowed token at this point in JSON text";
353
+ goto around_again;
354
+ default:
355
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error);
356
+ hand->parseError = "invalid token, internal error";
357
+ goto around_again;
358
+ }
359
+ /* got a value. transition depends on the state we're in. */
360
+ {
361
+ yajl_state s = yajl_bs_current(hand->stateStack);
362
+ if (s == yajl_state_start || s == yajl_state_got_value) {
363
+ yajl_bs_set(hand->stateStack, yajl_state_parse_complete);
364
+ } else if (s == yajl_state_map_need_val) {
365
+ yajl_bs_set(hand->stateStack, yajl_state_map_got_val);
366
+ } else {
367
+ yajl_bs_set(hand->stateStack, yajl_state_array_got_val);
368
+ }
369
+ }
370
+ if (stateToPush != yajl_state_start) {
371
+ yajl_bs_push(hand->stateStack, stateToPush);
372
+ }
373
+
374
+ goto around_again;
375
+ }
376
+ case yajl_state_map_start:
377
+ case yajl_state_map_need_key: {
378
+ /* only difference between these two states is that in
379
+ * start '}' is valid, whereas in need_key, we've parsed
380
+ * a comma, and a string key _must_ follow */
381
+ tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
382
+ offset, &buf, &bufLen);
383
+ switch (tok) {
384
+ case yajl_tok_eof:
385
+ return yajl_status_ok;
386
+ case yajl_tok_error:
387
+ yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
388
+ goto around_again;
389
+ case yajl_tok_string_with_escapes:
390
+ if (hand->callbacks && hand->callbacks->yajl_map_key) {
391
+ yajl_buf_clear(hand->decodeBuf);
392
+ yajl_string_decode(hand->decodeBuf, buf, bufLen);
393
+ buf = yajl_buf_data(hand->decodeBuf);
394
+ bufLen = yajl_buf_len(hand->decodeBuf);
395
+ }
396
+ /* intentional fall-through */
397
+ case yajl_tok_string:
398
+ if (hand->callbacks && hand->callbacks->yajl_map_key) {
399
+ _CC_CHK(hand->callbacks->yajl_map_key(hand->ctx, buf,
400
+ bufLen));
401
+ }
402
+ yajl_bs_set(hand->stateStack, yajl_state_map_sep);
403
+ goto around_again;
404
+ case yajl_tok_right_bracket:
405
+ if (yajl_bs_current(hand->stateStack) ==
406
+ yajl_state_map_start)
407
+ {
408
+ if (hand->callbacks && hand->callbacks->yajl_end_map) {
409
+ _CC_CHK(hand->callbacks->yajl_end_map(hand->ctx));
410
+ }
411
+ yajl_bs_pop(hand->stateStack);
412
+ goto around_again;
413
+ }
414
+ default:
415
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error);
416
+ hand->parseError =
417
+ "invalid object key (must be a string)";
418
+ goto around_again;
419
+ }
420
+ }
421
+ case yajl_state_map_sep: {
422
+ tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
423
+ offset, &buf, &bufLen);
424
+ switch (tok) {
425
+ case yajl_tok_colon:
426
+ yajl_bs_set(hand->stateStack, yajl_state_map_need_val);
427
+ goto around_again;
428
+ case yajl_tok_eof:
429
+ return yajl_status_ok;
430
+ case yajl_tok_error:
431
+ yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
432
+ goto around_again;
433
+ default:
434
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error);
435
+ hand->parseError = "object key and value must "
436
+ "be separated by a colon (':')";
437
+ goto around_again;
438
+ }
439
+ }
440
+ case yajl_state_map_got_val: {
441
+ tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
442
+ offset, &buf, &bufLen);
443
+ switch (tok) {
444
+ case yajl_tok_right_bracket:
445
+ if (hand->callbacks && hand->callbacks->yajl_end_map) {
446
+ _CC_CHK(hand->callbacks->yajl_end_map(hand->ctx));
447
+ }
448
+ yajl_bs_pop(hand->stateStack);
449
+ goto around_again;
450
+ case yajl_tok_comma:
451
+ yajl_bs_set(hand->stateStack, yajl_state_map_need_key);
452
+ goto around_again;
453
+ case yajl_tok_eof:
454
+ return yajl_status_ok;
455
+ case yajl_tok_error:
456
+ yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
457
+ goto around_again;
458
+ default:
459
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error);
460
+ hand->parseError = "after key and value, inside map, "
461
+ "I expect ',' or '}'";
462
+ /* try to restore error offset */
463
+ if (*offset >= bufLen) *offset -= bufLen;
464
+ else *offset = 0;
465
+ goto around_again;
466
+ }
467
+ }
468
+ case yajl_state_array_got_val: {
469
+ tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
470
+ offset, &buf, &bufLen);
471
+ switch (tok) {
472
+ case yajl_tok_right_brace:
473
+ if (hand->callbacks && hand->callbacks->yajl_end_array) {
474
+ _CC_CHK(hand->callbacks->yajl_end_array(hand->ctx));
475
+ }
476
+ yajl_bs_pop(hand->stateStack);
477
+ goto around_again;
478
+ case yajl_tok_comma:
479
+ yajl_bs_set(hand->stateStack, yajl_state_array_need_val);
480
+ goto around_again;
481
+ case yajl_tok_eof:
482
+ return yajl_status_ok;
483
+ case yajl_tok_error:
484
+ yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
485
+ goto around_again;
486
+ default:
487
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error);
488
+ hand->parseError =
489
+ "after array element, I expect ',' or ']'";
490
+ goto around_again;
491
+ }
492
+ }
493
+ }
494
+
495
+ abort();
496
+ return yajl_status_error;
497
+ }
498
+