oj_windows 3.16.15

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 (102) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +44 -0
  3. data/LICENSE +21 -0
  4. data/README.md +164 -0
  5. data/ext/oj_windows/buf.h +85 -0
  6. data/ext/oj_windows/cache.c +339 -0
  7. data/ext/oj_windows/cache.h +22 -0
  8. data/ext/oj_windows/cache8.c +105 -0
  9. data/ext/oj_windows/cache8.h +21 -0
  10. data/ext/oj_windows/circarray.c +64 -0
  11. data/ext/oj_windows/circarray.h +22 -0
  12. data/ext/oj_windows/code.c +214 -0
  13. data/ext/oj_windows/code.h +40 -0
  14. data/ext/oj_windows/compat.c +239 -0
  15. data/ext/oj_windows/custom.c +1074 -0
  16. data/ext/oj_windows/debug.c +126 -0
  17. data/ext/oj_windows/dump.c +1556 -0
  18. data/ext/oj_windows/dump.h +110 -0
  19. data/ext/oj_windows/dump_compat.c +901 -0
  20. data/ext/oj_windows/dump_leaf.c +162 -0
  21. data/ext/oj_windows/dump_object.c +710 -0
  22. data/ext/oj_windows/dump_strict.c +405 -0
  23. data/ext/oj_windows/encode.h +16 -0
  24. data/ext/oj_windows/err.c +57 -0
  25. data/ext/oj_windows/err.h +67 -0
  26. data/ext/oj_windows/extconf.rb +77 -0
  27. data/ext/oj_windows/fast.c +1710 -0
  28. data/ext/oj_windows/intern.c +325 -0
  29. data/ext/oj_windows/intern.h +22 -0
  30. data/ext/oj_windows/mem.c +320 -0
  31. data/ext/oj_windows/mem.h +53 -0
  32. data/ext/oj_windows/mimic_json.c +919 -0
  33. data/ext/oj_windows/object.c +726 -0
  34. data/ext/oj_windows/odd.c +245 -0
  35. data/ext/oj_windows/odd.h +43 -0
  36. data/ext/oj_windows/oj.c +2097 -0
  37. data/ext/oj_windows/oj.h +420 -0
  38. data/ext/oj_windows/parse.c +1317 -0
  39. data/ext/oj_windows/parse.h +113 -0
  40. data/ext/oj_windows/parser.c +1600 -0
  41. data/ext/oj_windows/parser.h +103 -0
  42. data/ext/oj_windows/rails.c +1484 -0
  43. data/ext/oj_windows/rails.h +18 -0
  44. data/ext/oj_windows/reader.c +222 -0
  45. data/ext/oj_windows/reader.h +137 -0
  46. data/ext/oj_windows/resolve.c +80 -0
  47. data/ext/oj_windows/resolve.h +12 -0
  48. data/ext/oj_windows/rxclass.c +144 -0
  49. data/ext/oj_windows/rxclass.h +26 -0
  50. data/ext/oj_windows/saj.c +675 -0
  51. data/ext/oj_windows/saj2.c +584 -0
  52. data/ext/oj_windows/saj2.h +23 -0
  53. data/ext/oj_windows/scp.c +187 -0
  54. data/ext/oj_windows/simd.h +47 -0
  55. data/ext/oj_windows/sparse.c +946 -0
  56. data/ext/oj_windows/stream_writer.c +329 -0
  57. data/ext/oj_windows/strict.c +189 -0
  58. data/ext/oj_windows/string_writer.c +517 -0
  59. data/ext/oj_windows/trace.c +72 -0
  60. data/ext/oj_windows/trace.h +55 -0
  61. data/ext/oj_windows/usual.c +1218 -0
  62. data/ext/oj_windows/usual.h +69 -0
  63. data/ext/oj_windows/util.c +136 -0
  64. data/ext/oj_windows/util.h +20 -0
  65. data/ext/oj_windows/val_stack.c +101 -0
  66. data/ext/oj_windows/val_stack.h +151 -0
  67. data/ext/oj_windows/validate.c +46 -0
  68. data/ext/oj_windows/wab.c +584 -0
  69. data/lib/oj/active_support_helper.rb +39 -0
  70. data/lib/oj/bag.rb +95 -0
  71. data/lib/oj/easy_hash.rb +52 -0
  72. data/lib/oj/error.rb +21 -0
  73. data/lib/oj/json.rb +188 -0
  74. data/lib/oj/mimic.rb +301 -0
  75. data/lib/oj/saj.rb +80 -0
  76. data/lib/oj/schandler.rb +143 -0
  77. data/lib/oj/state.rb +135 -0
  78. data/lib/oj/version.rb +4 -0
  79. data/lib/oj_windows/active_support_helper.rb +39 -0
  80. data/lib/oj_windows/bag.rb +95 -0
  81. data/lib/oj_windows/easy_hash.rb +52 -0
  82. data/lib/oj_windows/error.rb +21 -0
  83. data/lib/oj_windows/json.rb +188 -0
  84. data/lib/oj_windows/mimic.rb +301 -0
  85. data/lib/oj_windows/saj.rb +80 -0
  86. data/lib/oj_windows/schandler.rb +143 -0
  87. data/lib/oj_windows/state.rb +135 -0
  88. data/lib/oj_windows/version.rb +4 -0
  89. data/lib/oj_windows.rb +15 -0
  90. data/pages/Advanced.md +38 -0
  91. data/pages/Compatibility.md +49 -0
  92. data/pages/Custom.md +37 -0
  93. data/pages/Encoding.md +61 -0
  94. data/pages/InstallOptions.md +20 -0
  95. data/pages/JsonGem.md +60 -0
  96. data/pages/Modes.md +94 -0
  97. data/pages/Options.md +339 -0
  98. data/pages/Parser.md +134 -0
  99. data/pages/Rails.md +85 -0
  100. data/pages/Security.md +43 -0
  101. data/pages/WAB.md +12 -0
  102. metadata +242 -0
@@ -0,0 +1,52 @@
1
+ module Oj
2
+
3
+ # A Hash subclass that normalizes the hash keys to allow lookup by the
4
+ # key.to_s or key.to_sym. It also supports looking up hash values by methods
5
+ # that match the keys.
6
+ class EasyHash < Hash
7
+
8
+ # Replaces the Object.respond_to?() method.
9
+ # @param [Symbol] m method symbol
10
+ # @param [Boolean] include_all whether to include private and protected methods in the search
11
+ # @return [Boolean] true for any method that matches an instance
12
+ # variable reader, otherwise false.
13
+ def respond_to?(m, include_all = false)
14
+ return true if super
15
+ return true if has_key?(m)
16
+ return true if has_key?(m.to_s)
17
+
18
+ has_key?(m.to_sym)
19
+ end
20
+
21
+ def [](key)
22
+ return fetch(key, nil) if has_key?(key)
23
+ return fetch(key.to_s, nil) if has_key?(key.to_s)
24
+
25
+ fetch(key.to_sym, nil)
26
+ end
27
+
28
+ # Handles requests for Hash values. Others cause an Exception to be raised.
29
+ # @param [Symbol|String] m method symbol
30
+ # @return [Boolean] the value of the specified instance variable.
31
+ # @raise [ArgumentError] if an argument is given. Zero arguments expected.
32
+ # @raise [NoMethodError] if the instance variable is not defined.
33
+ def method_missing(m, *args, &block)
34
+ if m.to_s.end_with?('=')
35
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 1 with #{m}) to method #{m}") if args.nil? or 1 != args.length
36
+
37
+ m = m[0..-2]
38
+ return store(m.to_s, args[0]) if has_key?(m.to_s)
39
+ return store(m.to_sym, args[0]) if has_key?(m.to_sym)
40
+
41
+ return store(m, args[0])
42
+ else
43
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 0 with #{m}) to method #{m}") unless args.nil? or args.empty?
44
+ return fetch(m, nil) if has_key?(m)
45
+ return fetch(m.to_s, nil) if has_key?(m.to_s)
46
+ return fetch(m.to_sym, nil) if has_key?(m.to_sym)
47
+ end
48
+ raise NoMethodError.new("undefined method #{m}", m)
49
+ end
50
+
51
+ end # EasyHash
52
+ end # Oj
data/lib/oj/error.rb ADDED
@@ -0,0 +1,21 @@
1
+ module Oj
2
+
3
+ # Inherit Error class from StandardError.
4
+ Error = Class.new(StandardError)
5
+
6
+ # Following classes inherit from the Error class.
7
+ # -----------------------------------------------
8
+
9
+ # An Exception that is raised as a result of a parse error while parsing a JSON document.
10
+ ParseError = Class.new(Error)
11
+
12
+ # An Exception that is raised as a result of a path being too deep.
13
+ DepthError = Class.new(Error)
14
+
15
+ # An Exception that is raised if a file fails to load.
16
+ LoadError = Class.new(Error)
17
+
18
+ # An Exception that is raised if there is a conflict with mimicking JSON
19
+ MimicError = Class.new(Error)
20
+
21
+ end # Oj
data/lib/oj/json.rb ADDED
@@ -0,0 +1,188 @@
1
+ require 'ostruct'
2
+ require 'oj_windows/state'
3
+
4
+ if defined?(JSON::PRETTY_STATE_PROTOTYPE)
5
+ # There are enough people that try to use both the json gen and oj in mimic
6
+ # mode so don't display the warning.
7
+
8
+ # warn "WARNING: oj_windows/json is a compatability shim used by Oj. Requiring the file explicitly is not recommended."
9
+ end
10
+
11
+ unless defined?(JSON::PRETTY_STATE_PROTOTYPE)
12
+ module JSON
13
+ NaN = 0.0/0.0 unless defined?(::JSON::NaN)
14
+ Infinity = 1.0/0.0 unless defined?(::JSON::Infinity)
15
+ MinusInfinity = -1.0/0.0 unless defined?(::JSON::MinusInfinity)
16
+ # Taken from the unit test. Note that items like check_circular? are not
17
+ # present.
18
+ PRETTY_STATE_PROTOTYPE = Ext::Generator::State.from_state({
19
+ :allow_nan => false,
20
+ :array_nl => "\n",
21
+ :ascii_only => false,
22
+ :buffer_initial_length => 1024,
23
+ :depth => 0,
24
+ :indent => " ",
25
+ :max_nesting => 100,
26
+ :object_nl => "\n",
27
+ :space => " ",
28
+ :space_before => "",
29
+ }) unless defined?(::JSON::PRETTY_STATE_PROTOTYPE)
30
+ SAFE_STATE_PROTOTYPE = Ext::Generator::State.from_state({
31
+ :allow_nan => false,
32
+ :array_nl => "",
33
+ :ascii_only => false,
34
+ :buffer_initial_length => 1024,
35
+ :depth => 0,
36
+ :indent => "",
37
+ :max_nesting => 100,
38
+ :object_nl => "",
39
+ :space => "",
40
+ :space_before => "",
41
+ }) unless defined?(::JSON::SAFE_STATE_PROTOTYPE)
42
+ FAST_STATE_PROTOTYPE = Ext::Generator::State.from_state({
43
+ :allow_nan => false,
44
+ :array_nl => "",
45
+ :ascii_only => false,
46
+ :buffer_initial_length => 1024,
47
+ :depth => 0,
48
+ :indent => "",
49
+ :max_nesting => 0,
50
+ :object_nl => "",
51
+ :space => "",
52
+ :space_before => "",
53
+ }) unless defined?(::JSON::FAST_STATE_PROTOTYPE)
54
+
55
+ def self.dump_default_options
56
+ Oj::MimicDumpOption.new
57
+ end
58
+
59
+ def self.dump_default_options=(h)
60
+ m = Oj::MimicDumpOption.new
61
+ h.each do |k, v|
62
+ m[k] = v
63
+ end
64
+ end
65
+
66
+ def self.parser=(p)
67
+ @@parser = p
68
+ end
69
+
70
+ def self.parser()
71
+ @@parser
72
+ end
73
+
74
+ def self.generator=(g)
75
+ @@generator = g
76
+ end
77
+
78
+ def self.generator()
79
+ @@generator
80
+ end
81
+
82
+ module Ext
83
+ class Parser
84
+ def initialize(src)
85
+ raise TypeError.new("already initialized") unless @source.nil?
86
+
87
+ @source = src
88
+ end
89
+
90
+ def source()
91
+ raise TypeError.new("already initialized") if @source.nil?
92
+
93
+ @source
94
+ end
95
+
96
+ def parse()
97
+ raise TypeError.new("already initialized") if @source.nil?
98
+
99
+ JSON.parse(@source)
100
+ end
101
+
102
+ end # Parser
103
+ end # Ext
104
+
105
+ State = ::JSON::Ext::Generator::State unless defined?(::JSON::State)
106
+
107
+ begin
108
+ send(:remove_const, :Parser)
109
+ rescue
110
+ # ignore and move on
111
+ end
112
+ Parser = ::JSON::Ext::Parser unless defined?(::JSON::Parser)
113
+ self.parser = ::JSON::Ext::Parser
114
+ self.generator = ::JSON::Ext::Generator
115
+
116
+ # Taken directly from the json gem. Shamelessly copied. It is similar in
117
+ # some ways to the Oj::Bag class or the Oj::EasyHash class.
118
+ class GenericObject < OpenStruct
119
+ class << self
120
+ alias [] new
121
+
122
+ def json_creatable?
123
+ @json_creatable
124
+ end
125
+
126
+ attr_writer :json_creatable
127
+
128
+ def json_create(data)
129
+ data = data.dup
130
+ data.delete JSON.create_id
131
+ self[data]
132
+ end
133
+
134
+ def from_hash(object)
135
+ case
136
+ when object.respond_to?(:to_hash)
137
+ result = new
138
+ object.to_hash.each do |key, value|
139
+ result[key] = from_hash(value)
140
+ end
141
+ result
142
+ when object.respond_to?(:to_ary)
143
+ object.to_ary.map { |a| from_hash(a) }
144
+ else
145
+ object
146
+ end
147
+ end
148
+
149
+ def load(source, proc = nil, opts = {})
150
+ result = ::JSON.load(source, proc, opts.merge(:object_class => self))
151
+ result.nil? ? new : result
152
+ end
153
+
154
+ def dump(obj, *args)
155
+ ::JSON.dump(obj, *args)
156
+ end
157
+
158
+ end # self
159
+
160
+ self.json_creatable = false
161
+
162
+ def to_hash
163
+ table
164
+ end
165
+
166
+ def [](name)
167
+ __send__(name)
168
+ end unless method_defined?(:[])
169
+
170
+ def []=(name, value)
171
+ __send__("#{name}=", value)
172
+ end unless method_defined?(:[]=)
173
+
174
+ def |(other)
175
+ self.class[other.to_hash.merge(to_hash)]
176
+ end
177
+
178
+ def as_json(*)
179
+ { JSON.create_id => self.class.name }.merge to_hash
180
+ end
181
+
182
+ def to_json(*a)
183
+ as_json.to_json(*a)
184
+ end
185
+ end
186
+
187
+ end # JSON
188
+ end
data/lib/oj/mimic.rb ADDED
@@ -0,0 +1,301 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'bigdecimal'
4
+ require 'ostruct'
5
+
6
+ module Oj
7
+
8
+ ##
9
+ # Custom mode can be used to emulate the compat mode with some minor
10
+ # differences. These are the options that setup the custom mode to be like
11
+ # the compat mode.
12
+ CUSTOM_MIMIC_JSON_OPTIONS = {
13
+ allow_gc: true,
14
+ allow_invalid_unicode: false,
15
+ allow_nan: false,
16
+ array_class: nil,
17
+ array_nl: nil,
18
+ auto_define: false,
19
+ bigdecimal_as_decimal: false,
20
+ bigdecimal_load: :auto,
21
+ circular: false,
22
+ class_cache: false,
23
+ cache_keys: true,
24
+ cache_str: 5,
25
+ create_additions: false,
26
+ create_id: "json_class",
27
+ empty_string: false,
28
+ escape_mode: :unicode_xss,
29
+ float_precision: 0,
30
+ hash_class: nil,
31
+ ignore: nil,
32
+ ignore_under: false,
33
+ indent: 0,
34
+ integer_range: nil,
35
+ mode: :custom,
36
+ nan: :raise,
37
+ nilnil: false,
38
+ object_nl: nil,
39
+ omit_nil: false,
40
+ quirks_mode: true,
41
+ safe: false,
42
+ second_precision: 3,
43
+ space: nil,
44
+ space_before: nil,
45
+ symbol_keys: false,
46
+ time_format: :ruby,
47
+ trace: false,
48
+ use_as_json: false,
49
+ use_raw_json: false,
50
+ use_to_hash: false,
51
+ use_to_json: true,
52
+ }
53
+
54
+ # A bit hack-ish but does the trick. The JSON.dump_default_options is a Hash
55
+ # but in mimic we use a C struct to store defaults. This class creates a view
56
+ # onto that struct.
57
+ class MimicDumpOption < Hash
58
+ def initialize()
59
+ oo = Oj.default_options
60
+ self.store(:max_nesting, false)
61
+ self.store(:allow_nan, true)
62
+ self.store(:quirks_mode, oo[:quirks_mode])
63
+ self.store(:ascii_only, (:ascii == oo[:escape_mode]))
64
+
65
+ super
66
+ end
67
+
68
+ def []=(key, value)
69
+ case key
70
+ when :quirks_mode
71
+ Oj.default_options = {:quirks_mode => value}
72
+ when :ascii_only
73
+ Oj.default_options = {:ascii_only => value}
74
+ end
75
+ end
76
+ end
77
+
78
+ # Loads mimic-ed JSON paths. Used by Oj.mimic_JSON().
79
+ # @param mimic_paths [Array] additional paths to add to the Ruby loaded features.
80
+ def self.mimic_loaded(mimic_paths=[])
81
+ $LOAD_PATH.each do |d|
82
+ next unless File.exist?(d)
83
+
84
+ jfile = File.join(d, 'json.rb')
85
+ $LOADED_FEATURES << jfile unless $LOADED_FEATURES.include?(jfile) if File.exist?(jfile)
86
+
87
+ Dir.glob(File.join(d, 'json', '**', '*.rb')).each do |file|
88
+ # allow json/add/xxx to be loaded. User can override with Oj.add_to_json(xxx).
89
+ $LOADED_FEATURES << file unless $LOADED_FEATURES.include?(file) unless file.include?('add')
90
+ end
91
+ end
92
+ mimic_paths.each { |p| $LOADED_FEATURES << p }
93
+ $LOADED_FEATURES << 'json' unless $LOADED_FEATURES.include?('json')
94
+
95
+ require 'oj_windows/json'
96
+
97
+ if Object.const_defined?('OpenStruct')
98
+ OpenStruct.class_eval do
99
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
100
+ unless defined?(self.as_json)
101
+ def as_json(*)
102
+ name = self.class.name.to_s
103
+ raise JSON::JSONError, "Only named structs are supported!" if 0 == name.length
104
+
105
+ { JSON.create_id => name, 't' => table }
106
+ end
107
+ end
108
+ def self.json_create(h)
109
+ new(h['t'] || h[:t])
110
+ end
111
+ end
112
+ end
113
+
114
+ BigDecimal.class_eval do
115
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
116
+ unless defined?(self.as_json)
117
+ def as_json(*)
118
+ {JSON.create_id => 'BigDecimal', 'b' => _dump }
119
+ end
120
+ end
121
+ def self.json_create(h)
122
+ BigDecimal._load(h['b'])
123
+ end
124
+ end
125
+
126
+ Complex.class_eval do
127
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
128
+ unless defined?(self.as_json)
129
+ def as_json(*)
130
+ {JSON.create_id => 'Complex', 'r' => real, 'i' => imag }
131
+ end
132
+ end
133
+ def self.json_create(h)
134
+ Complex(h['r'], h['i'])
135
+ end
136
+ end
137
+
138
+ DateTime.class_eval do
139
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
140
+ unless defined?(self.as_json)
141
+ def as_json(*)
142
+ { JSON.create_id => 'DateTime',
143
+ 'y' => year,
144
+ 'm' => month,
145
+ 'd' => day,
146
+ 'H' => hour,
147
+ 'M' => min,
148
+ 'S' => sec,
149
+ 'of' => offset.to_s,
150
+ 'sg' => start }
151
+ end
152
+ end
153
+ def self.json_create(h)
154
+ # offset is a rational as a string
155
+ as, bs = h['of'].split('/')
156
+ a = as.to_i
157
+ b = bs.to_i
158
+ if 0 == b
159
+ off = a
160
+ else
161
+ off = Rational(a, b)
162
+ end
163
+ civil(h['y'], h['m'], h['d'], h['H'], h['M'], h['S'], off, h['sg'])
164
+ end
165
+ end
166
+
167
+ Date.class_eval do
168
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
169
+ unless defined?(self.as_json)
170
+ def as_json(*)
171
+ { JSON.create_id => 'Date', 'y' => year, 'm' => month, 'd' => day, 'sg' => start }
172
+ end
173
+ end
174
+ def self.json_create(h)
175
+ civil(h['y'], h['m'], h['d'], h['sg'])
176
+ end
177
+ end
178
+
179
+ Exception.class_eval do
180
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
181
+ unless defined?(self.as_json)
182
+ def as_json(*)
183
+ {JSON.create_id => self.class.name, 'm' => message, 'b' => backtrace }
184
+ end
185
+ end
186
+ def self.json_create(h)
187
+ e = new(h['m'])
188
+ e.set_backtrace(h['b'])
189
+ e
190
+ end
191
+ end
192
+
193
+ Range.class_eval do
194
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
195
+ unless defined?(self.as_json)
196
+ def as_json(*)
197
+ {JSON.create_id => 'Range', 'a' => [first, last, exclude_end?]}
198
+ end
199
+ end
200
+ def self.json_create(h)
201
+ new(*h['a'])
202
+ end
203
+ end
204
+
205
+ Rational.class_eval do
206
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
207
+ unless defined?(self.as_json)
208
+ def as_json(*)
209
+ {JSON.create_id => 'Rational', 'n' => numerator, 'd' => denominator }
210
+ end
211
+ end
212
+ def self.json_create(h)
213
+ Rational(h['n'], h['d'])
214
+ end
215
+ end
216
+
217
+ Regexp.class_eval do
218
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
219
+ unless defined?(self.as_json)
220
+ def as_json(*)
221
+ {JSON.create_id => 'Regexp', 'o' => options, 's' => source }
222
+ end
223
+ end
224
+ def self.json_create(h)
225
+ new(h['s'], h['o'])
226
+ end
227
+ end
228
+
229
+ Struct.class_eval do
230
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
231
+ unless defined?(self.as_json)
232
+ def as_json(*)
233
+ name = self.class.name.to_s
234
+ raise JSON::JSONError, "Only named structs are supported!" if 0 == name.length
235
+
236
+ { JSON.create_id => name, 'v' => values }
237
+ end
238
+ end
239
+ def self.json_create(h)
240
+ new(*h['v'])
241
+ end
242
+ end
243
+
244
+ Symbol.class_eval do
245
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
246
+ unless defined?(self.as_json)
247
+ def as_json(*)
248
+ {JSON.create_id => 'Symbol', 's' => to_s }
249
+ end
250
+ end
251
+ def self.json_create(h)
252
+ h['s'].to_sym
253
+ end
254
+ end
255
+
256
+ Time.class_eval do
257
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
258
+ unless defined?(self.as_json)
259
+ def as_json(*)
260
+ nsecs = [ tv_usec * 1000 ]
261
+ nsecs << tv_nsec if respond_to?(:tv_nsec)
262
+ nsecs = nsecs.max
263
+ { JSON.create_id => 'Time', 's' => tv_sec, 'n' => nsecs }
264
+ end
265
+ end
266
+ def self.json_create(h)
267
+ if (usec = h.delete('u'))
268
+ h['n'] = usec * 1000
269
+ end
270
+ if instance_methods.include?(:tv_nsec)
271
+ at(h['s'], Rational(h['n'], 1000))
272
+ else
273
+ at(h['s'], h['n'] / 1000)
274
+ end
275
+ end
276
+ end
277
+ end # self.mimic_loaded
278
+
279
+ end # Oj
280
+
281
+ # More monkey patches.
282
+ class String
283
+ def to_json_raw_object
284
+ {
285
+ JSON.create_id => self.class.name,
286
+ 'raw' => self.bytes
287
+ }
288
+ end
289
+ def to_json_raw(*)
290
+ to_json_raw_object().to_json()
291
+ end
292
+ def self.json_create(obj)
293
+ s = ''
294
+ s.encode!(Encoding::ASCII_8BIT) if s.respond_to?(:encode!)
295
+ raw = obj['raw']
296
+ if raw.is_a? Array
297
+ raw.each { |v| s << v }
298
+ end
299
+ s
300
+ end
301
+ end
data/lib/oj/saj.rb ADDED
@@ -0,0 +1,80 @@
1
+ module Oj
2
+ # A SAX style parse handler for JSON hence the acronym SAJ for Simple API
3
+ # for JSON. The Oj::Saj handler class can be subclassed and then used with
4
+ # the Oj::Saj key_parse() method or with the more resent
5
+ # Oj::Parser.new(:saj). The Saj methods will then be called as the file is
6
+ # parsed.
7
+ #
8
+ # With Oj::Parser.new(:saj) each method can also include a line and column
9
+ # argument so hash_start(key) could also be hash_start(key, line,
10
+ # column). The error() method is no used with Oj::Parser.new(:saj) so it
11
+ # will never be called.
12
+ #
13
+ # @example
14
+ #
15
+ # require 'oj'
16
+ #
17
+ # class MySaj < ::Oj::Saj
18
+ # def initialize()
19
+ # @hash_cnt = 0
20
+ # end
21
+ #
22
+ # def hash_start(key)
23
+ # @hash_cnt += 1
24
+ # end
25
+ # end
26
+ #
27
+ # cnt = MySaj.new()
28
+ # File.open('any.json', 'r') do |f|
29
+ # Oj.saj_parse(cnt, f)
30
+ # end
31
+ #
32
+ # or
33
+ #
34
+ # p = Oj::Parser.new(:saj)
35
+ # p.handler = MySaj.new()
36
+ # File.open('any.json', 'r') do |f|
37
+ # p.parse(f.read)
38
+ # end
39
+ #
40
+ # To make the desired methods active while parsing the desired method should
41
+ # be made public in the subclasses. If the methods remain private they will
42
+ # not be called during parsing.
43
+ #
44
+ # def hash_start(key); end
45
+ # def hash_end(key); end
46
+ # def array_start(key); end
47
+ # def array_end(key); end
48
+ # def add_value(value, key); end
49
+ # def error(message, line, column); end
50
+ #
51
+ class Saj
52
+ # Create a new instance of the Saj handler class.
53
+ def initialize()
54
+ end
55
+
56
+ # To make the desired methods active while parsing the desired method should
57
+ # be made public in the subclasses. If the methods remain private they will
58
+ # not be called during parsing.
59
+ private
60
+
61
+ def hash_start(key)
62
+ end
63
+
64
+ def hash_end(key)
65
+ end
66
+
67
+ def array_start(key)
68
+ end
69
+
70
+ def array_end(key)
71
+ end
72
+
73
+ def add_value(value, key)
74
+ end
75
+
76
+ def error(message, line, column)
77
+ end
78
+
79
+ end # Saj
80
+ end # Oj