ffi-yajl 0.0.1-universal-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +330 -0
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+
3
+ require 'ffi_yajl/encoder'
4
+ require 'ffi_yajl/parser'
5
+
6
+ unless RUBY_VERSION.to_f >= 1.9
7
+ # segfaults on ruby 1.8 and this is an exceedingly low priority to fix, use ffi instead
8
+ raise NotImplementedError, "The C-extension is disabled on Ruby 1.8"
9
+ end
10
+
11
+ module FFI_Yajl
12
+ class Parser
13
+ require 'ffi_yajl/ext/parser'
14
+ include FFI_Yajl::Ext::Parser
15
+ end
16
+
17
+ class Encoder
18
+ require 'ffi_yajl/ext/encoder'
19
+ include FFI_Yajl::Ext::Encoder
20
+ end
21
+ end
22
+
File without changes
@@ -0,0 +1,129 @@
1
+ require 'rubygems'
2
+
3
+ require 'ffi'
4
+
5
+ module FFI_Yajl
6
+ extend ::FFI::Library
7
+
8
+ libname = ::FFI.map_library_name("yajl")
9
+ libpath = File.expand_path(File.join(File.dirname(__FILE__), "..", libname))
10
+
11
+ if File.file?(libpath)
12
+ # use our vendored version of libyajl2 if we find it installed
13
+ ffi_lib libpath
14
+ else
15
+ ffi_lib 'yajl'
16
+ end
17
+
18
+ class YajlCallbacks < ::FFI::Struct
19
+ layout :yajl_null, :pointer,
20
+ :yajl_boolean, :pointer,
21
+ :yajl_integer, :pointer,
22
+ :yajl_double, :pointer,
23
+ :yajl_number, :pointer,
24
+ :yajl_string, :pointer,
25
+ :yajl_start_map, :pointer,
26
+ :yajl_map_key, :pointer,
27
+ :yajl_end_map, :pointer,
28
+ :yajl_start_array, :pointer,
29
+ :yajl_end_array, :pointer
30
+ end
31
+
32
+ enum :yajl_status, [
33
+ :yajl_status_ok,
34
+ :yajl_status_client_canceled,
35
+ :yajl_status_insufficient_data,
36
+ :yajl_status_error,
37
+ ]
38
+
39
+ # FFI::Enums are slow, should remove the rest
40
+ # enum :yajl_gen_status, [
41
+ # :yajl_gen_status_ok,
42
+ # :yajl_gen_keys_must_be_strings,
43
+ # :yajl_max_depth_exceeded,
44
+ # :yajl_gen_in_error_state,
45
+ # :yajl_gen_generation_complete,
46
+ # :yajl_gen_invalid_number,
47
+ # :yajl_gen_no_buf,
48
+ # ]
49
+
50
+ enum :yajl_option, [
51
+ :yajl_allow_comments, 0x01,
52
+ :yajl_dont_validate_strings, 0x02,
53
+ :yajl_allow_trailing_garbage, 0x04,
54
+ :yajl_allow_multiple_values, 0x08,
55
+ :yajl_allow_partial_values, 0x10,
56
+ ]
57
+
58
+ enum :yajl_gen_option, [
59
+ :yajl_gen_beautify, 0x01,
60
+ :yajl_gen_indent_string, 0x02,
61
+ :yajl_gen_print_callback, 0x04,
62
+ :yajl_gen_validate_utf8, 0x08,
63
+ ]
64
+
65
+ typedef :pointer, :yajl_handle
66
+ typedef :pointer, :yajl_gen
67
+
68
+ # yajl uses unsinged char *'s consistently
69
+ typedef :pointer, :ustring_pointer
70
+ typedef :string, :ustring
71
+
72
+ # const char *yajl_status_to_string (yajl_status code)
73
+ attach_function :yajl_status_to_string, [ :yajl_status ], :string
74
+ # yajl_handle yajl_alloc(const yajl_callbacks * callbacks, yajl_alloc_funcs * afs, void * ctx)
75
+ attach_function :yajl_alloc, [:pointer, :pointer, :pointer], :yajl_handle
76
+ # void yajl_free (yajl_handle handle)
77
+ attach_function :yajl_free, [:yajl_handle], :void
78
+ # yajl_status yajl_parse (yajl_handle hand, const unsigned char *jsonText, unsigned int jsonTextLength)
79
+ attach_function :yajl_parse, [:yajl_handle, :ustring, :uint], :yajl_status
80
+ # yajl_status yajl_parse_complete (yajl_handle hand)
81
+ attach_function :yajl_complete_parse, [:yajl_handle], :yajl_status
82
+ # unsigned char *yajl_get_error (yajl_handle hand, int verbose, const unsigned char *jsonText, unsigned int jsonTextLength)
83
+ attach_function :yajl_get_error, [:yajl_handle, :int, :ustring, :int], :ustring
84
+ # void yajl_free_error (yajl_handle hand, unsigned char *str)
85
+ attach_function :yajl_free_error, [:yajl_handle, :ustring], :void
86
+
87
+ #
88
+ attach_function :yajl_config, [:yajl_handle, :yajl_option, :int], :int
89
+
90
+ attach_function :yajl_gen_config, [:yajl_gen, :yajl_gen_option, :varargs], :int
91
+
92
+ # yajl_gen yajl_gen_alloc (const yajl_alloc_funcs *allocFuncs)
93
+ attach_function :yajl_gen_alloc, [:pointer], :yajl_gen
94
+ # yajl_gen yajl_gen_alloc2 (const yajl_print_t callback, const yajl_gen_config *config, const yajl_alloc_funcs *allocFuncs, void *ctx)
95
+ # attach_function :yajl_gen_alloc2, [:pointer, :pointer, :pointer, :pointer], :yajl_gen
96
+ # void yajl_gen_free (yajl_gen handle)
97
+ attach_function :yajl_gen_free, [:yajl_gen], :void
98
+
99
+ attach_function :yajl_gen_integer, [:yajl_gen, :long_long], :int
100
+ attach_function :yajl_gen_double, [:yajl_gen, :double], :int
101
+ attach_function :yajl_gen_number, [:yajl_gen, :ustring, :int], :int
102
+ attach_function :yajl_gen_string, [:yajl_gen, :ustring, :int], :int
103
+ attach_function :yajl_gen_null, [:yajl_gen], :int
104
+ attach_function :yajl_gen_bool, [:yajl_gen, :int], :int
105
+ attach_function :yajl_gen_map_open, [:yajl_gen], :int
106
+ attach_function :yajl_gen_map_close, [:yajl_gen], :int
107
+ attach_function :yajl_gen_array_open, [:yajl_gen], :int
108
+ attach_function :yajl_gen_array_close, [:yajl_gen], :int
109
+ # yajl_gen_status yajl_gen_get_buf (yajl_gen hand, const unsigned char **buf, unsigned int *len)
110
+ attach_function :yajl_gen_get_buf, [:yajl_gen, :pointer ,:pointer], :int
111
+ # void yajl_gen_clear (yajl_gen hand)
112
+ attach_function :yajl_gen_clear, [:yajl_gen], :void
113
+
114
+ end
115
+
116
+ require 'ffi_yajl/encoder'
117
+ require 'ffi_yajl/parser'
118
+
119
+ module FFI_Yajl
120
+ class Parser
121
+ require 'ffi_yajl/ffi/parser'
122
+ include FFI_Yajl::FFI::Parser
123
+ end
124
+
125
+ class Encoder
126
+ require 'ffi_yajl/ffi/encoder'
127
+ include FFI_Yajl::FFI::Encoder
128
+ end
129
+ end
@@ -0,0 +1,175 @@
1
+
2
+ require 'ffi_yajl/ffi'
3
+
4
+ module FFI_Yajl
5
+ module FFI
6
+ module Encoder
7
+ def do_yajl_encode(obj, yajl_gen_opts = {})
8
+
9
+ yajl_gen = FFI_Yajl.yajl_gen_alloc(nil);
10
+
11
+ # configure the yajl encoder
12
+ if yajl_gen_opts[:yajl_gen_beautify]
13
+ FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_beautify, :int, 1)
14
+ end
15
+ if yajl_gen_opts[:yajl_gen_validate_utf8]
16
+ FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_validate_utf8, :int, 1)
17
+ end
18
+ indent = yajl_gen_opts[:yajl_gen_indent_string] || " "
19
+ FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_indent_string, :string, indent)
20
+
21
+ # setup our own state
22
+ state = {
23
+ :json_opts => opts,
24
+ :processing_key => false,
25
+ }
26
+
27
+ # do the encoding
28
+ obj.ffi_yajl(yajl_gen, state)
29
+
30
+ # get back our encoded JSON
31
+ string_ptr = ::FFI::MemoryPointer.new(:string)
32
+ length_ptr = ::FFI::MemoryPointer.new(:int)
33
+ if ( status = FFI_Yajl.yajl_gen_get_buf(yajl_gen, string_ptr, length_ptr) ) != 0
34
+ FFI_Yajl::Encoder.raise_error_for_status(status)
35
+ end
36
+ length = length_ptr.read_int
37
+ string = string_ptr.get_pointer(0).read_string
38
+
39
+ FFI_Yajl.yajl_gen_free(yajl_gen)
40
+
41
+ return string
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+
48
+ class Hash
49
+ def ffi_yajl(yajl_gen, state)
50
+ if ( status = FFI_Yajl.yajl_gen_map_open(yajl_gen) ) != 0
51
+ FFI_Yajl::Encoder.raise_error_for_status(status)
52
+ end
53
+ self.each do |key, value|
54
+ # Perf Fix: mutate state hash rather than creating new copy
55
+ state[:processing_key] = true
56
+ key.ffi_yajl(yajl_gen, state)
57
+ state[:processing_key] = false
58
+ value.ffi_yajl(yajl_gen, state)
59
+ end
60
+ if ( status = FFI_Yajl.yajl_gen_map_close(yajl_gen) ) != 0
61
+ FFI_Yajl::Encoder.raise_error_for_status(status)
62
+ end
63
+ end
64
+ end
65
+
66
+ class Array
67
+ def ffi_yajl(yajl_gen, state)
68
+ if ( status = FFI_Yajl.yajl_gen_array_open(yajl_gen) ) != 0
69
+ FFI_Yajl::Encoder.raise_error_for_status(status)
70
+ end
71
+ self.each do |value|
72
+ value.ffi_yajl(yajl_gen, state)
73
+ end
74
+ if ( status = FFI_Yajl.yajl_gen_array_close(yajl_gen) ) != 0
75
+ FFI_Yajl::Encoder.raise_error_for_status(status)
76
+ end
77
+ end
78
+ end
79
+
80
+ class NilClass
81
+ def ffi_yajl(yajl_gen, state)
82
+ if ( status = FFI_Yajl.yajl_gen_null(yajl_gen) ) != 0
83
+ FFI_Yajl::Encoder.raise_error_for_status(status)
84
+ end
85
+ end
86
+ end
87
+
88
+ class TrueClass
89
+ def ffi_yajl(yajl_gen, state)
90
+ if ( status = FFI_Yajl.yajl_gen_bool(yajl_gen, 1) ) != 0
91
+ FFI_Yajl::Encoder.raise_error_for_status(status)
92
+ end
93
+ end
94
+ end
95
+
96
+ class FalseClass
97
+ def ffi_yajl(yajl_gen, state)
98
+ if ( status = FFI_Yajl.yajl_gen_bool(yajl_gen, 0) ) != 0
99
+ FFI_Yajl::Encoder.raise_error_for_status(status)
100
+ end
101
+ end
102
+ end
103
+
104
+ class Fixnum
105
+ def ffi_yajl(yajl_gen, state)
106
+ str = self.to_s
107
+ if str == "NaN" || str == "Infinity" || str == "-Infinity"
108
+ raise ::FFI_Yajl::EncodeError.new("'#{str}' is an invalid number")
109
+ end
110
+ if state[:processing_key]
111
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
112
+ FFI_Yajl::Encoder.raise_error_for_status(status)
113
+ end
114
+ else
115
+ if ( status = FFI_Yajl.yajl_gen_integer(yajl_gen, self) ) != 0
116
+ FFI_Yajl::Encoder.raise_error_for_status(status)
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ class Bignum
123
+ def ffi_yajl(yajl_gen, state)
124
+ str = self.to_s
125
+ if str == "NaN" || str == "Infinity" || str == "-Infinity"
126
+ raise ::FFI_Yajl::EncodeError.new("'#{str}' is an invalid number")
127
+ end
128
+ if state[:processing_key]
129
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
130
+ FFI_Yajl::Encoder.raise_error_for_status(status)
131
+ end
132
+ else
133
+ if ( status = FFI_Yajl.yajl_gen_number(yajl_gen, str, str.bytesize) ) != 0
134
+ FFI_Yajl::Encoder.raise_error_for_status(status)
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ class Float
141
+ def ffi_yajl(yajl_gen, state)
142
+ str = self.to_s
143
+ if str == "NaN" || str == "Infinity" || str == "-Infinity"
144
+ raise ::FFI_Yajl::EncodeError.new("'#{str}' is an invalid number")
145
+ end
146
+ if state[:processing_key]
147
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
148
+ FFI_Yajl::Encoder.raise_error_for_status(status)
149
+ end
150
+ else
151
+ if ( status = FFI_Yajl.yajl_gen_number(yajl_gen, str, str.bytesize) ) != 0
152
+ FFI_Yajl::Encoder.raise_error_for_status(status)
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ class String
159
+ def ffi_yajl(yajl_gen, state)
160
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, self, self.bytesize) ) != 0
161
+ FFI_Yajl::Encoder.raise_error_for_status(status)
162
+ end
163
+ end
164
+ end
165
+
166
+ # I feel dirty
167
+ class Object
168
+ def ffi_yajl(yajl_gen, state)
169
+ json = self.to_json(state[:json_opts])
170
+ if ( status = FFI_Yajl.yajl_gen_number(yajl_gen, json, json.bytesize) ) != 0
171
+ FFI_Yajl::Encoder.raise_error_for_status(status)
172
+ end
173
+ end
174
+ end
175
+
@@ -0,0 +1,145 @@
1
+
2
+ require 'ffi_yajl/ffi'
3
+
4
+ module FFI_Yajl
5
+ module FFI
6
+ module Parser
7
+ attr_accessor :stack, :key_stack, :key, :finished
8
+
9
+ #
10
+ # stack used to build up our complex object
11
+ #
12
+ def stack
13
+ @stack ||= Array.new
14
+ end
15
+
16
+ def set_value(val)
17
+ case stack.last
18
+ when Hash
19
+ raise FFI_Yajl::ParseError.new("internal error: missing key in parse") if key.nil?
20
+ stack.last[key] = val
21
+ when Array
22
+ stack.last.push(val)
23
+ else
24
+ raise FFI_Yajl::ParseError.new("internal error: object not a hash or array")
25
+ end
26
+ end
27
+
28
+ def stack_pop
29
+ if stack.length > 1
30
+ set_value( stack.pop )
31
+ else
32
+ @finished = stack.pop
33
+ end
34
+ end
35
+
36
+ #
37
+ # stack to keep track of keys as we create nested hashes
38
+ #
39
+ def key_stack
40
+ @key_stack ||= Array.new
41
+ end
42
+
43
+ def key_push
44
+ key_stack.push(key)
45
+ end
46
+
47
+ def key_pop
48
+ @key = key_stack.pop()
49
+ end
50
+
51
+
52
+ def setup_callbacks
53
+ @null_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
54
+ set_value(nil)
55
+ 1
56
+ end
57
+ @boolean_callback = ::FFI::Function.new(:int, [:pointer, :int]) do |ctx, boolval|
58
+ set_value(boolval == 1 ? true : false)
59
+ 1
60
+ end
61
+ @integer_callback = ::FFI::Function.new(:int, [:pointer, :long_long]) do |ctx, intval|
62
+ set_value(intval)
63
+ 1
64
+ end
65
+ @number_callback = ::FFI::Function.new(:int, [:pointer, :string, :size_t ]) do |ctx, stringval, stringlen|
66
+ s = stringval.slice(0,stringlen)
67
+ s.force_encoding('UTF-8') if defined? Encoding
68
+ # XXX: I can't think of a better way to do this right now. need to call to_f if and only if its a float.
69
+ v = ( s =~ /\./ ) ? s.to_f : s.to_i
70
+ set_value(v)
71
+ 1
72
+ end
73
+ @double_callback = ::FFI::Function.new(:int, [:pointer, :double]) do |ctx, doubleval|
74
+ set_value(doubleval)
75
+ 1
76
+ end
77
+ @string_callback = ::FFI::Function.new(:int, [:pointer, :string, :size_t]) do |ctx, stringval, stringlen|
78
+ s = stringval.slice(0,stringlen)
79
+ s.force_encoding('UTF-8') if defined? Encoding
80
+ set_value(s)
81
+ 1
82
+ end
83
+ @start_map_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
84
+ key_push # for key => { } case, save the key
85
+ stack.push(Hash.new)
86
+ 1
87
+ end
88
+ @map_key_callback = ::FFI::Function.new(:int, [:pointer, :string, :size_t]) do |ctx, key, keylen|
89
+ s = key.slice(0,keylen)
90
+ s.force_encoding('UTF-8') if defined? Encoding
91
+ self.key = s
92
+ 1
93
+ end
94
+ @end_map_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
95
+ key_pop
96
+ stack_pop
97
+ 1
98
+ end
99
+ @start_array_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
100
+ key_push # for key => [ ] case, save the key
101
+ stack.push(Array.new)
102
+ 1
103
+ end
104
+ @end_array_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
105
+ key_pop
106
+ stack_pop
107
+ 1
108
+ end
109
+ end
110
+
111
+
112
+ def do_yajl_parse(str, opts = {})
113
+ setup_callbacks
114
+ callback_ptr = ::FFI::MemoryPointer.new(::FFI_Yajl::YajlCallbacks)
115
+ callbacks = ::FFI_Yajl::YajlCallbacks.new(callback_ptr)
116
+ callbacks[:yajl_null] = @null_callback
117
+ callbacks[:yajl_boolean] = @boolean_callback
118
+ callbacks[:yajl_integer] = @integer_callback
119
+ callbacks[:yajl_double] = @double_callback
120
+ callbacks[:yajl_number] = @number_callback
121
+ callbacks[:yajl_string] = @string_callback
122
+ callbacks[:yajl_start_map] = @start_map_callback
123
+ callbacks[:yajl_map_key] = @map_key_callback
124
+ callbacks[:yajl_end_map] = @end_map_callback
125
+ callbacks[:yajl_start_array] = @start_array_callback
126
+ callbacks[:yajl_end_array] = @end_array_callback
127
+ yajl_handle = ::FFI_Yajl.yajl_alloc(callback_ptr, nil, nil)
128
+ if ( stat = ::FFI_Yajl.yajl_parse(yajl_handle, str, str.bytesize) != :yajl_status_ok )
129
+ # FIXME: dup the error and call yajl_free_error?
130
+ error = ::FFI_Yajl.yajl_get_error(yajl_handle, 1, str, str.bytesize)
131
+ raise ::FFI_Yajl::ParseError.new(error)
132
+ end
133
+ if ( stat = FFI_Yajl.yajl_complete_parse(yajl_handle) != :yajl_status_ok )
134
+ # FIXME: dup the error and call yajl_free_error?
135
+ error = ::FFI_Yajl.yajl_get_error(yajl_handle, 1, str, str.bytesize)
136
+ raise ::FFI_Yajl::ParseError.new(error)
137
+ end
138
+ finished
139
+ ensure
140
+ ::FFI_Yajl.yajl_free(yajl_handle) if yajl_handle
141
+ end
142
+ end
143
+ end
144
+ end
145
+