oj 2.18.5 → 3.0.0

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 (111) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +33 -226
  3. data/ext/oj/circarray.c +0 -25
  4. data/ext/oj/circarray.h +0 -25
  5. data/ext/oj/code.c +227 -0
  6. data/ext/oj/code.h +40 -0
  7. data/ext/oj/compat.c +126 -38
  8. data/ext/oj/custom.c +1097 -0
  9. data/ext/oj/dump.c +658 -2376
  10. data/ext/oj/dump.h +92 -0
  11. data/ext/oj/dump_compat.c +937 -0
  12. data/ext/oj/dump_leaf.c +254 -0
  13. data/ext/oj/dump_object.c +810 -0
  14. data/ext/oj/dump_rails.c +329 -0
  15. data/ext/oj/dump_strict.c +416 -0
  16. data/ext/oj/err.c +0 -25
  17. data/ext/oj/err.h +8 -2
  18. data/ext/oj/fast.c +24 -24
  19. data/ext/oj/mimic_json.c +817 -0
  20. data/ext/oj/mimic_rails.c +806 -0
  21. data/ext/oj/mimic_rails.h +17 -0
  22. data/ext/oj/object.c +18 -72
  23. data/ext/oj/odd.c +0 -25
  24. data/ext/oj/odd.h +2 -27
  25. data/ext/oj/oj.c +655 -1503
  26. data/ext/oj/oj.h +93 -40
  27. data/ext/oj/parse.c +99 -46
  28. data/ext/oj/parse.h +12 -26
  29. data/ext/oj/reader.c +1 -25
  30. data/ext/oj/reader.h +3 -25
  31. data/ext/oj/resolve.c +9 -11
  32. data/ext/oj/resolve.h +2 -2
  33. data/ext/oj/rxclass.c +133 -0
  34. data/ext/oj/rxclass.h +27 -0
  35. data/ext/oj/saj.c +4 -25
  36. data/ext/oj/scp.c +3 -25
  37. data/ext/oj/sparse.c +89 -13
  38. data/ext/oj/stream_writer.c +301 -0
  39. data/ext/oj/strict.c +4 -27
  40. data/ext/oj/string_writer.c +480 -0
  41. data/ext/oj/val_stack.h +6 -2
  42. data/lib/oj.rb +1 -23
  43. data/lib/oj/easy_hash.rb +12 -4
  44. data/lib/oj/json.rb +172 -0
  45. data/lib/oj/mimic.rb +123 -18
  46. data/lib/oj/state.rb +131 -0
  47. data/lib/oj/version.rb +1 -1
  48. data/pages/Advanced.md +22 -0
  49. data/pages/Compatibility.md +25 -0
  50. data/pages/Custom.md +23 -0
  51. data/pages/Encoding.md +65 -0
  52. data/pages/JsonGem.md +79 -0
  53. data/pages/Modes.md +140 -0
  54. data/pages/Options.md +250 -0
  55. data/pages/Rails.md +60 -0
  56. data/pages/Security.md +20 -0
  57. data/test/activesupport4/decoding_test.rb +105 -0
  58. data/test/activesupport4/encoding_test.rb +531 -0
  59. data/test/activesupport4/test_helper.rb +41 -0
  60. data/test/activesupport5/decoding_test.rb +125 -0
  61. data/test/activesupport5/encoding_test.rb +483 -0
  62. data/test/activesupport5/encoding_test_cases.rb +90 -0
  63. data/test/activesupport5/test_helper.rb +50 -0
  64. data/test/activesupport5/time_zone_test_helpers.rb +24 -0
  65. data/test/json_gem/json_addition_test.rb +216 -0
  66. data/test/json_gem/json_common_interface_test.rb +143 -0
  67. data/test/json_gem/json_encoding_test.rb +109 -0
  68. data/test/json_gem/json_ext_parser_test.rb +20 -0
  69. data/test/json_gem/json_fixtures_test.rb +35 -0
  70. data/test/json_gem/json_generator_test.rb +383 -0
  71. data/test/json_gem/json_generic_object_test.rb +90 -0
  72. data/test/json_gem/json_parser_test.rb +470 -0
  73. data/test/json_gem/json_string_matching_test.rb +42 -0
  74. data/test/json_gem/test_helper.rb +18 -0
  75. data/test/perf_compat.rb +30 -28
  76. data/test/perf_object.rb +1 -1
  77. data/test/perf_strict.rb +18 -1
  78. data/test/sample.rb +0 -1
  79. data/test/test_compat.rb +169 -93
  80. data/test/test_custom.rb +355 -0
  81. data/test/test_file.rb +0 -8
  82. data/test/test_null.rb +376 -0
  83. data/test/test_object.rb +268 -3
  84. data/test/test_scp.rb +22 -1
  85. data/test/test_strict.rb +160 -4
  86. data/test/test_various.rb +52 -620
  87. data/test/tests.rb +14 -0
  88. data/test/tests_mimic.rb +14 -0
  89. data/test/tests_mimic_addition.rb +7 -0
  90. metadata +89 -47
  91. data/test/activesupport_datetime_test.rb +0 -23
  92. data/test/bug.rb +0 -51
  93. data/test/bug2.rb +0 -10
  94. data/test/bug3.rb +0 -46
  95. data/test/bug_fast.rb +0 -32
  96. data/test/bug_load.rb +0 -24
  97. data/test/crash.rb +0 -111
  98. data/test/curl/curl_oj.rb +0 -46
  99. data/test/curl/get_oj.rb +0 -24
  100. data/test/curl/just_curl.rb +0 -31
  101. data/test/curl/just_oj.rb +0 -51
  102. data/test/example.rb +0 -11
  103. data/test/foo.rb +0 -24
  104. data/test/io.rb +0 -48
  105. data/test/isolated/test_mimic_rails_datetime.rb +0 -27
  106. data/test/mod.rb +0 -16
  107. data/test/rails.rb +0 -50
  108. data/test/russian.rb +0 -18
  109. data/test/struct.rb +0 -29
  110. data/test/test_serializer.rb +0 -59
  111. data/test/write_timebars.rb +0 -31
@@ -58,7 +58,10 @@ typedef struct _Val {
58
58
  char karray[32];
59
59
  volatile VALUE key_val;
60
60
  union {
61
- const char *classname;
61
+ struct {
62
+ const char *classname;
63
+ VALUE clas;
64
+ };
62
65
  OddArgs odd_args;
63
66
  };
64
67
  uint16_t klen;
@@ -127,7 +130,8 @@ stack_push(ValStack stack, VALUE val, ValNext next) {
127
130
  }
128
131
  stack->tail->val = val;
129
132
  stack->tail->next = next;
130
- stack->tail->classname = 0;
133
+ stack->tail->classname = NULL;
134
+ stack->tail->clas = Qundef;
131
135
  stack->tail->key = 0;
132
136
  stack->tail->key_val = Qundef;
133
137
  stack->tail->clen = 0;
data/lib/oj.rb CHANGED
@@ -1,26 +1,4 @@
1
- # Optimized JSON (Oj), as the name implies was written to provide speed
2
- # optimized JSON handling.
3
- #
4
- # Oj has several dump or serialization modes which control how Objects are
5
- # converted to JSON. These modes are set with the :mode option in either the
6
- # default options or as one of the options to the dump() method.
7
- #
8
- # - :strict mode will only allow the 7 basic JSON types to be serialized. Any other Object
9
- # will raise and Exception.
10
- #
11
- # - :null mode replaces any Object that is not one of the JSON types is replaced by a JSON null.
12
- #
13
- # - :object mode will dump any Object as a JSON Object with keys that match
14
- # the Ruby Object's variable names without the '@' character. This is the
15
- # highest performance mode.
16
- #
17
- # - :compat mode is is the compatible with other systems. It will serialize
18
- # any Object but will check to see if the Object implements a to_hash() or
19
- # to_json() method. If either exists that method is used for serializing the
20
- # Object. The to_hash() is more flexible and produces more consistent output
21
- # so it has a preference over the to_json() method. If neither the to_json()
22
- # or to_hash() methods exist then the Oj internal Object variable encoding
23
- # is used.
1
+
24
2
  module Oj
25
3
  end
26
4
 
@@ -33,10 +33,18 @@ module Oj
33
33
  # @raise [ArgumentError] if an argument is given. Zero arguments expected.
34
34
  # @raise [NoMethodError] if the instance variable is not defined.
35
35
  def method_missing(m, *args, &block)
36
- raise ArgumentError.new("wrong number of arguments (#{args.size} for 0 with #{m}) to method #{m}") unless args.nil? or args.empty?
37
- return fetch(m, nil) if has_key?(m)
38
- return fetch(m.to_s, nil) if has_key?(m.to_s)
39
- return fetch(m.to_sym, nil) if has_key?(m.to_sym)
36
+ if m.to_s.end_with?('=')
37
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 1 with #{m}) to method #{m}") if args.nil? or 1 != args.length
38
+ m = m[0..-2]
39
+ return store(m.to_s, args[0]) if has_key?(m.to_s)
40
+ return store(m.to_sym, args[0]) if has_key?(m.to_sym)
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
40
48
  raise NoMethodError.new("undefined method #{m}", m)
41
49
  end
42
50
 
@@ -0,0 +1,172 @@
1
+
2
+ require 'ostruct'
3
+ require 'oj/state'
4
+
5
+ module JSON
6
+ NaN = 0.0/0.0 unless defined?(::JSON::NaN)
7
+ Infinity = 1.0/0.0 unless defined?(::JSON::Infinity)
8
+ MinusInfinity = -1.0/0.0 unless defined?(::JSON::MinusInfinity)
9
+ # Taken from the unit test. Note that items like check_circular? are not
10
+ # present.
11
+ PRETTY_STATE_PROTOTYPE = Ext::Generator::State.from_state({
12
+ :allow_nan => false,
13
+ :array_nl => "\n",
14
+ :ascii_only => false,
15
+ :buffer_initial_length => 1024,
16
+ :depth => 0,
17
+ :indent => " ",
18
+ :max_nesting => 100,
19
+ :object_nl => "\n",
20
+ :space => " ",
21
+ :space_before => "",
22
+ }) unless defined?(::JSON::PRETTY_STATE_PROTOTYPE)
23
+ SAFE_STATE_PROTOTYPE = Ext::Generator::State.from_state({
24
+ :allow_nan => false,
25
+ :array_nl => "",
26
+ :ascii_only => false,
27
+ :buffer_initial_length => 1024,
28
+ :depth => 0,
29
+ :indent => "",
30
+ :max_nesting => 100,
31
+ :object_nl => "",
32
+ :space => "",
33
+ :space_before => "",
34
+ }) unless defined?(::JSON::SAFE_STATE_PROTOTYPE)
35
+ FAST_STATE_PROTOTYPE = Ext::Generator::State.from_state({
36
+ :allow_nan => false,
37
+ :array_nl => "",
38
+ :ascii_only => false,
39
+ :buffer_initial_length => 1024,
40
+ :depth => 0,
41
+ :indent => "",
42
+ :max_nesting => 0,
43
+ :object_nl => "",
44
+ :space => "",
45
+ :space_before => "",
46
+ }) unless defined?(::JSON::FAST_STATE_PROTOTYPE)
47
+
48
+ def self.dump_default_options
49
+ Oj::MimicDumpOption.new
50
+ end
51
+
52
+ def self.dump_default_options=(h)
53
+ m = Oj::MimicDumpOption.new
54
+ h.each do |k,v|
55
+ m[k] = v
56
+ end
57
+ end
58
+
59
+ def self.parser=(p)
60
+ @@parser = p
61
+ end
62
+
63
+ def self.parser()
64
+ @@parser
65
+ end
66
+
67
+ def self.generator=(g)
68
+ @@generator = g
69
+ end
70
+
71
+ def self.generator()
72
+ @@generator
73
+ end
74
+
75
+ module Ext
76
+ class Parser
77
+ def initialize(src)
78
+ raise TypeError.new("already initialized") unless @source.nil?
79
+ @source = src
80
+ end
81
+
82
+ def source()
83
+ raise TypeError.new("already initialized") if @source.nil?
84
+ @source
85
+ end
86
+
87
+ def parse()
88
+ raise TypeError.new("already initialized") if @source.nil?
89
+ JSON.parse(@source)
90
+ end
91
+
92
+ end # Parser
93
+ end # Ext
94
+
95
+ State = ::JSON::Ext::Generator::State
96
+
97
+ Parser = ::JSON::Ext::Parser
98
+ self.parser = ::JSON::Ext::Parser
99
+ self.generator = ::JSON::Ext::Generator
100
+
101
+ # Taken directly from the json gem. Shamelessly copied. It is similar in
102
+ # some ways to the Oj::Bag class or the Oj::EasyHash class.
103
+ class GenericObject < OpenStruct
104
+ class << self
105
+ alias [] new
106
+
107
+ def json_creatable?
108
+ @json_creatable
109
+ end
110
+
111
+ attr_writer :json_creatable
112
+
113
+ def json_create(data)
114
+ data = data.dup
115
+ data.delete JSON.create_id
116
+ self[data]
117
+ end
118
+
119
+ def from_hash(object)
120
+ case
121
+ when object.respond_to?(:to_hash)
122
+ result = new
123
+ object.to_hash.each do |key, value|
124
+ result[key] = from_hash(value)
125
+ end
126
+ result
127
+ when object.respond_to?(:to_ary)
128
+ object.to_ary.map { |a| from_hash(a) }
129
+ else
130
+ object
131
+ end
132
+ end
133
+
134
+ def load(source, proc = nil, opts = {})
135
+ result = ::JSON.load(source, proc, opts.merge(:object_class => self))
136
+ result.nil? ? new : result
137
+ end
138
+
139
+ def dump(obj, *args)
140
+ ::JSON.dump(obj, *args)
141
+ end
142
+
143
+ end # self
144
+
145
+ self.json_creatable = false
146
+
147
+ def to_hash
148
+ table
149
+ end
150
+
151
+ def [](name)
152
+ __send__(name)
153
+ end unless method_defined?(:[])
154
+
155
+ def []=(name, value)
156
+ __send__("#{name}=", value)
157
+ end unless method_defined?(:[]=)
158
+
159
+ def |(other)
160
+ self.class[other.to_hash.merge(to_hash)]
161
+ end
162
+
163
+ def as_json(*)
164
+ { JSON.create_id => self.class.name }.merge to_hash
165
+ end
166
+
167
+ def to_json(*a)
168
+ as_json.to_json(*a)
169
+ end
170
+ end
171
+
172
+ end # JSON
@@ -1,4 +1,5 @@
1
1
 
2
+ require 'bigdecimal'
2
3
  begin
3
4
  require 'ostruct'
4
5
  rescue Exception
@@ -29,6 +30,8 @@ module Oj
29
30
  end
30
31
  end
31
32
 
33
+ # Loads mimic-ed JSON paths. Used by Oj.mimic_JSON().
34
+ # @param mimic_path [Array] additional paths to add to the Ruby loaded features.
32
35
  def self.mimic_loaded(mimic_paths=[])
33
36
  $LOAD_PATH.each do |d|
34
37
  next unless File.exist?(d)
@@ -37,12 +40,15 @@ module Oj
37
40
  $LOADED_FEATURES << jfile unless $LOADED_FEATURES.include?(jfile) if File.exist?(jfile)
38
41
 
39
42
  Dir.glob(File.join(d, 'json', '**', '*.rb')).each do |file|
40
- $LOADED_FEATURES << file unless $LOADED_FEATURES.include?(file)
43
+ # allow json/add/xxx to be loaded. User can override with Oj.add_to_json(xxx).
44
+ $LOADED_FEATURES << file unless $LOADED_FEATURES.include?(file) unless file.include?('add')
41
45
  end
42
46
  end
43
47
  mimic_paths.each { |p| $LOADED_FEATURES << p }
44
48
  $LOADED_FEATURES << 'json' unless $LOADED_FEATURES.include?('json')
45
49
 
50
+ require 'oj/json'
51
+
46
52
  if Object.const_defined?('OpenStruct')
47
53
  OpenStruct.class_eval do
48
54
  # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
@@ -54,9 +60,100 @@ module Oj
54
60
  end
55
61
  end
56
62
  def self.json_create(h)
57
- new(h['t'])
63
+ new(h['t'] || h[:t])
64
+ end
65
+ end
66
+ end
67
+
68
+ BigDecimal.class_eval do
69
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
70
+ unless defined?(self.as_json)
71
+ def as_json(*)
72
+ {JSON.create_id => 'BigDecimal', 'b' => _dump }
73
+ end
74
+ end
75
+ def self.json_create(h)
76
+ BigDecimal._load(h['b'])
77
+ end
78
+ end
79
+
80
+ Complex.class_eval do
81
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
82
+ unless defined?(self.as_json)
83
+ def as_json(*)
84
+ {JSON.create_id => 'Complex', 'r' => real, 'i' => imag }
85
+ end
86
+ end
87
+ def self.json_create(h)
88
+ Complex(h['r'], h['i'])
89
+ end
90
+ end
91
+
92
+ Date.class_eval do
93
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
94
+ unless defined?(self.as_json)
95
+ def as_json(*)
96
+ { JSON.create_id => 'Date', 'y' => year, 'm' => month, 'd' => day, 'sg' => start }
97
+ end
98
+ end
99
+ def self.json_create(h)
100
+ civil(h['y'], h['m'], h['d'], h['sg'])
101
+ end
102
+ end
103
+
104
+ DateTime.class_eval do
105
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
106
+ unless defined?(self.as_json)
107
+ def as_json(*)
108
+ { JSON.create_id => 'DateTime',
109
+ 'y' => year,
110
+ 'm' => month,
111
+ 'd' => day,
112
+ 'H' => hour,
113
+ 'M' => min,
114
+ 'S' => sec,
115
+ 'of' => offset.to_s,
116
+ 'sg' => start }
58
117
  end
59
118
  end
119
+ def self.json_create(h)
120
+ # offset is a rational as a string
121
+ as, bs = h['of'].split('/')
122
+ a = as.to_i
123
+ b = bs.to_i
124
+ if 0 == b
125
+ off = a
126
+ else
127
+ off = Rational(a, b)
128
+ end
129
+ civil(h['y'], h['m'], h['d'], h['H'], h['M'], h['S'], off, h['sg'])
130
+ end
131
+ end
132
+
133
+ Date.class_eval do
134
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
135
+ unless defined?(self.as_json)
136
+ def as_json(*)
137
+ { JSON.create_id => 'Date', 'y' => year, 'm' => month, 'd' => day, 'sg' => start }
138
+ end
139
+ end
140
+ def self.json_create(h)
141
+ civil(h['y'], h['m'], h['d'], h['sg'])
142
+ end
143
+ end
144
+
145
+ Exception.class_eval do
146
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
147
+ unless defined?(self.as_json)
148
+ def as_json(*)
149
+ {JSON.create_id => self.class.name, 'm' => message, 'b' => backtrace }
150
+ end
151
+ end
152
+ def self.json_create(h)
153
+ e = new(h['m'])
154
+ e.set_backtrace(h['b'])
155
+ e
156
+ end
60
157
  end
61
158
 
62
159
  Range.class_eval do
@@ -67,7 +164,7 @@ module Oj
67
164
  end
68
165
  end
69
166
  def self.json_create(h)
70
- new(h['a'])
167
+ new(*h['a'])
71
168
  end
72
169
  end
73
170
 
@@ -105,7 +202,7 @@ module Oj
105
202
  end
106
203
  end
107
204
  def self.json_create(h)
108
- new(h['v'])
205
+ new(*h['v'])
109
206
  end
110
207
  end
111
208
 
@@ -125,7 +222,6 @@ module Oj
125
222
  # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
126
223
  unless defined?(self.as_json)
127
224
  def as_json(*)
128
- {JSON.create_id => 'Symbol', 's' => to_s }
129
225
  nsecs = [ tv_usec * 1000 ]
130
226
  nsecs << tv_nsec if respond_to?(:tv_nsec)
131
227
  nsecs = nsecs.max
@@ -144,19 +240,28 @@ module Oj
144
240
  end
145
241
  end
146
242
 
147
- JSON.module_eval do
148
- def self.dump_default_options
149
- Oj::MimicDumpOption.new
150
- end
151
-
152
- def self.dump_default_options=(h)
153
- m = Oj::MimicDumpOption.new
154
- h.each do |k,v|
155
- m[k] = v
156
- end
157
- end
158
- end
159
-
160
243
  end # self.mimic_loaded
161
244
 
162
245
  end # Oj
246
+
247
+ # More monkey patches.
248
+ class String
249
+ def to_json_raw_object
250
+ {
251
+ JSON.create_id => self.class.name,
252
+ 'raw' => self.bytes
253
+ }
254
+ end
255
+ def to_json_raw(*)
256
+ to_json_raw_object().to_json()
257
+ end
258
+ def self.json_create(obj)
259
+ s = ''
260
+ s.encode!(Encoding::ASCII_8BIT) if s.respond_to?(:encode!)
261
+ raw = obj['raw']
262
+ if raw.is_a? Array
263
+ raw.each { |v| s << v }
264
+ end
265
+ s
266
+ end
267
+ end
@@ -0,0 +1,131 @@
1
+
2
+ module JSON
3
+ module Ext
4
+ module Generator
5
+ unless defined?(::JSON::Ext::Generator::State)
6
+ # This class exists for json gem compatibility only. While it can be
7
+ # used as the options for other than compatibility a simple Hash is
8
+ # recommended as it is simpler and performs better. The only bit
9
+ # missing by not using a state object is the depth availability which
10
+ # may be the depth during dumping or maybe not since it can be set and
11
+ # the docs for depth= is the same as max_nesting. Note: Had to make
12
+ # this a subclass of Object instead of Hash like EashyHash due to
13
+ # conflicts with the json gem.
14
+ class State
15
+
16
+ def self.from_state(opts)
17
+ s = self.new()
18
+ s.clear()
19
+ s.merge(opts)
20
+ s
21
+ end
22
+
23
+ def initialize(opts = {})
24
+ @attrs = {}
25
+
26
+ # Populate with all vars then merge in opts. This class deviates from
27
+ # the json gem in that any of the options can be set with the opts
28
+ # argument. The json gem limits the opts use to 7 of the options.
29
+ @attrs[:indent] = ''
30
+ @attrs[:space] = ''
31
+ @attrs[:space_before] = ''
32
+ @attrs[:array_nl] = ''
33
+ @attrs[:object_nl] = ''
34
+ @attrs[:allow_nan] = false
35
+ @attrs[:buffer_initial_length] = 1024 # completely ignored by Oj
36
+ @attrs[:depth] = 0
37
+ @attrs[:max_nesting] = 100
38
+ @attrs[:check_circular?] = true
39
+ @attrs[:ascii_only] = false
40
+
41
+ @attrs.merge!(opts)
42
+ end
43
+
44
+ def to_h()
45
+ return @attrs.dup
46
+ end
47
+
48
+ def to_hash()
49
+ return @attrs.dup
50
+ end
51
+
52
+ def allow_nan?()
53
+ @attrs[:allow_nan]
54
+ end
55
+
56
+ def ascii_only?()
57
+ @attrs[:ascii_only]
58
+ end
59
+
60
+ def configure(opts)
61
+ raise TypeError.new('expected a Hash') unless opts.respond_to?(:to_h)
62
+ @attrs.merge!(opts.to_h)
63
+ end
64
+
65
+ def generate(obj)
66
+ JSON.generate(obj)
67
+ end
68
+
69
+ def merge(opts)
70
+ @attrs.merge!(opts)
71
+ end
72
+
73
+ # special rule for this.
74
+ def buffer_initial_length=(len)
75
+ len = 1024 if 0 >= len
76
+ @attrs[:buffer_initial_length] = len
77
+ end
78
+
79
+ # Replaces the Object.respond_to?() method.
80
+ # @param [Symbol] m method symbol
81
+ # @return [Boolean] true for any method that matches an instance
82
+ # variable reader, otherwise false.
83
+ def respond_to?(m)
84
+ return true if super
85
+ return true if has_key?(key)
86
+ return true if has_key?(key.to_s)
87
+ has_key?(key.to_sym)
88
+ end
89
+
90
+ def [](key)
91
+ key = key.to_sym
92
+ @attrs.fetch(key, nil)
93
+ end
94
+
95
+ def []=(key, value)
96
+ key = key.to_sym
97
+ @attrs[key] = value
98
+ end
99
+
100
+ def clear()
101
+ @attrs.clear()
102
+ end
103
+
104
+ def has_key?(k)
105
+ @attrs.has_key?(key.to_sym)
106
+ end
107
+
108
+ # Handles requests for Hash values. Others cause an Exception to be raised.
109
+ # @param [Symbol|String] m method symbol
110
+ # @return [Boolean] the value of the specified instance variable.
111
+ # @raise [ArgumentError] if an argument is given. Zero arguments expected.
112
+ # @raise [NoMethodError] if the instance variable is not defined.
113
+ def method_missing(m, *args, &block)
114
+ if m.to_s.end_with?('=')
115
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 1 with #{m}) to method #{m}") if args.nil? or 1 != args.length
116
+ m = m.to_s[0..-2]
117
+ m = m.to_sym
118
+ return @attrs.store(m, args[0])
119
+ else
120
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 0 with #{m}) to method #{m}") unless args.nil? or args.empty?
121
+ return @attrs[m.to_sym]
122
+ end
123
+ raise NoMethodError.new("undefined method #{m}", m)
124
+ end
125
+
126
+ end # State
127
+ end # defined check
128
+ end # Generator
129
+ end # Ext
130
+
131
+ end # JSON