oj 3.8.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 (156) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +104 -0
  4. data/ext/oj/buf.h +103 -0
  5. data/ext/oj/cache8.c +107 -0
  6. data/ext/oj/cache8.h +48 -0
  7. data/ext/oj/circarray.c +68 -0
  8. data/ext/oj/circarray.h +23 -0
  9. data/ext/oj/code.c +235 -0
  10. data/ext/oj/code.h +42 -0
  11. data/ext/oj/compat.c +299 -0
  12. data/ext/oj/custom.c +1191 -0
  13. data/ext/oj/dump.c +1252 -0
  14. data/ext/oj/dump.h +96 -0
  15. data/ext/oj/dump_compat.c +977 -0
  16. data/ext/oj/dump_leaf.c +252 -0
  17. data/ext/oj/dump_object.c +837 -0
  18. data/ext/oj/dump_strict.c +433 -0
  19. data/ext/oj/encode.h +45 -0
  20. data/ext/oj/err.c +57 -0
  21. data/ext/oj/err.h +70 -0
  22. data/ext/oj/extconf.rb +47 -0
  23. data/ext/oj/fast.c +1771 -0
  24. data/ext/oj/hash.c +163 -0
  25. data/ext/oj/hash.h +46 -0
  26. data/ext/oj/hash_test.c +512 -0
  27. data/ext/oj/mimic_json.c +878 -0
  28. data/ext/oj/object.c +771 -0
  29. data/ext/oj/odd.c +231 -0
  30. data/ext/oj/odd.h +44 -0
  31. data/ext/oj/oj.c +1704 -0
  32. data/ext/oj/oj.h +385 -0
  33. data/ext/oj/parse.c +1086 -0
  34. data/ext/oj/parse.h +111 -0
  35. data/ext/oj/rails.c +1493 -0
  36. data/ext/oj/rails.h +21 -0
  37. data/ext/oj/reader.c +231 -0
  38. data/ext/oj/reader.h +151 -0
  39. data/ext/oj/resolve.c +102 -0
  40. data/ext/oj/resolve.h +14 -0
  41. data/ext/oj/rxclass.c +147 -0
  42. data/ext/oj/rxclass.h +27 -0
  43. data/ext/oj/saj.c +714 -0
  44. data/ext/oj/scp.c +224 -0
  45. data/ext/oj/sparse.c +910 -0
  46. data/ext/oj/stream_writer.c +363 -0
  47. data/ext/oj/strict.c +212 -0
  48. data/ext/oj/string_writer.c +534 -0
  49. data/ext/oj/trace.c +79 -0
  50. data/ext/oj/trace.h +28 -0
  51. data/ext/oj/util.c +136 -0
  52. data/ext/oj/util.h +19 -0
  53. data/ext/oj/val_stack.c +118 -0
  54. data/ext/oj/val_stack.h +185 -0
  55. data/ext/oj/wab.c +631 -0
  56. data/lib/oj.rb +21 -0
  57. data/lib/oj/active_support_helper.rb +41 -0
  58. data/lib/oj/bag.rb +88 -0
  59. data/lib/oj/easy_hash.rb +52 -0
  60. data/lib/oj/error.rb +22 -0
  61. data/lib/oj/json.rb +176 -0
  62. data/lib/oj/mimic.rb +267 -0
  63. data/lib/oj/saj.rb +66 -0
  64. data/lib/oj/schandler.rb +142 -0
  65. data/lib/oj/state.rb +131 -0
  66. data/lib/oj/version.rb +5 -0
  67. data/pages/Advanced.md +22 -0
  68. data/pages/Compatibility.md +25 -0
  69. data/pages/Custom.md +23 -0
  70. data/pages/Encoding.md +65 -0
  71. data/pages/JsonGem.md +79 -0
  72. data/pages/Modes.md +155 -0
  73. data/pages/Options.md +283 -0
  74. data/pages/Rails.md +116 -0
  75. data/pages/Security.md +20 -0
  76. data/pages/WAB.md +13 -0
  77. data/test/_test_active.rb +76 -0
  78. data/test/_test_active_mimic.rb +96 -0
  79. data/test/_test_mimic_rails.rb +126 -0
  80. data/test/activerecord/result_test.rb +27 -0
  81. data/test/activesupport4/decoding_test.rb +108 -0
  82. data/test/activesupport4/encoding_test.rb +531 -0
  83. data/test/activesupport4/test_helper.rb +41 -0
  84. data/test/activesupport5/decoding_test.rb +125 -0
  85. data/test/activesupport5/encoding_test.rb +485 -0
  86. data/test/activesupport5/encoding_test_cases.rb +90 -0
  87. data/test/activesupport5/test_helper.rb +50 -0
  88. data/test/activesupport5/time_zone_test_helpers.rb +24 -0
  89. data/test/bar.rb +25 -0
  90. data/test/files.rb +29 -0
  91. data/test/foo.rb +167 -0
  92. data/test/helper.rb +26 -0
  93. data/test/isolated/shared.rb +308 -0
  94. data/test/isolated/test_mimic_after.rb +13 -0
  95. data/test/isolated/test_mimic_alone.rb +12 -0
  96. data/test/isolated/test_mimic_as_json.rb +45 -0
  97. data/test/isolated/test_mimic_before.rb +13 -0
  98. data/test/isolated/test_mimic_define.rb +28 -0
  99. data/test/isolated/test_mimic_rails_after.rb +22 -0
  100. data/test/isolated/test_mimic_rails_before.rb +21 -0
  101. data/test/isolated/test_mimic_redefine.rb +15 -0
  102. data/test/json_gem/json_addition_test.rb +216 -0
  103. data/test/json_gem/json_common_interface_test.rb +148 -0
  104. data/test/json_gem/json_encoding_test.rb +107 -0
  105. data/test/json_gem/json_ext_parser_test.rb +20 -0
  106. data/test/json_gem/json_fixtures_test.rb +35 -0
  107. data/test/json_gem/json_generator_test.rb +383 -0
  108. data/test/json_gem/json_generic_object_test.rb +90 -0
  109. data/test/json_gem/json_parser_test.rb +470 -0
  110. data/test/json_gem/json_string_matching_test.rb +42 -0
  111. data/test/json_gem/test_helper.rb +18 -0
  112. data/test/perf.rb +107 -0
  113. data/test/perf_compat.rb +130 -0
  114. data/test/perf_fast.rb +164 -0
  115. data/test/perf_file.rb +64 -0
  116. data/test/perf_object.rb +138 -0
  117. data/test/perf_saj.rb +109 -0
  118. data/test/perf_scp.rb +151 -0
  119. data/test/perf_simple.rb +287 -0
  120. data/test/perf_strict.rb +145 -0
  121. data/test/perf_wab.rb +131 -0
  122. data/test/sample.rb +54 -0
  123. data/test/sample/change.rb +14 -0
  124. data/test/sample/dir.rb +19 -0
  125. data/test/sample/doc.rb +36 -0
  126. data/test/sample/file.rb +48 -0
  127. data/test/sample/group.rb +16 -0
  128. data/test/sample/hasprops.rb +16 -0
  129. data/test/sample/layer.rb +12 -0
  130. data/test/sample/line.rb +20 -0
  131. data/test/sample/oval.rb +10 -0
  132. data/test/sample/rect.rb +10 -0
  133. data/test/sample/shape.rb +35 -0
  134. data/test/sample/text.rb +20 -0
  135. data/test/sample_json.rb +37 -0
  136. data/test/test_compat.rb +509 -0
  137. data/test/test_custom.rb +503 -0
  138. data/test/test_debian.rb +53 -0
  139. data/test/test_fast.rb +470 -0
  140. data/test/test_file.rb +239 -0
  141. data/test/test_gc.rb +49 -0
  142. data/test/test_hash.rb +29 -0
  143. data/test/test_integer_range.rb +73 -0
  144. data/test/test_null.rb +376 -0
  145. data/test/test_object.rb +1018 -0
  146. data/test/test_saj.rb +186 -0
  147. data/test/test_scp.rb +433 -0
  148. data/test/test_strict.rb +410 -0
  149. data/test/test_various.rb +741 -0
  150. data/test/test_wab.rb +307 -0
  151. data/test/test_writer.rb +380 -0
  152. data/test/tests.rb +24 -0
  153. data/test/tests_mimic.rb +14 -0
  154. data/test/tests_mimic_addition.rb +7 -0
  155. data/test/zoo.rb +13 -0
  156. metadata +359 -0
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ #frozen_string_literal: false
4
+
5
+ require 'json_gem/test_helper'
6
+
7
+ require 'time'
8
+
9
+ class JSONStringMatchingTest < Test::Unit::TestCase
10
+ include Test::Unit::TestCaseOmissionSupport
11
+
12
+ class TestTime < ::Time
13
+ def self.json_create(string)
14
+ Time.parse(string)
15
+ end
16
+
17
+ def to_json(*)
18
+ %{"#{strftime('%FT%T%z')}"}
19
+ end
20
+
21
+ def ==(other)
22
+ to_i == other.to_i
23
+ end
24
+ end
25
+
26
+ def test_match_date
27
+ t = TestTime.new
28
+ t_json = [ t ].to_json
29
+ time_regexp = /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{4}\z/
30
+ assert_equal [ t ],
31
+ JSON.parse(
32
+ t_json,
33
+ :create_additions => true,
34
+ :match_string => { time_regexp => TestTime }
35
+ )
36
+ assert_equal [ t.strftime('%FT%T%z') ],
37
+ JSON.parse(
38
+ t_json,
39
+ :match_string => { time_regexp => TestTime }
40
+ )
41
+ end
42
+ end
@@ -0,0 +1,18 @@
1
+ $: << File.dirname(__FILE__)
2
+ $oj_dir = File.dirname(File.dirname(File.expand_path(File.dirname(__FILE__))))
3
+ %w(lib ext).each do |dir|
4
+ $: << File.join($oj_dir, dir)
5
+ end
6
+
7
+ require 'test/unit'
8
+ REAL_JSON_GEM = !!ENV['REAL_JSON_GEM']
9
+
10
+ if ENV['REAL_JSON_GEM']
11
+ require 'json'
12
+ else
13
+ require 'oj'
14
+ Oj.mimic_JSON
15
+ end
16
+
17
+ NaN = JSON::NaN if defined?(JSON::NaN)
18
+ NaN = 0.0/0 unless defined?(NaN)
@@ -0,0 +1,107 @@
1
+
2
+ class Perf
3
+
4
+ def initialize()
5
+ @items = []
6
+ end
7
+
8
+ def add(title, op, &blk)
9
+ @items << Item.new(title, op, &blk)
10
+ end
11
+
12
+ def before(title, &blk)
13
+ @items.each do |i|
14
+ if title == i.title
15
+ i.set_before(&blk)
16
+ break
17
+ end
18
+ end
19
+ end
20
+
21
+ def run(iter)
22
+ base = Item.new(nil, nil) { }
23
+ base.run(iter, 0.0)
24
+ @items.each do |i|
25
+ i.run(iter, base.duration)
26
+ if i.error.nil?
27
+ puts "#{i.title}.#{i.op} #{iter} times in %0.3f seconds or %0.3f #{i.op}/sec." % [i.duration, iter / i.duration]
28
+ else
29
+ puts "***** #{i.title}.#{i.op} failed! #{i.error}"
30
+ end
31
+ end
32
+ summary()
33
+ end
34
+
35
+ def summary()
36
+ fastest = nil
37
+ slowest = nil
38
+ width = 6
39
+ @items.each do |i|
40
+ next if i.duration.nil?
41
+ width = i.title.size if width < i.title.size
42
+ end
43
+ iva = @items.clone
44
+ iva.delete_if { |i| i.duration.nil? }
45
+ iva = iva.sort_by { |i| i.duration }
46
+ puts
47
+ puts "Summary:"
48
+ puts "%*s time (secs) rate (ops/sec)" % [width, 'System']
49
+ puts "#{'-' * width} ----------- --------------"
50
+ iva.each do |i|
51
+ if i.duration.nil?
52
+ else
53
+ puts "%*s %11.3f %14.3f" % [width, i.title, i.duration, i.rate ]
54
+ end
55
+ end
56
+ puts
57
+ puts "Comparison Matrix\n(performance factor, 2.0 means row is twice as fast as column)"
58
+ puts ([' ' * width] + iva.map { |i| "%*s" % [width, i.title] }).join(' ')
59
+ puts (['-' * width] + iva.map { |i| '-' * width }).join(' ')
60
+ iva.each do |i|
61
+ line = ["%*s" % [width, i.title]]
62
+ iva.each do |o|
63
+ line << "%*.2f" % [width, o.duration / i.duration]
64
+ end
65
+ puts line.join(' ')
66
+ end
67
+ puts
68
+ end
69
+
70
+ class Item
71
+ attr_accessor :title
72
+ attr_accessor :op
73
+ attr_accessor :blk
74
+ attr_accessor :duration
75
+ attr_accessor :rate
76
+ attr_accessor :error
77
+
78
+ def initialize(title, op, &blk)
79
+ @title = title
80
+ @blk = blk
81
+ @op = op
82
+ @duration = nil
83
+ @rate = nil
84
+ @error = nil
85
+ @before = nil
86
+ end
87
+
88
+ def set_before(&blk)
89
+ @before = blk
90
+ end
91
+
92
+ def run(iter, base)
93
+ begin
94
+ GC.start
95
+ @before.call unless @before.nil?
96
+ start = Time.now
97
+ iter.times { @blk.call }
98
+ @duration = Time.now - start - base
99
+ @duration = 0.0 if @duration < 0.0
100
+ @rate = iter / @duration
101
+ rescue Exception => e
102
+ @error = "#{e.class}: #{e.message}"
103
+ end
104
+ end
105
+
106
+ end # Item
107
+ end # Perf
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << '.'
5
+ $: << File.join(File.dirname(__FILE__), "../lib")
6
+ $: << File.join(File.dirname(__FILE__), "../ext")
7
+
8
+ require 'optparse'
9
+ require 'perf'
10
+ require 'oj'
11
+
12
+ $verbose = false
13
+ $indent = 0
14
+ $iter = 20000
15
+ $size = 0
16
+
17
+ opts = OptionParser.new
18
+ opts.on("-v", "verbose") { $verbose = true }
19
+ opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
20
+ opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
21
+ opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
22
+ opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
23
+ files = opts.parse(ARGV)
24
+
25
+ def capture_error(tag, orig, load_key, dump_key, &blk)
26
+ begin
27
+ obj = blk.call(orig)
28
+ puts obj unless orig == obj
29
+ raise "#{tag} #{dump_key} and #{load_key} did not return the same object as the original." unless orig == obj
30
+ rescue Exception => e
31
+ $failed[tag] = "#{e.class}: #{e.message}"
32
+ end
33
+ end
34
+
35
+ # Verify that all packages dump and load correctly and return the same Object as the original.
36
+ capture_error('Oj:compat', $obj, 'load', 'dump') { |o| Oj.compat_load(Oj.dump(o, :mode => :compat)) }
37
+ capture_error('JSON::Ext', $obj, 'generate', 'parse') { |o|
38
+ require 'json'
39
+ require 'json/ext'
40
+ JSON.generator = JSON::Ext::Generator
41
+ JSON.parser = JSON::Ext::Parser
42
+ JSON.load(JSON.generate(o))
43
+ }
44
+
45
+ module One
46
+ module Two
47
+ module Three
48
+ class Empty
49
+
50
+ def initialize()
51
+ @a = 1
52
+ @b = 2
53
+ @c = 3
54
+ end
55
+
56
+ def eql?(o)
57
+ self.class == o.class && @a == o.a && @b = o.b && @c = o.c
58
+ end
59
+ alias == eql?
60
+
61
+ def as_json(*a)
62
+ {JSON.create_id => self.class.name, 'a' => @a, 'b' => @b, 'c' => @c }
63
+ end
64
+
65
+ def to_json(*a)
66
+ JSON.generate(as_json())
67
+ end
68
+
69
+ def self.json_create(h)
70
+ self.new()
71
+ end
72
+ end # Empty
73
+ end # Three
74
+ end # Two
75
+ end # One
76
+
77
+ $obj = {
78
+ 'a' => 'Alpha', # string
79
+ 'b' => true, # boolean
80
+ 'c' => 12345, # number
81
+ 'd' => [ true, [false, [-123456789, nil], 3.9676, ['Something else.', false], nil]], # mix it up array
82
+ 'e' => { 'zero' => nil, 'one' => 1, 'two' => 2, 'three' => [3], 'four' => [0, 1, 2, 3, 4] }, # hash
83
+ 'f' => nil, # nil
84
+ 'g' => One::Two::Three::Empty.new(),
85
+ 'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
86
+ 'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
87
+ }
88
+
89
+ Oj.default_options = { :indent => $indent, :mode => :compat, :use_to_json => true, :create_additions => true, :create_id => '^o' }
90
+
91
+ if 0 < $size
92
+ s = Oj.dump($obj).size + 1
93
+ cnt = $size * 1024 / s
94
+ o = $obj
95
+ $obj = []
96
+ cnt.times do
97
+ $obj << o
98
+ end
99
+ end
100
+
101
+ $json = Oj.dump($obj)
102
+ $failed = {} # key is same as String used in tests later
103
+
104
+ if $verbose
105
+ puts "size: #{$json.size}"
106
+ puts "json:\n#{$json}\n"
107
+ puts "Oj:compat loaded object:\n#{Oj.compat_load($json)}\n"
108
+ puts "JSON loaded object:\n#{JSON::Ext::Parser.new($json).parse}\n"
109
+ end
110
+
111
+ puts '-' * 80
112
+ puts "Compat Parse Performance"
113
+ perf = Perf.new()
114
+ unless $failed.has_key?('JSON::Ext')
115
+ perf.add('JSON::Ext', 'parse') { JSON.load($json) }
116
+ perf.before('JSON::Ext') { JSON.parser = JSON::Ext::Parser }
117
+ end
118
+ unless $failed.has_key?('Oj:compat')
119
+ perf.add('Oj:compat', 'compat_load') { Oj.compat_load($json) }
120
+ end
121
+ perf.run($iter)
122
+
123
+ puts
124
+ puts '-' * 80
125
+ puts
126
+
127
+ unless $failed.empty?
128
+ puts "The following packages were not included for the reason listed"
129
+ $failed.each { |tag,msg| puts "***** #{tag}: #{msg}" }
130
+ end
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env ruby -wW1
2
+ # encoding: UTF-8
3
+
4
+ $: << '.'
5
+ $: << File.join(File.dirname(__FILE__), "../lib")
6
+ $: << File.join(File.dirname(__FILE__), "../ext")
7
+
8
+ require 'optparse'
9
+ #require 'yajl'
10
+ require 'perf'
11
+ require 'json'
12
+ require 'json/ext'
13
+ require 'oj'
14
+
15
+ $verbose = false
16
+ $indent = 0
17
+ $iter = 100000
18
+ $gets = 0
19
+ $fetch = false
20
+ $write = false
21
+ $read = false
22
+
23
+ opts = OptionParser.new
24
+ opts.on("-v", "verbose") { $verbose = true }
25
+ opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
26
+ opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
27
+ opts.on("-g", "--gets [Int]", Integer, "number of gets") { |i| $gets = i }
28
+ opts.on("-f", "fetch") { $fetch = true }
29
+ opts.on("-w", "write") { $write = true }
30
+ opts.on("-r", "read") { $read = true }
31
+ opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
32
+ files = opts.parse(ARGV)
33
+
34
+ # This just navigates to each leaf of the JSON structure.
35
+ def dig(obj, &blk)
36
+ case obj
37
+ when Array
38
+ obj.each { |e| dig(e, &blk) }
39
+ when Hash
40
+ obj.values.each { |e| dig(e, &blk) }
41
+ else
42
+ blk.yield(obj)
43
+ end
44
+ end
45
+
46
+ $obj = {
47
+ 'a' => 'Alpha', # string
48
+ 'b' => true, # boolean
49
+ 'c' => 12345, # number
50
+ 'd' => [ true, [false, {'12345' => 12345, 'nil' => nil}, 3.967, { 'x' => 'something', 'y' => false, 'z' => true}, nil]], # mix it up array
51
+ 'e' => { 'one' => 1, 'two' => 2 }, # hash
52
+ 'f' => nil, # nil
53
+ 'g' => 12345678901234567890123456789, # big number
54
+ 'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
55
+ 'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
56
+ }
57
+
58
+ Oj.default_options = { :indent => $indent, :mode => :compat }
59
+
60
+ $json = Oj.dump($obj)
61
+ $failed = {} # key is same as String used in tests later
62
+
63
+ def capture_error(tag, orig, load_key, dump_key, &blk)
64
+ begin
65
+ obj = blk.call(orig)
66
+ raise "#{tag} #{dump_key} and #{load_key} did not return the same object as the original." unless orig == obj
67
+ rescue Exception => e
68
+ $failed[tag] = "#{e.class}: #{e.message}"
69
+ end
70
+ end
71
+
72
+ # Verify that all packages dump and load correctly and return the same Object as the original.
73
+ capture_error('Oj::Doc', $obj, 'load', 'dump') { |o| Oj::Doc.open(Oj.dump(o, :mode => :strict)) { |f| f.fetch() } }
74
+ #capture_error('Yajl', $obj, 'encode', 'parse') { |o| Yajl::Parser.parse(Yajl::Encoder.encode(o)) }
75
+ capture_error('JSON::Ext', $obj, 'generate', 'parse') { |o| JSON.generator = JSON::Ext::Generator; JSON::Ext::Parser.new(JSON.generate(o)).parse }
76
+
77
+ if $verbose
78
+ puts "json:\n#{$json}\n"
79
+ end
80
+
81
+ puts '-' * 80
82
+ puts "Parse Performance"
83
+ perf = Perf.new()
84
+ perf.add('Oj::Doc', 'parse') { Oj::Doc.open($json) {|f| } } unless $failed.has_key?('Oj::Doc')
85
+ #perf.add('Yajl', 'parse') { Yajl::Parser.parse($json) } unless $failed.has_key?('Yajl')
86
+ perf.add('JSON::Ext', 'parse') { JSON::Ext::Parser.new($json).parse } unless $failed.has_key?('JSON::Ext')
87
+ perf.run($iter)
88
+
89
+ puts '-' * 80
90
+ puts "JSON generation Performance"
91
+ Oj::Doc.open($json) do |doc|
92
+ perf = Perf.new()
93
+ perf.add('Oj::Doc', 'dump') { doc.dump() }
94
+ # perf.add('Yajl', 'encode') { Yajl::Encoder.encode($obj) }
95
+ perf.add('JSON::Ext', 'fast_generate') { JSON.fast_generate($obj) }
96
+ perf.before('JSON::Ext') { JSON.generator = JSON::Ext::Generator }
97
+ perf.run($iter)
98
+ end
99
+
100
+ if 0 < $gets
101
+ puts '-' * 80
102
+ puts "Parse and get all values Performance"
103
+ perf = Perf.new()
104
+ perf.add('Oj::Doc', 'parse') { Oj::Doc.open($json) {|f| $gets.times { f.each_value() {} } } } unless $failed.has_key?('Oj::Doc')
105
+ # perf.add('Yajl', 'parse') { $gets.times { dig(Yajl::Parser.parse($json)) {} } } unless $failed.has_key?('Yajl')
106
+ perf.add('JSON::Ext', 'parse') { $gets.times { dig(JSON::Ext::Parser.new($json).parse) {} } } unless $failed.has_key?('JSON::Ext')
107
+ perf.run($iter)
108
+ end
109
+
110
+ if $fetch
111
+ puts '-' * 80
112
+ puts "fetch nested Performance"
113
+ json_hash = Oj.load($json, :mode => :strict)
114
+ Oj::Doc.open($json) do |fast|
115
+ #puts "*** C fetch: #{fast.fetch('/d/2/4/y')}"
116
+ #puts "*** Ruby fetch: #{json_hash.fetch('d', []).fetch(1, []).fetch(3, []).fetch('x', nil)}"
117
+ perf = Perf.new()
118
+ perf.add('Oj::Doc', 'fetch') { fast.fetch('/d/2/4/x'); fast.fetch('/h/a/b/c/d/e/f/g'); fast.fetch('/i/1/1/1/1/1/1/1') }
119
+ # version that fails gracefully
120
+ perf.add('Ruby', 'fetch') do
121
+ json_hash.fetch('d', []).fetch(1, []).fetch(3, []).fetch('x', nil)
122
+ json_hash.fetch('h', {}).fetch('a', {}).fetch('b', {}).fetch('c', {}).fetch('d', {}).fetch('e', {}).fetch('f', {}).fetch('g', {})
123
+ json_hash.fetch('i', []).fetch(0, []).fetch(0, []).fetch(0, []).fetch(0, []).fetch(0, []).fetch(0, []).fetch(0, nil)
124
+ end
125
+ # version that raises if the path is incorrect
126
+ # perf.add('Ruby', 'fetch') { $fetch.times { json_hash['d'][1][3][1] } }
127
+ perf.run($iter)
128
+ end
129
+ end
130
+
131
+ if $write
132
+ puts '-' * 80
133
+ puts "JSON write to file Performance"
134
+ Oj::Doc.open($json) do |doc|
135
+ perf = Perf.new()
136
+ perf.add('Oj::Doc', 'dump') { doc.dump(nil, 'oj.json') }
137
+ # perf.add('Yajl', 'encode') { File.open('yajl.json', 'w') { |f| Yajl::Encoder.encode($obj, f) } }
138
+ perf.add('JSON::Ext', 'fast_generate') { File.open('json_ext.json', 'w') { |f| f.write(JSON.fast_generate($obj)) } }
139
+ perf.before('JSON::Ext') { JSON.generator = JSON::Ext::Generator }
140
+ perf.run($iter)
141
+ end
142
+ end
143
+
144
+ if $read
145
+ puts '-' * 80
146
+ puts "JSON read from file Performance"
147
+ Oj::Doc.open($json) { |doc| doc.dump(nil, 'oj.json') }
148
+ # File.open('yajl.json', 'w') { |f| Yajl::Encoder.encode($obj, f) }
149
+ JSON.generator = JSON::Ext::Generator
150
+ File.open('json_ext.json', 'w') { |f| f.write(JSON.fast_generate($obj)) }
151
+ Oj::Doc.open($json) do |doc|
152
+ perf = Perf.new()
153
+ perf.add('Oj::Doc', 'open_file') { ::Oj::Doc.open_file('oj.json') }
154
+ # perf.add('Yajl', 'decode') { Yajl::decoder.decode(File.read('yajl.json')) }
155
+ perf.add('JSON::Ext', '') { JSON.parse(File.read('json_ext.json')) }
156
+ perf.before('JSON::Ext') { JSON.parser = JSON::Ext::Parser }
157
+ perf.run($iter)
158
+ end
159
+ end
160
+
161
+ unless $failed.empty?
162
+ puts "The following packages were not included for the reason listed"
163
+ $failed.each { |tag,msg| puts "***** #{tag}: #{msg}" }
164
+ end