ffi-yajl 0.0.1-universal-java → 3.0.1

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 (211) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +21 -201
  3. data/README.md +105 -10
  4. data/bin/ffi-yajl-bench +11 -11
  5. data/ext/ffi_yajl/ext/dlopen/dlopen.c +40 -0
  6. data/ext/ffi_yajl/ext/dlopen/extconf.rb +16 -0
  7. data/ext/ffi_yajl/ext/dlopen/yajl.sym +18 -0
  8. data/ext/ffi_yajl/ext/encoder/encoder.c +270 -115
  9. data/ext/ffi_yajl/ext/encoder/extconf.rb +71 -14
  10. data/ext/ffi_yajl/ext/parser/extconf.rb +71 -14
  11. data/ext/ffi_yajl/ext/parser/parser.c +85 -44
  12. data/lib/ffi_yajl/benchmark/encode.rb +39 -92
  13. data/lib/ffi_yajl/benchmark/encode_json_and_marshal.rb +23 -23
  14. data/lib/ffi_yajl/benchmark/encode_json_and_yaml.rb +24 -30
  15. data/lib/ffi_yajl/benchmark/encode_profile.rb +15 -19
  16. data/lib/ffi_yajl/benchmark/http.rb +21 -25
  17. data/lib/ffi_yajl/benchmark/parse.rb +77 -117
  18. data/lib/ffi_yajl/benchmark/parse_json_and_marshal.rb +27 -27
  19. data/lib/ffi_yajl/benchmark/parse_json_and_yaml.rb +30 -30
  20. data/lib/ffi_yajl/benchmark/parse_profile.rb +14 -18
  21. data/lib/ffi_yajl/benchmark/parse_profile_ruby_prof.rb +14 -19
  22. data/lib/ffi_yajl/benchmark/parse_stream.rb +28 -28
  23. data/lib/ffi_yajl/benchmark.rb +26 -6
  24. data/lib/ffi_yajl/encoder.rb +47 -6
  25. data/lib/ffi_yajl/ext.rb +37 -10
  26. data/lib/ffi_yajl/ffi/encoder.rb +150 -63
  27. data/lib/ffi_yajl/ffi/parser.rb +82 -64
  28. data/lib/ffi_yajl/ffi.rb +70 -46
  29. data/lib/ffi_yajl/map_library_name.rb +109 -0
  30. data/lib/ffi_yajl/parser.rb +69 -1
  31. data/lib/ffi_yajl/platform.rb +29 -0
  32. data/lib/ffi_yajl/version.rb +23 -1
  33. data/lib/ffi_yajl.rb +44 -8
  34. metadata +25 -238
  35. data/Rakefile +0 -62
  36. data/ext/libyajl2/extconf.rb +0 -65
  37. data/ext/libyajl2/vendored/.git +0 -1
  38. data/ext/libyajl2/vendored/.gitignore +0 -3
  39. data/ext/libyajl2/vendored/BUILDING +0 -23
  40. data/ext/libyajl2/vendored/BUILDING.win32 +0 -27
  41. data/ext/libyajl2/vendored/CMakeLists.txt +0 -79
  42. data/ext/libyajl2/vendored/COPYING +0 -13
  43. data/ext/libyajl2/vendored/ChangeLog +0 -175
  44. data/ext/libyajl2/vendored/README +0 -74
  45. data/ext/libyajl2/vendored/TODO +0 -9
  46. data/ext/libyajl2/vendored/YAJLDoc.cmake +0 -26
  47. data/ext/libyajl2/vendored/configure +0 -79
  48. data/ext/libyajl2/vendored/example/CMakeLists.txt +0 -23
  49. data/ext/libyajl2/vendored/example/README.md +0 -7
  50. data/ext/libyajl2/vendored/example/parse_config.c +0 -69
  51. data/ext/libyajl2/vendored/example/sample.config +0 -101
  52. data/ext/libyajl2/vendored/perf/CMakeLists.txt +0 -23
  53. data/ext/libyajl2/vendored/perf/documents.c +0 -1418
  54. data/ext/libyajl2/vendored/perf/documents.h +0 -28
  55. data/ext/libyajl2/vendored/perf/perftest.c +0 -134
  56. data/ext/libyajl2/vendored/reformatter/CMakeLists.txt +0 -39
  57. data/ext/libyajl2/vendored/reformatter/json_reformat.c +0 -194
  58. data/ext/libyajl2/vendored/src/CMakeLists.txt +0 -86
  59. data/ext/libyajl2/vendored/src/YAJL.dxy +0 -1258
  60. data/ext/libyajl2/vendored/src/api/yajl_common.h +0 -75
  61. data/ext/libyajl2/vendored/src/api/yajl_gen.h +0 -157
  62. data/ext/libyajl2/vendored/src/api/yajl_parse.h +0 -226
  63. data/ext/libyajl2/vendored/src/api/yajl_tree.h +0 -185
  64. data/ext/libyajl2/vendored/src/api/yajl_version.h.cmake +0 -23
  65. data/ext/libyajl2/vendored/src/yajl +0 -33
  66. data/ext/libyajl2/vendored/src/yajl.c +0 -175
  67. data/ext/libyajl2/vendored/src/yajl.pc.cmake +0 -9
  68. data/ext/libyajl2/vendored/src/yajl_alloc.c +0 -52
  69. data/ext/libyajl2/vendored/src/yajl_alloc.h +0 -34
  70. data/ext/libyajl2/vendored/src/yajl_buf.c +0 -103
  71. data/ext/libyajl2/vendored/src/yajl_buf.h +0 -57
  72. data/ext/libyajl2/vendored/src/yajl_bytestack.h +0 -69
  73. data/ext/libyajl2/vendored/src/yajl_encode.c +0 -220
  74. data/ext/libyajl2/vendored/src/yajl_encode.h +0 -34
  75. data/ext/libyajl2/vendored/src/yajl_gen.c +0 -354
  76. data/ext/libyajl2/vendored/src/yajl_lex.c +0 -763
  77. data/ext/libyajl2/vendored/src/yajl_lex.h +0 -117
  78. data/ext/libyajl2/vendored/src/yajl_parser.c +0 -498
  79. data/ext/libyajl2/vendored/src/yajl_parser.h +0 -78
  80. data/ext/libyajl2/vendored/src/yajl_tree.c +0 -503
  81. data/ext/libyajl2/vendored/src/yajl_version.c +0 -7
  82. data/ext/libyajl2/vendored/test/CMakeLists.txt +0 -23
  83. data/ext/libyajl2/vendored/test/cases/ac_difficult_json_c_test_case_with_comments.json +0 -1
  84. data/ext/libyajl2/vendored/test/cases/ac_difficult_json_c_test_case_with_comments.json.gold +0 -36
  85. data/ext/libyajl2/vendored/test/cases/ac_simple_with_comments.json +0 -11
  86. data/ext/libyajl2/vendored/test/cases/ac_simple_with_comments.json.gold +0 -9
  87. data/ext/libyajl2/vendored/test/cases/ag_false_then_garbage.json +0 -1
  88. data/ext/libyajl2/vendored/test/cases/ag_false_then_garbage.json.gold +0 -2
  89. data/ext/libyajl2/vendored/test/cases/ag_null_then_garbage.json +0 -1
  90. data/ext/libyajl2/vendored/test/cases/ag_null_then_garbage.json.gold +0 -2
  91. data/ext/libyajl2/vendored/test/cases/ag_true_then_garbage.json +0 -1
  92. data/ext/libyajl2/vendored/test/cases/ag_true_then_garbage.json.gold +0 -2
  93. data/ext/libyajl2/vendored/test/cases/am_eof.json +0 -1
  94. data/ext/libyajl2/vendored/test/cases/am_eof.json.gold +0 -4
  95. data/ext/libyajl2/vendored/test/cases/am_integers.json +0 -1
  96. data/ext/libyajl2/vendored/test/cases/am_integers.json.gold +0 -3
  97. data/ext/libyajl2/vendored/test/cases/am_multiple.json +0 -3
  98. data/ext/libyajl2/vendored/test/cases/am_multiple.json.gold +0 -5
  99. data/ext/libyajl2/vendored/test/cases/am_stuff.json +0 -7
  100. data/ext/libyajl2/vendored/test/cases/am_stuff.json.gold +0 -14
  101. data/ext/libyajl2/vendored/test/cases/ap_array_open.json +0 -1
  102. data/ext/libyajl2/vendored/test/cases/ap_array_open.json.gold +0 -2
  103. data/ext/libyajl2/vendored/test/cases/ap_eof_str.json +0 -1
  104. data/ext/libyajl2/vendored/test/cases/ap_eof_str.json.gold +0 -1
  105. data/ext/libyajl2/vendored/test/cases/ap_map_open.json +0 -1
  106. data/ext/libyajl2/vendored/test/cases/ap_map_open.json.gold +0 -2
  107. data/ext/libyajl2/vendored/test/cases/ap_partial_ok.json +0 -1
  108. data/ext/libyajl2/vendored/test/cases/ap_partial_ok.json.gold +0 -4
  109. data/ext/libyajl2/vendored/test/cases/array.json +0 -6
  110. data/ext/libyajl2/vendored/test/cases/array.json.gold +0 -22
  111. data/ext/libyajl2/vendored/test/cases/array_close.json +0 -1
  112. data/ext/libyajl2/vendored/test/cases/array_close.json.gold +0 -2
  113. data/ext/libyajl2/vendored/test/cases/bignums.json +0 -1
  114. data/ext/libyajl2/vendored/test/cases/bignums.json.gold +0 -5
  115. data/ext/libyajl2/vendored/test/cases/bogus_char.json +0 -4
  116. data/ext/libyajl2/vendored/test/cases/bogus_char.json.gold +0 -10
  117. data/ext/libyajl2/vendored/test/cases/codepoints_from_unicode_org.json +0 -1
  118. data/ext/libyajl2/vendored/test/cases/codepoints_from_unicode_org.json.gold +0 -2
  119. data/ext/libyajl2/vendored/test/cases/deep_arrays.json +0 -1
  120. data/ext/libyajl2/vendored/test/cases/deep_arrays.json.gold +0 -2049
  121. data/ext/libyajl2/vendored/test/cases/difficult_json_c_test_case.json +0 -1
  122. data/ext/libyajl2/vendored/test/cases/difficult_json_c_test_case.json.gold +0 -36
  123. data/ext/libyajl2/vendored/test/cases/doubles.json +0 -1
  124. data/ext/libyajl2/vendored/test/cases/doubles.json.gold +0 -7
  125. data/ext/libyajl2/vendored/test/cases/doubles_in_array.json +0 -1
  126. data/ext/libyajl2/vendored/test/cases/doubles_in_array.json.gold +0 -8
  127. data/ext/libyajl2/vendored/test/cases/empty_array.json +0 -1
  128. data/ext/libyajl2/vendored/test/cases/empty_array.json.gold +0 -3
  129. data/ext/libyajl2/vendored/test/cases/empty_string.json +0 -1
  130. data/ext/libyajl2/vendored/test/cases/empty_string.json.gold +0 -2
  131. data/ext/libyajl2/vendored/test/cases/escaped_bulgarian.json +0 -4
  132. data/ext/libyajl2/vendored/test/cases/escaped_bulgarian.json.gold +0 -7
  133. data/ext/libyajl2/vendored/test/cases/escaped_foobar.json +0 -1
  134. data/ext/libyajl2/vendored/test/cases/escaped_foobar.json.gold +0 -2
  135. data/ext/libyajl2/vendored/test/cases/false.json +0 -1
  136. data/ext/libyajl2/vendored/test/cases/false.json.gold +0 -2
  137. data/ext/libyajl2/vendored/test/cases/fg_false_then_garbage.json +0 -1
  138. data/ext/libyajl2/vendored/test/cases/fg_false_then_garbage.json.gold +0 -3
  139. data/ext/libyajl2/vendored/test/cases/fg_issue_7.json +0 -1
  140. data/ext/libyajl2/vendored/test/cases/fg_issue_7.json.gold +0 -3
  141. data/ext/libyajl2/vendored/test/cases/fg_null_then_garbage.json +0 -1
  142. data/ext/libyajl2/vendored/test/cases/fg_null_then_garbage.json.gold +0 -3
  143. data/ext/libyajl2/vendored/test/cases/fg_true_then_garbage.json +0 -1
  144. data/ext/libyajl2/vendored/test/cases/fg_true_then_garbage.json.gold +0 -3
  145. data/ext/libyajl2/vendored/test/cases/four_byte_utf8.json +0 -2
  146. data/ext/libyajl2/vendored/test/cases/four_byte_utf8.json.gold +0 -5
  147. data/ext/libyajl2/vendored/test/cases/high_overflow.json +0 -1
  148. data/ext/libyajl2/vendored/test/cases/high_overflow.json.gold +0 -2
  149. data/ext/libyajl2/vendored/test/cases/integers.json +0 -3
  150. data/ext/libyajl2/vendored/test/cases/integers.json.gold +0 -14
  151. data/ext/libyajl2/vendored/test/cases/invalid_utf8.json +0 -1
  152. data/ext/libyajl2/vendored/test/cases/invalid_utf8.json.gold +0 -3
  153. data/ext/libyajl2/vendored/test/cases/isolated_surrogate_marker.json +0 -1
  154. data/ext/libyajl2/vendored/test/cases/isolated_surrogate_marker.json.gold +0 -2
  155. data/ext/libyajl2/vendored/test/cases/leading_zero_in_number.json +0 -1
  156. data/ext/libyajl2/vendored/test/cases/leading_zero_in_number.json.gold +0 -5
  157. data/ext/libyajl2/vendored/test/cases/lonely_minus_sign.json +0 -7
  158. data/ext/libyajl2/vendored/test/cases/lonely_minus_sign.json.gold +0 -9
  159. data/ext/libyajl2/vendored/test/cases/lonely_number.json +0 -1
  160. data/ext/libyajl2/vendored/test/cases/lonely_number.json.gold +0 -2
  161. data/ext/libyajl2/vendored/test/cases/low_overflow.json +0 -1
  162. data/ext/libyajl2/vendored/test/cases/low_overflow.json.gold +0 -2
  163. data/ext/libyajl2/vendored/test/cases/map_close.json +0 -1
  164. data/ext/libyajl2/vendored/test/cases/map_close.json.gold +0 -2
  165. data/ext/libyajl2/vendored/test/cases/missing_integer_after_decimal_point.json +0 -1
  166. data/ext/libyajl2/vendored/test/cases/missing_integer_after_decimal_point.json.gold +0 -2
  167. data/ext/libyajl2/vendored/test/cases/missing_integer_after_exponent.json +0 -1
  168. data/ext/libyajl2/vendored/test/cases/missing_integer_after_exponent.json.gold +0 -2
  169. data/ext/libyajl2/vendored/test/cases/multiple.json +0 -3
  170. data/ext/libyajl2/vendored/test/cases/multiple.json.gold +0 -4
  171. data/ext/libyajl2/vendored/test/cases/non_utf8_char_in_string.json +0 -1
  172. data/ext/libyajl2/vendored/test/cases/non_utf8_char_in_string.json.gold +0 -8
  173. data/ext/libyajl2/vendored/test/cases/np_partial_bad.json +0 -1
  174. data/ext/libyajl2/vendored/test/cases/np_partial_bad.json.gold +0 -5
  175. data/ext/libyajl2/vendored/test/cases/null.json +0 -1
  176. data/ext/libyajl2/vendored/test/cases/null.json.gold +0 -2
  177. data/ext/libyajl2/vendored/test/cases/nulls_and_bools.json +0 -5
  178. data/ext/libyajl2/vendored/test/cases/nulls_and_bools.json.gold +0 -9
  179. data/ext/libyajl2/vendored/test/cases/simple.json +0 -5
  180. data/ext/libyajl2/vendored/test/cases/simple.json.gold +0 -9
  181. data/ext/libyajl2/vendored/test/cases/simple_with_comments.json +0 -11
  182. data/ext/libyajl2/vendored/test/cases/simple_with_comments.json.gold +0 -5
  183. data/ext/libyajl2/vendored/test/cases/string_invalid_escape.json +0 -1
  184. data/ext/libyajl2/vendored/test/cases/string_invalid_escape.json.gold +0 -3
  185. data/ext/libyajl2/vendored/test/cases/string_invalid_hex_char.json +0 -1
  186. data/ext/libyajl2/vendored/test/cases/string_invalid_hex_char.json.gold +0 -2
  187. data/ext/libyajl2/vendored/test/cases/string_with_escapes.json +0 -3
  188. data/ext/libyajl2/vendored/test/cases/string_with_escapes.json.gold +0 -7
  189. data/ext/libyajl2/vendored/test/cases/string_with_invalid_newline.json +0 -2
  190. data/ext/libyajl2/vendored/test/cases/string_with_invalid_newline.json.gold +0 -2
  191. data/ext/libyajl2/vendored/test/cases/three_byte_utf8.json +0 -1
  192. data/ext/libyajl2/vendored/test/cases/three_byte_utf8.json.gold +0 -7
  193. data/ext/libyajl2/vendored/test/cases/true.json +0 -1
  194. data/ext/libyajl2/vendored/test/cases/true.json.gold +0 -2
  195. data/ext/libyajl2/vendored/test/cases/unescaped_bulgarian.json +0 -1
  196. data/ext/libyajl2/vendored/test/cases/unescaped_bulgarian.json.gold +0 -4
  197. data/ext/libyajl2/vendored/test/cases/zerobyte.json +0 -1
  198. data/ext/libyajl2/vendored/test/cases/zerobyte.json.gold +0 -0
  199. data/ext/libyajl2/vendored/test/run_tests.sh +0 -94
  200. data/ext/libyajl2/vendored/test/yajl_test.c +0 -281
  201. data/ext/libyajl2/vendored/verify/CMakeLists.txt +0 -39
  202. data/ext/libyajl2/vendored/verify/json_verify.c +0 -116
  203. data/lib/ffi_yajl/json_gem.rb +0 -121
  204. data/lib/libyajl.so +0 -0
  205. data/lib/libyajl.so.2 +0 -0
  206. data/lib/libyajl.so.2.0.5 +0 -0
  207. data/lib/libyajl_s.a +0 -0
  208. data/spec/ffi_yajl/encoder_spec.rb +0 -39
  209. data/spec/ffi_yajl/json_gem_spec.rb +0 -355
  210. data/spec/ffi_yajl/parser_spec.rb +0 -78
  211. data/spec/spec_helper.rb +0 -14
@@ -1,29 +1,86 @@
1
- require 'mkmf'
1
+ # rubocop:disable Style/GlobalVars
2
+ require "mkmf"
3
+ require "rubygems"
4
+ require "libyajl2"
2
5
 
3
- # the customer is always right, ruby is always compiled to be stupid
4
- $CFLAGS = ENV['CFLAGS'] if ENV['CFLAGS']
5
- $LDFLAGS = ENV['LDFLAGS'] if ENV['LDFLAGS']
6
- RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
6
+ RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"] if ENV["CC"]
7
7
 
8
- # search our gem root first to pick up libyajl2 that we vendored
9
- gem_root = File.expand_path(File.join(File.dirname(__FILE__), "../../../.."))
10
- $CFLAGS = "-I#{gem_root}/include -L#{gem_root}/lib #{$CFLAGS}"
11
- $LDFLAGS = "-L#{gem_root}/lib #{$CFLAGS}"
8
+ # pick up the vendored libyajl2 out of the libyajl2 gem
9
+ $CFLAGS = "-I#{Libyajl2.include_path} #{$CFLAGS}"
10
+ $LDFLAGS = "-L#{Libyajl2.opt_path} #{$LDFLAGS}"
11
+
12
+ # remove "-Wl,--no-undefined" flag if existent to allow for loading with dlopen
13
+ $LDFLAGS.slice!("-Wl,--no-undefined")
12
14
 
13
- puts gem_root
14
15
  puts $CFLAGS
15
16
  puts $LDFLAGS
16
17
 
17
18
  # except if you're doing an unoptimized gcc install we're going to help you out a bit
18
- if RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc|clang/
19
+ if RbConfig::MAKEFILE_CONFIG["CC"] =~ /gcc|clang/
19
20
  $CFLAGS << " -O3" unless $CFLAGS[/-O\d/]
20
21
  # how many people realize that -Wall is a compiler-specific flag???
21
22
  # apparently not many based on reading lots of shitty extconf.rb's out there
22
23
  $CFLAGS << " -Wall"
23
24
  end
24
25
 
25
- $LDFLAGS << " -lyajl"
26
+ def windows?
27
+ !!(RUBY_PLATFORM =~ /mswin|mingw|cygwin|windows/)
28
+ end
29
+
30
+ def macos?
31
+ !!(RUBY_PLATFORM =~ /darwin/)
32
+ end
33
+
34
+ def clang?
35
+ cc_version = `#{RbConfig.expand("$(CC) --version")}`
36
+ cc_version.match?(/clang/i)
37
+ end
38
+
39
+ # XCode 14 warns if `-Wl,-undefined dynamic_lookup` is specified, and as
40
+ # a result Ruby interpreters compiled under XCode 14 no longer specify
41
+ # this flag by default in DLDFLAGS. Let's specify the list of dynamic symbols
42
+ # here to avoid compilation failures.
43
+ if clang? && macos?
44
+ symfile = File.join(__dir__, "../dlopen/yajl.sym")
45
+ dynamic_symbols = File.readlines(symfile)
46
+ dynamic_symbols.each do |sym|
47
+ $DLDFLAGS << " -Wl,-U,#{sym.strip}"
48
+ end
49
+ end
50
+
51
+ if windows?
52
+ # include our libyajldll.a definitions on windows in the libyajl2 gem
53
+ $libs = "#{$libs} -lyajldll"
54
+ end
55
+
56
+ # NOTE: find_library has the side effect of adding -lyajl to the flags which we are deliberately
57
+ # avoiding doing with the libyajl2-gem (allowing it to be lazily loaded with dlopen)
58
+ if !windows? && !find_header("yajl/yajl_tree.h")
59
+ puts "libyajl2 headers not found in libyajl2-gem, searching for system libraries..."
60
+
61
+ HEADER_DIRS = [
62
+ "/opt/local/include", # MacPorts
63
+ "/usr/local/include", # /usr/local
64
+ RbConfig::CONFIG["includedir"], # Ruby
65
+ "/usr/include", # (default)
66
+ ].freeze
67
+
68
+ LIB_DIRS = [
69
+ "/opt/local/lib", # MacPorts
70
+ "/usr/local/lib", # /usr/local + Homebrew
71
+ RbConfig::CONFIG["libdir"], # Ruby
72
+ "/usr/lib", # (default)
73
+ ].freeze
74
+
75
+ # add --with-yajl-dir, --with-yajl-include, --with-yajl-lib
76
+ dir_config("yajl", HEADER_DIRS, LIB_DIRS)
77
+
78
+ # here we use find_library in order to deliberately link with -lyajl as a useful side-effect
79
+ unless find_header("yajl/yajl_tree.h") && find_library("yajl", "yajl_complete_parse")
80
+ abort "libyajl2 is missing. please install libyajl2"
81
+ end
82
+ end
26
83
 
27
- dir_config 'parser'
84
+ dir_config "parser"
28
85
 
29
- create_makefile 'ffi_yajl/ext/parser'
86
+ create_makefile "ffi_yajl/ext/parser"
@@ -9,42 +9,54 @@ static rb_encoding *utf8Encoding;
9
9
  static VALUE mFFI_Yajl, mExt, mParser, cParseError;
10
10
 
11
11
  typedef struct {
12
- VALUE finished;
13
- VALUE stack;
14
- VALUE key_stack;
15
- VALUE key;
12
+ VALUE self;
13
+ int symbolizeKeys;
14
+ int uniqueKeyChecking;
16
15
  } CTX;
17
16
 
18
17
  void set_value(CTX *ctx, VALUE val) {
19
- long len = RARRAY_LEN(ctx->stack);
20
- VALUE last = rb_ary_entry(ctx->stack, len-1);
18
+ VALUE stack = rb_ivar_get(ctx->self, rb_intern("stack"));
19
+ VALUE key = rb_ivar_get(ctx->self, rb_intern("key"));
20
+ long len = RARRAY_LEN(stack);
21
+ VALUE last = rb_ary_entry(stack, len-1);
21
22
  switch (TYPE(last)) {
22
23
  case T_ARRAY:
23
24
  rb_ary_push(last, val);
24
25
  break;
25
26
  case T_HASH:
26
- rb_hash_aset(last, ctx->key, val);
27
+ if ( ctx->uniqueKeyChecking ) {
28
+ ID sym_has_key = rb_intern("has_key?");
29
+ if ( rb_funcall(last, sym_has_key, 1, key) == Qtrue ) {
30
+ rb_raise(cParseError, "repeated key: %s", RSTRING_PTR(key));
31
+ }
32
+ }
33
+ rb_hash_aset(last, key, val);
27
34
  break;
28
35
  default:
36
+ rb_ary_push(stack, val);
29
37
  break;
30
38
  }
31
39
  }
32
40
 
33
41
  void set_key(CTX *ctx, VALUE key) {
34
- ctx->key = key;
42
+ rb_ivar_set(ctx->self, rb_intern("key"), key);
35
43
  }
36
44
 
37
45
  void start_object(CTX *ctx, VALUE obj) {
38
- rb_ary_push(ctx->key_stack, ctx->key);
39
- rb_ary_push(ctx->stack, obj);
46
+ VALUE key_stack = rb_ivar_get(ctx->self, rb_intern("key_stack"));
47
+ VALUE key = rb_ivar_get(ctx->self, rb_intern("key"));
48
+ VALUE stack = rb_ivar_get(ctx->self, rb_intern("stack"));
49
+
50
+ rb_ary_push(key_stack, key);
51
+ rb_ary_push(stack, obj);
40
52
  }
41
53
 
42
54
  void end_object(CTX *ctx) {
43
- ctx->key = rb_ary_pop(ctx->key_stack);
44
- if ( RARRAY_LEN(ctx->stack) > 1 ) {
45
- set_value(ctx, rb_ary_pop(ctx->stack));
46
- } else {
47
- ctx->finished = rb_ary_pop(ctx->stack);
55
+ VALUE key_stack = rb_ivar_get(ctx->self, rb_intern("key_stack"));
56
+ VALUE stack = rb_ivar_get(ctx->self, rb_intern("stack"));
57
+ rb_ivar_set(ctx->self, rb_intern("key"), rb_ary_pop(key_stack));
58
+ if ( RARRAY_LEN(stack) > 1 ) {
59
+ set_value(ctx, rb_ary_pop(stack));
48
60
  }
49
61
  }
50
62
 
@@ -69,7 +81,7 @@ int double_callback(void *ctx, double doubleVal) {
69
81
  }
70
82
 
71
83
  int number_callback(void *ctx, const char *numberVal, size_t numberLen) {
72
- char buf[numberLen+1];
84
+ char *buf = (char *)malloc(numberLen+1);
73
85
  buf[numberLen] = 0;
74
86
  memcpy(buf, numberVal, numberLen);
75
87
  if (memchr(buf, '.', numberLen) ||
@@ -79,21 +91,14 @@ int number_callback(void *ctx, const char *numberVal, size_t numberLen) {
79
91
  } else {
80
92
  set_value(ctx, rb_cstr2inum(buf, 10));
81
93
  }
94
+ free(buf);
82
95
  return 1;
83
96
  }
84
97
 
85
98
  int string_callback(void *ctx, const unsigned char *stringVal, size_t stringLen) {
86
- char buf[stringLen+1];
87
- VALUE str;
88
- #ifdef HAVE_RUBY_ENCODING_H
89
- rb_encoding *default_internal_enc;
90
- #endif
91
-
92
- buf[stringLen] = 0;
93
- memcpy(buf, stringVal, stringLen);
94
- str = rb_str_new2(buf);
99
+ VALUE str = rb_str_new((const char *)stringVal, stringLen);
95
100
  #ifdef HAVE_RUBY_ENCODING_H
96
- default_internal_enc = rb_default_internal_encoding();
101
+ rb_encoding *default_internal_enc = rb_default_internal_encoding();
97
102
  rb_enc_associate(str, utf8Encoding);
98
103
  if (default_internal_enc) {
99
104
  str = rb_str_export_to_enc(str, default_internal_enc);
@@ -109,23 +114,30 @@ int start_map_callback(void *ctx) {
109
114
  }
110
115
 
111
116
  int map_key_callback(void *ctx, const unsigned char *stringVal, size_t stringLen) {
112
- char buf[stringLen+1];
113
- VALUE str;
117
+ VALUE key;
114
118
  #ifdef HAVE_RUBY_ENCODING_H
115
119
  rb_encoding *default_internal_enc;
116
120
  #endif
117
121
 
118
- buf[stringLen] = 0;
119
- memcpy(buf, stringVal, stringLen);
120
- str = rb_str_new2(buf);
122
+ if ( ((CTX *)ctx)->symbolizeKeys ) {
121
123
  #ifdef HAVE_RUBY_ENCODING_H
122
- default_internal_enc = rb_default_internal_encoding();
123
- rb_enc_associate(str, utf8Encoding);
124
- if (default_internal_enc) {
125
- str = rb_str_export_to_enc(str, default_internal_enc);
126
- }
124
+ ID id = rb_intern3((const char *)stringVal, stringLen, utf8Encoding);
125
+ key = ID2SYM(id);
126
+ #else
127
+ VALUE str = rb_str_new((const char *)stringVal, stringLen);
128
+ key = rb_str_intern(str);
129
+ #endif
130
+ } else {
131
+ key = rb_str_new((const char *)stringVal, stringLen);
132
+ #ifdef HAVE_RUBY_ENCODING_H
133
+ default_internal_enc = rb_default_internal_encoding();
134
+ rb_enc_associate(key, utf8Encoding);
135
+ if (default_internal_enc) {
136
+ key = rb_str_export_to_enc(key, default_internal_enc);
137
+ }
127
138
  #endif
128
- set_key(ctx,str);
139
+ }
140
+ set_key(ctx, key);
129
141
  return 1;
130
142
  }
131
143
 
@@ -158,16 +170,46 @@ static yajl_callbacks callbacks = {
158
170
  end_array_callback,
159
171
  };
160
172
 
161
- static VALUE mParser_do_yajl_parse(VALUE self, VALUE str, VALUE opts) {
173
+ int get_opts_key(VALUE self, const char *key) {
174
+ VALUE opts = rb_iv_get(self, "@opts");
175
+ if (TYPE(opts) != T_HASH) {
176
+ rb_raise(rb_eTypeError, "opts is not a valid hash");
177
+ }
178
+ return rb_hash_aref(opts, ID2SYM(rb_intern(key))) == Qtrue;
179
+ }
180
+
181
+ static VALUE mParser_do_yajl_parse(VALUE self, VALUE str, VALUE yajl_opts) {
162
182
  yajl_handle hand;
163
183
  yajl_status stat;
164
184
  unsigned char *err;
165
- CTX ctx;
185
+ volatile CTX ctx;
186
+
187
+ rb_ivar_set(self, rb_intern("key"), Qnil);
188
+ rb_ivar_set(self, rb_intern("stack"), rb_ary_new());
189
+ rb_ivar_set(self, rb_intern("key_stack"), rb_ary_new());
190
+
191
+ ctx.self = self;
192
+ ctx.symbolizeKeys = get_opts_key(self, "symbolize_keys");
193
+ ctx.uniqueKeyChecking = get_opts_key(self, "unique_key_checking");
166
194
 
167
- ctx.stack = rb_ary_new();
168
- ctx.key_stack = rb_ary_new();
195
+ hand = yajl_alloc(&callbacks, NULL, (void *)&ctx);
196
+
197
+ if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_comments"))) == Qtrue) {
198
+ yajl_config(hand, yajl_allow_comments, 1);
199
+ }
200
+ if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_dont_validate_strings"))) == Qtrue) {
201
+ yajl_config(hand, yajl_dont_validate_strings, 1);
202
+ }
203
+ if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_trailing_garbage"))) == Qtrue) {
204
+ yajl_config(hand, yajl_allow_trailing_garbage, 1);
205
+ }
206
+ if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_multiple_values"))) == Qtrue) {
207
+ yajl_config(hand, yajl_allow_multiple_values, 1);
208
+ }
209
+ if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_partial_values"))) == Qtrue) {
210
+ yajl_config(hand, yajl_allow_partial_values, 1);
211
+ }
169
212
 
170
- hand = yajl_alloc(&callbacks, NULL, &ctx);
171
213
  if ((stat = yajl_parse(hand, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str))) != yajl_status_ok) {
172
214
  err = yajl_get_error(hand, 1, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str));
173
215
  goto raise;
@@ -177,7 +219,7 @@ static VALUE mParser_do_yajl_parse(VALUE self, VALUE str, VALUE opts) {
177
219
  goto raise;
178
220
  }
179
221
  yajl_free(hand);
180
- return ctx.finished;
222
+ return rb_ary_pop(rb_ivar_get(self, rb_intern("stack")));
181
223
 
182
224
  raise:
183
225
  if (hand) {
@@ -196,4 +238,3 @@ void Init_parser() {
196
238
  utf8Encoding = rb_utf8_encoding();
197
239
  #endif
198
240
  }
199
-
@@ -1,135 +1,82 @@
1
1
  # Portions Originally Copyright (c) 2008-2011 Brian Lopez - http://github.com/brianmario
2
2
  # See MIT-LICENSE
3
3
 
4
- require 'rubygems'
5
- require 'benchmark'
6
- require 'stringio'
4
+ require "rubygems" unless defined?(Gem)
5
+ require "benchmark" unless defined?(Benchmark)
6
+ require "stringio" unless defined?(StringIO)
7
7
  if !defined?(RUBY_ENGINE) || RUBY_ENGINE !~ /jruby/
8
- if ENV['FORCE_FFI_YAJL'] != 'ext'
9
- begin
10
- require 'yajl'
11
- rescue Exception
12
- puts "INFO: yajl-ruby not installed"
13
- end
14
- else
15
- puts "INFO: skipping yajl-ruby because we're using the C extension"
8
+ begin
9
+ require "yajl"
10
+ rescue LoadError
11
+ puts "INFO: yajl-ruby not installed"
16
12
  end
17
13
  else
18
14
  puts "INFO: skipping yajl-ruby on jruby"
19
15
  end
20
- require 'ffi_yajl'
16
+ require_relative "../../ffi_yajl"
21
17
  begin
22
- require 'json'
23
- rescue Exception
18
+ require "json" unless defined?(JSON)
19
+ rescue LoadError
24
20
  puts "INFO: json gem not installed"
25
21
  end
26
22
  begin
27
- require 'psych'
28
- rescue Exception
29
- puts "INFO: psych gem not installed"
30
- end
31
- begin
32
- require 'active_support'
33
- rescue Exception
34
- puts "INFO: active_support gem not installed"
35
- end
36
- begin
37
- require 'oj'
38
- rescue Exception
23
+ require "oj"
24
+ rescue LoadError
39
25
  puts "INFO: oj gem not installed"
40
26
  end
41
27
 
42
28
  module FFI_Yajl
43
29
  class Benchmark
44
30
  class Encode
45
-
46
31
  def run
47
- #filename = ARGV[0] || 'benchmark/subjects/ohai.json'
32
+ # filename = ARGV[0] || 'benchmark/subjects/ohai.json'
48
33
  filename = File.expand_path(File.join(File.dirname(__FILE__), "subjects", "ohai.json"))
49
- hash = File.open(filename, 'rb') { |f| FFI_Yajl::Parser.parse(f.read) }
34
+ hash = File.open(filename, "rb") { |f| FFI_Yajl::Parser.parse(f.read) }
50
35
 
51
36
  times = ARGV[1] ? ARGV[1].to_i : 1000
52
37
  puts "Starting benchmark encoding #{filename} #{times} times\n\n"
53
- ::Benchmark.bmbm { |x|
54
-
55
- x.report("FFI_Yajl::Encoder.encode (to a String)") {
56
- times.times {
57
- output = FFI_Yajl::Encoder.encode(hash)
58
- }
59
- }
38
+ ::Benchmark.bmbm do |x|
39
+ x.report("FFI_Yajl::Encoder.encode (to a String)") do
40
+ times.times { FFI_Yajl::Encoder.encode(hash) }
41
+ end
60
42
 
61
43
  ffi_string_encoder = FFI_Yajl::Encoder.new
62
- x.report("FFI_Yajl::Encoder#encode (to a String)") {
63
- times.times {
64
- output = ffi_string_encoder.encode(hash)
65
- }
66
- }
44
+ x.report("FFI_Yajl::Encoder#encode (to a String)") do
45
+ times.times { ffi_string_encoder.encode(hash) }
46
+ end
67
47
 
68
48
  if defined?(Oj)
69
- x.report("Oj.dump (to a String)") {
70
- times.times {
71
- output = Oj.dump(hash)
72
- }
73
- }
49
+ x.report("Oj.dump (to a String)") do
50
+ times.times { Oj.dump(hash) }
51
+ end
74
52
  end
75
53
 
76
54
  if defined?(Yajl::Encoder)
77
- x.report("Yajl::Encoder.encode (to a String)") {
78
- times.times {
79
- output = Yajl::Encoder.encode(hash)
80
- }
81
- }
55
+ x.report("Yajl::Encoder.encode (to a String)") do
56
+ times.times { Yajl::Encoder.encode(hash) }
57
+ end
82
58
 
83
59
  io_encoder = Yajl::Encoder.new
84
- x.report("Yajl::Encoder#encode (to an IO)") {
85
- times.times {
86
- io_encoder.encode(hash, StringIO.new)
87
- }
88
- }
60
+ x.report("Yajl::Encoder#encode (to an IO)") do
61
+ times.times { io_encoder.encode(hash, StringIO.new) }
62
+ end
89
63
 
90
64
  string_encoder = Yajl::Encoder.new
91
- x.report("Yajl::Encoder#encode (to a String)") {
92
- times.times {
93
- output = string_encoder.encode(hash)
94
- }
95
- }
65
+ x.report("Yajl::Encoder#encode (to a String)") do
66
+ times.times { string_encoder.encode(hash) }
67
+ end
96
68
  end
97
69
 
98
70
  if defined?(JSON)
99
- x.report("JSON.generate") {
100
- times.times {
101
- JSON.generate(hash)
102
- }
103
- }
104
- end
105
- if defined?(Psych)
106
- x.report("Psych.to_json") {
107
- times.times {
108
- Psych.to_json(hash)
109
- }
110
- }
111
- if defined?(Psych::JSON::Stream)
112
- x.report("Psych::JSON::Stream") {
113
- times.times {
114
- io = StringIO.new
115
- stream = Psych::JSON::Stream.new io
116
- stream.start
117
- stream.push hash
118
- stream.finish
119
- }
120
- }
71
+ x.report("JSON.generate") do
72
+ times.times { JSON.generate(hash) }
73
+ end
74
+ x.report("JSON.fast_generate") do
75
+ times.times { JSON.fast_generate(hash) }
121
76
  end
122
77
  end
123
- if defined?(ActiveSupport::JSON)
124
- x.report("ActiveSupport::JSON.encode") {
125
- times.times {
126
- ActiveSupport::JSON.encode(hash)
127
- }
128
- }
129
- end
130
- }
78
+ end
131
79
  end
132
80
  end
133
81
  end
134
-
135
82
  end
@@ -1,42 +1,42 @@
1
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/..')
2
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
1
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/..")
2
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
3
3
 
4
- require 'rubygems'
5
- require 'benchmark'
6
- require 'yajl'
7
- require 'stringio'
4
+ require "rubygems" unless defined?(Gem)
5
+ require "benchmark" unless defined?(Benchmark)
6
+ require "yajl"
7
+ require "stringio" unless defined?(StringIO)
8
8
  begin
9
- require 'json'
9
+ require "json" unless defined?(JSON)
10
10
  rescue LoadError
11
11
  end
12
12
 
13
13
  times = ARGV[0] ? ARGV[0].to_i : 1000
14
- filename = 'benchmark/subjects/ohai.json'
15
- json = File.new(filename, 'r')
14
+ filename = "benchmark/subjects/ohai.json"
15
+ json = File.new(filename, "r")
16
16
  hash = Yajl::Parser.new.parse(json)
17
17
  json.close
18
18
 
19
19
  puts "Starting benchmark encoding #{filename} #{times} times\n\n"
20
- Benchmark.bmbm { |x|
20
+ Benchmark.bmbm do |x|
21
21
  encoder = Yajl::Encoder.new
22
- x.report {
22
+ x.report do
23
23
  puts "Yajl::Encoder#encode"
24
- times.times {
24
+ times.times do
25
25
  encoder.encode(hash, StringIO.new)
26
- }
27
- }
26
+ end
27
+ end
28
28
  if defined?(JSON)
29
- x.report {
29
+ x.report do
30
30
  puts "JSON's #to_json"
31
- times.times {
31
+ times.times do
32
32
  JSON.generate(hash)
33
- }
34
- }
33
+ end
34
+ end
35
35
  end
36
- x.report {
36
+ x.report do
37
37
  puts "Marshal.dump"
38
- times.times {
38
+ times.times do
39
39
  Marshal.dump(hash)
40
- }
41
- }
42
- }
40
+ end
41
+ end
42
+ end
@@ -1,53 +1,47 @@
1
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/..')
2
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
1
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/..")
2
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
3
3
 
4
- require 'rubygems'
5
- require 'benchmark'
6
- require 'yajl'
4
+ require "rubygems" unless defined?(Gem)
5
+ require "benchmark" unless defined?(Benchmark)
6
+ require "yajl"
7
7
  begin
8
- require 'json'
8
+ require "json" unless defined?(JSON)
9
9
  rescue LoadError
10
10
  end
11
- require 'yaml'
11
+ require "yaml" unless defined?(YAML)
12
12
 
13
13
  # JSON Section
14
- filename = 'benchmark/subjects/ohai.json'
15
- json = File.new(filename, 'r')
14
+ filename = "benchmark/subjects/ohai.json"
15
+ json = File.new(filename, "r")
16
16
  hash = Yajl::Parser.new.parse(json)
17
17
  json.close
18
18
 
19
19
  times = ARGV[0] ? ARGV[0].to_i : 1000
20
20
  puts "Starting benchmark encoding #{filename} into JSON #{times} times\n\n"
21
- Benchmark.bmbm { |x|
21
+ Benchmark.bmbm do |x|
22
22
  encoder = Yajl::Encoder.new
23
- x.report {
23
+ x.report do
24
24
  puts "Yajl::Encoder#encode"
25
- times.times {
26
- encoder.encode(hash, StringIO.new)
27
- }
28
- }
25
+ times.times { encoder.encode(hash, StringIO.new) }
26
+ end
29
27
  if defined?(JSON)
30
- x.report {
28
+ x.report do
31
29
  puts "JSON's #to_json"
32
- times.times {
33
- JSON.generate(hash)
34
- }
35
- }
30
+ times.times { JSON.generate(hash) }
31
+ end
36
32
  end
37
- }
33
+ end
38
34
 
39
35
  # YAML Section
40
- filename = 'benchmark/subjects/ohai.yml'
41
- yml = File.new(filename, 'r')
36
+ filename = "benchmark/subjects/ohai.yml"
37
+ yml = File.new(filename, "r")
42
38
  data = YAML.load_stream(yml)
43
39
  yml.close
44
40
 
45
41
  puts "Starting benchmark encoding #{filename} into YAML #{times} times\n\n"
46
- Benchmark.bmbm { |x|
47
- x.report {
42
+ Benchmark.bmbm do |x|
43
+ x.report do
48
44
  puts "YAML.dump"
49
- times.times {
50
- YAML.dump(data, StringIO.new)
51
- }
52
- }
53
- }
45
+ times.times { YAML.dump(data, StringIO.new) }
46
+ end
47
+ end