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,54 +1,54 @@
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
11
  begin
12
- require 'active_support'
12
+ require "active_support"
13
13
  rescue LoadError
14
14
  end
15
15
 
16
- filename = 'benchmark/subjects/twitter_stream.json'
17
- json = File.new(filename, 'r')
16
+ filename = "benchmark/subjects/twitter_stream.json"
17
+ json = File.new(filename, "r")
18
18
 
19
19
  times = ARGV[0] ? ARGV[0].to_i : 100
20
20
  puts "Starting benchmark parsing JSON stream (#{File.size(filename)} bytes of JSON data with 430 JSON separate strings) #{times} times\n\n"
21
- Benchmark.bmbm { |x|
21
+ Benchmark.bmbm do |x|
22
22
  parser = Yajl::Parser.new
23
- parser.on_parse_complete = lambda {|obj|}
24
- x.report {
23
+ parser.on_parse_complete = ->(obj) {}
24
+ x.report do
25
25
  puts "Yajl::Parser#parse"
26
- times.times {
26
+ times.times do
27
27
  json.rewind
28
28
  parser.parse(json)
29
- }
30
- }
29
+ end
30
+ end
31
31
  if defined?(JSON)
32
- x.report {
32
+ x.report do
33
33
  puts "JSON.parse"
34
- times.times {
34
+ times.times do
35
35
  json.rewind
36
- while chunk = json.gets
37
- JSON.parse(chunk, :max_nesting => false)
36
+ while ( chunk = json.gets )
37
+ JSON.parse(chunk, max_nesting: false)
38
38
  end
39
- }
40
- }
39
+ end
40
+ end
41
41
  end
42
42
  if defined?(ActiveSupport::JSON)
43
- x.report {
43
+ x.report do
44
44
  puts "ActiveSupport::JSON.decode"
45
- times.times {
45
+ times.times do
46
46
  json.rewind
47
- while chunk = json.gets
47
+ while ( chunk = json.gets )
48
48
  ActiveSupport::JSON.decode(chunk)
49
49
  end
50
- }
51
- }
50
+ end
51
+ end
52
52
  end
53
- }
54
- json.close
53
+ end
54
+ json.close
@@ -1,7 +1,27 @@
1
+ # Copyright (c) 2015 Lamont Granquist
2
+ # Copyright (c) 2013-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
22
 
2
- require 'ffi_yajl/benchmark/encode.rb'
3
- require 'ffi_yajl/benchmark/encode_profile.rb'
4
- require 'ffi_yajl/benchmark/parse.rb'
5
- require 'ffi_yajl/benchmark/parse_profile.rb'
6
- require 'ffi_yajl/benchmark/parse_profile_ruby_prof.rb'
7
-
23
+ require "ffi_yajl/benchmark/encode"
24
+ require "ffi_yajl/benchmark/encode_profile"
25
+ require "ffi_yajl/benchmark/parse"
26
+ require "ffi_yajl/benchmark/parse_profile"
27
+ require "ffi_yajl/benchmark/parse_profile_ruby_prof"
@@ -1,6 +1,28 @@
1
+ # Copyright (c) 2015 Lamont Granquist
2
+ # Copyright (c) 2013-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
22
 
2
23
  module FFI_Yajl
3
24
  class EncodeError < StandardError; end
25
+
4
26
  class Encoder
5
27
  attr_accessor :opts
6
28
 
@@ -8,18 +30,27 @@ module FFI_Yajl
8
30
  # initialization that we can do in pure ruby
9
31
  yajl_gen_opts = {}
10
32
 
11
- yajl_gen_opts[:yajl_gen_validate_utf8] = true
33
+ yajl_gen_opts[:yajl_gen_validate_utf8] = @opts[:validate_utf8] == false ? false : true
12
34
  yajl_gen_opts[:yajl_gen_beautify] = false
13
35
  yajl_gen_opts[:yajl_gen_indent_string] = " "
14
36
 
15
37
  if opts[:pretty]
16
38
  yajl_gen_opts[:yajl_gen_beautify] = true
17
- yajl_gen_opts[:yajl_gen_indent_string] = opts[:indent] ? opts[:indent] : " "
39
+ yajl_gen_opts[:yajl_gen_indent_string] = opts[:indent] || " "
18
40
  end
19
41
 
20
42
  # call either the ext or ffi hook
21
- str = do_yajl_encode(obj, yajl_gen_opts)
22
- str.force_encoding('UTF-8') if defined? Encoding
43
+ str = do_yajl_encode(obj, yajl_gen_opts, opts)
44
+ # we can skip cleaning the whole string for utf-8 issues if we have yajl validate as we go
45
+
46
+ str.force_encoding("UTF-8")
47
+ unless yajl_gen_opts[:yajl_gen_validate_utf8]
48
+ if str.respond_to?(:scrub)
49
+ str.scrub!
50
+ else
51
+ str.encode!("UTF-16le", undef: :replace, invalid: :replace).encode!("UTF-8")
52
+ end
53
+ end
23
54
  str
24
55
  end
25
56
 
@@ -29,9 +60,17 @@ module FFI_Yajl
29
60
 
30
61
  def initialize(opts = {})
31
62
  @opts = opts
63
+ @opts ||= {}
32
64
  end
33
65
 
34
- def self.raise_error_for_status(status)
66
+ def self.raise_error_for_status(status, token = nil)
67
+ # scrub token to valid utf-8 since we may be issuing an exception on an invalid utf-8 token
68
+ token = token.to_s.force_encoding("UTF-8")
69
+ if token.respond_to?(:scrub)
70
+ token.scrub!
71
+ else
72
+ token.encode!("UTF-16le", undef: :replace, invalid: :replace).encode!("UTF-8")
73
+ end
35
74
  case status
36
75
  when 1 # yajl_gen_keys_must_be_strings
37
76
  raise FFI_Yajl::EncodeError, "YAJL internal error: attempted use of non-string object as key"
@@ -45,8 +84,10 @@ module FFI_Yajl
45
84
  raise FFI_Yajl::EncodeError, "Invalid number: cannot encode Infinity, -Infinity, or NaN"
46
85
  when 6 # yajl_gen_no_buf
47
86
  raise FFI_Yajl::EncodeError, "YAJL internal error: yajl_gen_get_buf was called, but a print callback was specified, so no internal buffer is available"
87
+ when 7 # yajl_gen_invalid_string
88
+ raise FFI_Yajl::EncodeError, "Invalid UTF-8 string '#{token}': cannot encode to UTF-8"
48
89
  else
49
- raise FFI_Yajl::EncodeError, "Unknown YAJL Error, please report this as a bug"
90
+ raise FFI_Yajl::EncodeError, "Unknown YAJL Error (#{status}), please report this as a bug"
50
91
  end
51
92
  end
52
93
  end
data/lib/ffi_yajl/ext.rb CHANGED
@@ -1,22 +1,49 @@
1
- require 'rubygems'
1
+ # Copyright (c) 2015 Lamont Granquist
2
+ # Copyright (c) 2013-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2
22
 
3
- require 'ffi_yajl/encoder'
4
- require 'ffi_yajl/parser'
23
+ require "rubygems" unless defined?(Gem)
5
24
 
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
25
+ require_relative "encoder"
26
+ require_relative "parser"
27
+ require "ffi_yajl/ext/dlopen"
28
+ require_relative "map_library_name"
29
+
30
+ # needed so the encoder c-code can find these symbols
31
+ require "stringio" unless defined?(StringIO)
32
+ require "date"
10
33
 
11
34
  module FFI_Yajl
35
+ extend FFI_Yajl::MapLibraryName
36
+ extend FFI_Yajl::Ext::Dlopen
37
+
38
+ dlopen_yajl_library
39
+
12
40
  class Parser
13
- require 'ffi_yajl/ext/parser'
41
+ require "ffi_yajl/ext/parser"
14
42
  include FFI_Yajl::Ext::Parser
15
43
  end
16
44
 
17
45
  class Encoder
18
- require 'ffi_yajl/ext/encoder'
46
+ require "ffi_yajl/ext/encoder"
19
47
  include FFI_Yajl::Ext::Encoder
20
48
  end
21
49
  end
22
-
@@ -1,12 +1,33 @@
1
+ # Copyright (c) 2015 Lamont Granquist
2
+ # Copyright (c) 2013-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
22
 
2
- require 'ffi_yajl/ffi'
23
+ require "date"
24
+ require "stringio" unless defined?(StringIO)
3
25
 
4
26
  module FFI_Yajl
5
27
  module FFI
6
28
  module Encoder
7
- def do_yajl_encode(obj, yajl_gen_opts = {})
8
-
9
- yajl_gen = FFI_Yajl.yajl_gen_alloc(nil);
29
+ def do_yajl_encode(obj, yajl_gen_opts, opts)
30
+ yajl_gen = FFI_Yajl.yajl_gen_alloc(nil)
10
31
 
11
32
  # configure the yajl encoder
12
33
  if yajl_gen_opts[:yajl_gen_beautify]
@@ -20,8 +41,8 @@ module FFI_Yajl
20
41
 
21
42
  # setup our own state
22
43
  state = {
23
- :json_opts => opts,
24
- :processing_key => false,
44
+ json_opts: opts,
45
+ processing_key: false,
25
46
  }
26
47
 
27
48
  # do the encoding
@@ -33,105 +54,121 @@ module FFI_Yajl
33
54
  if ( status = FFI_Yajl.yajl_gen_get_buf(yajl_gen, string_ptr, length_ptr) ) != 0
34
55
  FFI_Yajl::Encoder.raise_error_for_status(status)
35
56
  end
36
- length = length_ptr.read_int
37
57
  string = string_ptr.get_pointer(0).read_string
38
58
 
39
59
  FFI_Yajl.yajl_gen_free(yajl_gen)
40
60
 
41
- return string
61
+ string
42
62
  end
43
-
44
63
  end
45
64
  end
46
65
  end
47
66
 
48
67
  class Hash
49
68
  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)
69
+ if state[:processing_key]
70
+ str = to_s
71
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
72
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
73
+ end
74
+ else
75
+ if ( status = FFI_Yajl.yajl_gen_map_open(yajl_gen) ) != 0
76
+ FFI_Yajl::Encoder.raise_error_for_status(status, "{")
77
+ end
78
+ each do |key, value|
79
+ # Perf Fix: mutate state hash rather than creating new copy
80
+ state[:processing_key] = true
81
+ key.ffi_yajl(yajl_gen, state)
82
+ state[:processing_key] = false
83
+ value.ffi_yajl(yajl_gen, state)
84
+ end
85
+ if ( status = FFI_Yajl.yajl_gen_map_close(yajl_gen) ) != 0
86
+ FFI_Yajl::Encoder.raise_error_for_status(status, "}")
87
+ end
62
88
  end
63
89
  end
64
90
  end
65
91
 
66
92
  class Array
67
93
  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)
94
+ if state[:processing_key]
95
+ str = to_s
96
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
97
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
98
+ end
99
+ else
100
+ if ( status = FFI_Yajl.yajl_gen_array_open(yajl_gen) ) != 0
101
+ FFI_Yajl::Encoder.raise_error_for_status(status, "[")
102
+ end
103
+ each do |value|
104
+ value.ffi_yajl(yajl_gen, state)
105
+ end
106
+ if ( status = FFI_Yajl.yajl_gen_array_close(yajl_gen) ) != 0
107
+ FFI_Yajl::Encoder.raise_error_for_status(status, "]")
108
+ end
76
109
  end
77
110
  end
78
111
  end
79
112
 
80
113
  class NilClass
81
114
  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)
115
+ str = to_s
116
+ if state[:processing_key]
117
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
118
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
119
+ end
120
+ else
121
+ if ( status = FFI_Yajl.yajl_gen_null(yajl_gen) ) != 0
122
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
123
+ end
84
124
  end
85
125
  end
86
126
  end
87
127
 
88
128
  class TrueClass
89
129
  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)
130
+ str = to_s
131
+ if state[:processing_key]
132
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
133
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
134
+ end
135
+ else
136
+ if ( status = FFI_Yajl.yajl_gen_bool(yajl_gen, 1) ) != 0
137
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
138
+ end
92
139
  end
93
140
  end
94
141
  end
95
142
 
96
143
  class FalseClass
97
144
  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
145
+ str = to_s
110
146
  if state[:processing_key]
111
147
  if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
112
- FFI_Yajl::Encoder.raise_error_for_status(status)
148
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
113
149
  end
114
150
  else
115
- if ( status = FFI_Yajl.yajl_gen_integer(yajl_gen, self) ) != 0
116
- FFI_Yajl::Encoder.raise_error_for_status(status)
151
+ if ( status = FFI_Yajl.yajl_gen_bool(yajl_gen, 0) ) != 0
152
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
117
153
  end
118
154
  end
119
155
  end
120
156
  end
121
157
 
122
- class Bignum
158
+ class Integer
123
159
  def ffi_yajl(yajl_gen, state)
124
- str = self.to_s
160
+ str = to_s
125
161
  if str == "NaN" || str == "Infinity" || str == "-Infinity"
126
- raise ::FFI_Yajl::EncodeError.new("'#{str}' is an invalid number")
162
+ raise ::FFI_Yajl::EncodeError, "'#{str}' is an invalid number"
127
163
  end
164
+
128
165
  if state[:processing_key]
129
166
  if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
130
- FFI_Yajl::Encoder.raise_error_for_status(status)
167
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
131
168
  end
132
169
  else
133
170
  if ( status = FFI_Yajl.yajl_gen_number(yajl_gen, str, str.bytesize) ) != 0
134
- FFI_Yajl::Encoder.raise_error_for_status(status)
171
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
135
172
  end
136
173
  end
137
174
  end
@@ -139,26 +176,72 @@ end
139
176
 
140
177
  class Float
141
178
  def ffi_yajl(yajl_gen, state)
142
- str = self.to_s
179
+ str = to_s
143
180
  if str == "NaN" || str == "Infinity" || str == "-Infinity"
144
- raise ::FFI_Yajl::EncodeError.new("'#{str}' is an invalid number")
181
+ raise ::FFI_Yajl::EncodeError, "'#{str}' is an invalid number"
145
182
  end
183
+
146
184
  if state[:processing_key]
147
185
  if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
148
- FFI_Yajl::Encoder.raise_error_for_status(status)
186
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
149
187
  end
150
188
  else
151
189
  if ( status = FFI_Yajl.yajl_gen_number(yajl_gen, str, str.bytesize) ) != 0
152
- FFI_Yajl::Encoder.raise_error_for_status(status)
190
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
153
191
  end
154
192
  end
155
193
  end
156
194
  end
157
195
 
196
+ class Symbol
197
+ def ffi_yajl(yajl_gen, state)
198
+ str = to_s
199
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
200
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
201
+ end
202
+ end
203
+ end
204
+
158
205
  class String
159
206
  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)
207
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, self, bytesize) ) != 0
208
+ FFI_Yajl::Encoder.raise_error_for_status(status, self)
209
+ end
210
+ end
211
+ end
212
+
213
+ class StringIO
214
+ def ffi_yajl(yajl_gen, state)
215
+ str = read
216
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
217
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
218
+ end
219
+ end
220
+ end
221
+
222
+ class Date
223
+ def ffi_yajl(yajl_gen, state)
224
+ str = to_s
225
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
226
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
227
+ end
228
+ end
229
+ end
230
+
231
+ class Time
232
+ def ffi_yajl(yajl_gen, state)
233
+ str = strftime "%Y-%m-%d %H:%M:%S %z"
234
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
235
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
236
+ end
237
+ end
238
+ end
239
+
240
+ class DateTime
241
+ def ffi_yajl(yajl_gen, state)
242
+ str = to_s
243
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
244
+ FFI_Yajl::Encoder.raise_error_for_status(status, str)
162
245
  end
163
246
  end
164
247
  end
@@ -166,10 +249,14 @@ end
166
249
  # I feel dirty
167
250
  class Object
168
251
  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)
252
+ if !state[:processing_key] && respond_to?(:to_json)
253
+ str = to_json(state[:json_opts])
254
+ # #yajl_gen_number outputs a string without quotes around it
255
+ status = FFI_Yajl.yajl_gen_number(yajl_gen, str, str.bytesize)
256
+ else
257
+ str = to_s
258
+ status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize)
172
259
  end
260
+ FFI_Yajl::Encoder.raise_error_for_status(status, str) if ( status ) != 0
173
261
  end
174
262
  end
175
-