oj 2.0.0 → 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.
- checksums.yaml +7 -0
- data/LICENSE +17 -23
- data/README.md +74 -425
- data/ext/oj/buf.h +103 -0
- data/ext/oj/cache8.c +4 -0
- data/ext/oj/circarray.c +68 -0
- data/ext/oj/circarray.h +23 -0
- data/ext/oj/code.c +227 -0
- data/ext/oj/code.h +40 -0
- data/ext/oj/compat.c +243 -0
- data/ext/oj/custom.c +1097 -0
- data/ext/oj/dump.c +766 -1534
- data/ext/oj/dump.h +92 -0
- data/ext/oj/dump_compat.c +937 -0
- data/ext/oj/dump_leaf.c +254 -0
- data/ext/oj/dump_object.c +810 -0
- data/ext/oj/dump_rails.c +329 -0
- data/ext/oj/dump_strict.c +416 -0
- data/ext/oj/encode.h +51 -0
- data/ext/oj/err.c +57 -0
- data/ext/oj/err.h +70 -0
- data/ext/oj/extconf.rb +17 -7
- data/ext/oj/fast.c +213 -180
- data/ext/oj/hash.c +163 -0
- data/ext/oj/hash.h +46 -0
- data/ext/oj/hash_test.c +512 -0
- data/ext/oj/mimic_json.c +817 -0
- data/ext/oj/mimic_rails.c +806 -0
- data/ext/oj/mimic_rails.h +17 -0
- data/ext/oj/object.c +752 -0
- data/ext/oj/odd.c +230 -0
- data/ext/oj/odd.h +44 -0
- data/ext/oj/oj.c +1288 -929
- data/ext/oj/oj.h +240 -69
- data/ext/oj/parse.c +1014 -0
- data/ext/oj/parse.h +92 -0
- data/ext/oj/reader.c +223 -0
- data/ext/oj/reader.h +151 -0
- data/ext/oj/resolve.c +127 -0
- data/ext/oj/{cache.h → resolve.h} +6 -13
- data/ext/oj/rxclass.c +133 -0
- data/ext/oj/rxclass.h +27 -0
- data/ext/oj/saj.c +77 -175
- data/ext/oj/scp.c +224 -0
- data/ext/oj/sparse.c +911 -0
- data/ext/oj/stream_writer.c +301 -0
- data/ext/oj/strict.c +162 -0
- data/ext/oj/string_writer.c +480 -0
- data/ext/oj/val_stack.c +98 -0
- data/ext/oj/val_stack.h +188 -0
- data/lib/oj/active_support_helper.rb +41 -0
- data/lib/oj/bag.rb +6 -10
- data/lib/oj/easy_hash.rb +52 -0
- data/lib/oj/json.rb +172 -0
- data/lib/oj/mimic.rb +260 -5
- data/lib/oj/saj.rb +13 -10
- data/lib/oj/schandler.rb +142 -0
- data/lib/oj/state.rb +131 -0
- data/lib/oj/version.rb +1 -1
- data/lib/oj.rb +11 -23
- data/pages/Advanced.md +22 -0
- data/pages/Compatibility.md +25 -0
- data/pages/Custom.md +23 -0
- data/pages/Encoding.md +65 -0
- data/pages/JsonGem.md +79 -0
- data/pages/Modes.md +140 -0
- data/pages/Options.md +250 -0
- data/pages/Rails.md +60 -0
- data/pages/Security.md +20 -0
- data/test/_test_active.rb +76 -0
- data/test/_test_active_mimic.rb +96 -0
- data/test/_test_mimic_rails.rb +126 -0
- data/test/activesupport4/decoding_test.rb +105 -0
- data/test/activesupport4/encoding_test.rb +531 -0
- data/test/activesupport4/test_helper.rb +41 -0
- data/test/activesupport5/decoding_test.rb +125 -0
- data/test/activesupport5/encoding_test.rb +483 -0
- data/test/activesupport5/encoding_test_cases.rb +90 -0
- data/test/activesupport5/test_helper.rb +50 -0
- data/test/activesupport5/time_zone_test_helpers.rb +24 -0
- data/test/helper.rb +27 -0
- data/test/isolated/shared.rb +310 -0
- data/test/isolated/test_mimic_after.rb +13 -0
- data/test/isolated/test_mimic_alone.rb +12 -0
- data/test/isolated/test_mimic_as_json.rb +45 -0
- data/test/isolated/test_mimic_before.rb +13 -0
- data/test/isolated/test_mimic_define.rb +28 -0
- data/test/isolated/test_mimic_rails_after.rb +22 -0
- data/test/isolated/test_mimic_rails_before.rb +21 -0
- data/test/isolated/test_mimic_redefine.rb +15 -0
- data/test/json_gem/json_addition_test.rb +216 -0
- data/test/json_gem/json_common_interface_test.rb +143 -0
- data/test/json_gem/json_encoding_test.rb +109 -0
- data/test/json_gem/json_ext_parser_test.rb +20 -0
- data/test/json_gem/json_fixtures_test.rb +35 -0
- data/test/json_gem/json_generator_test.rb +383 -0
- data/test/json_gem/json_generic_object_test.rb +90 -0
- data/test/json_gem/json_parser_test.rb +470 -0
- data/test/json_gem/json_string_matching_test.rb +42 -0
- data/test/json_gem/test_helper.rb +18 -0
- data/test/perf_compat.rb +130 -0
- data/test/perf_fast.rb +9 -9
- data/test/perf_file.rb +64 -0
- data/test/{perf_obj.rb → perf_object.rb} +24 -10
- data/test/perf_scp.rb +151 -0
- data/test/perf_strict.rb +32 -113
- data/test/sample.rb +2 -3
- data/test/test_compat.rb +474 -0
- data/test/test_custom.rb +355 -0
- data/test/test_debian.rb +53 -0
- data/test/test_fast.rb +66 -16
- data/test/test_file.rb +237 -0
- data/test/test_gc.rb +49 -0
- data/test/test_hash.rb +29 -0
- data/test/test_null.rb +376 -0
- data/test/test_object.rb +1010 -0
- data/test/test_saj.rb +16 -16
- data/test/test_scp.rb +417 -0
- data/test/test_strict.rb +410 -0
- data/test/test_various.rb +815 -0
- data/test/test_writer.rb +308 -0
- data/test/tests.rb +9 -902
- data/test/tests_mimic.rb +14 -0
- data/test/tests_mimic_addition.rb +7 -0
- metadata +253 -38
- data/ext/oj/cache.c +0 -148
- data/ext/oj/foo.rb +0 -6
- data/ext/oj/load.c +0 -1049
- data/test/a.rb +0 -38
- data/test/perf1.rb +0 -64
- data/test/perf2.rb +0 -76
- data/test/perf_obj_old.rb +0 -213
- data/test/test_mimic.rb +0 -208
data/ext/oj/val_stack.h
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/* val_stack.h
|
|
2
|
+
* Copyright (c) 2011, Peter Ohler
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
|
6
|
+
* modification, are permitted provided that the following conditions are met:
|
|
7
|
+
*
|
|
8
|
+
* - Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
* list of conditions and the following disclaimer.
|
|
10
|
+
*
|
|
11
|
+
* - Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
* this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
* and/or other materials provided with the distribution.
|
|
14
|
+
*
|
|
15
|
+
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
|
16
|
+
* used to endorse or promote products derived from this software without
|
|
17
|
+
* specific prior written permission.
|
|
18
|
+
*
|
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
#ifndef __OJ_VAL_STACK_H__
|
|
32
|
+
#define __OJ_VAL_STACK_H__
|
|
33
|
+
|
|
34
|
+
#include "ruby.h"
|
|
35
|
+
#include "odd.h"
|
|
36
|
+
#include <stdint.h>
|
|
37
|
+
#if USE_PTHREAD_MUTEX
|
|
38
|
+
#include <pthread.h>
|
|
39
|
+
#endif
|
|
40
|
+
|
|
41
|
+
#define STACK_INC 64
|
|
42
|
+
|
|
43
|
+
typedef enum {
|
|
44
|
+
NEXT_NONE = 0,
|
|
45
|
+
NEXT_ARRAY_NEW = 'a',
|
|
46
|
+
NEXT_ARRAY_ELEMENT = 'e',
|
|
47
|
+
NEXT_ARRAY_COMMA = ',',
|
|
48
|
+
NEXT_HASH_NEW = 'h',
|
|
49
|
+
NEXT_HASH_KEY = 'k',
|
|
50
|
+
NEXT_HASH_COLON = ':',
|
|
51
|
+
NEXT_HASH_VALUE = 'v',
|
|
52
|
+
NEXT_HASH_COMMA = 'n',
|
|
53
|
+
} ValNext;
|
|
54
|
+
|
|
55
|
+
typedef struct _Val {
|
|
56
|
+
volatile VALUE val;
|
|
57
|
+
const char *key;
|
|
58
|
+
char karray[32];
|
|
59
|
+
volatile VALUE key_val;
|
|
60
|
+
union {
|
|
61
|
+
struct {
|
|
62
|
+
const char *classname;
|
|
63
|
+
VALUE clas;
|
|
64
|
+
};
|
|
65
|
+
OddArgs odd_args;
|
|
66
|
+
};
|
|
67
|
+
uint16_t klen;
|
|
68
|
+
uint16_t clen;
|
|
69
|
+
char next; // ValNext
|
|
70
|
+
char k1; // first original character in the key
|
|
71
|
+
char kalloc;
|
|
72
|
+
} *Val;
|
|
73
|
+
|
|
74
|
+
typedef struct _ValStack {
|
|
75
|
+
struct _Val base[STACK_INC];
|
|
76
|
+
Val head; // current stack
|
|
77
|
+
Val end; // stack end
|
|
78
|
+
Val tail; // pointer to one past last element name on stack
|
|
79
|
+
#if USE_PTHREAD_MUTEX
|
|
80
|
+
pthread_mutex_t mutex;
|
|
81
|
+
#elif USE_RB_MUTEX
|
|
82
|
+
VALUE mutex;
|
|
83
|
+
#endif
|
|
84
|
+
|
|
85
|
+
} *ValStack;
|
|
86
|
+
|
|
87
|
+
extern VALUE oj_stack_init(ValStack stack);
|
|
88
|
+
|
|
89
|
+
inline static int
|
|
90
|
+
stack_empty(ValStack stack) {
|
|
91
|
+
return (stack->head == stack->tail);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
inline static void
|
|
95
|
+
stack_cleanup(ValStack stack) {
|
|
96
|
+
if (stack->base != stack->head) {
|
|
97
|
+
xfree(stack->head);
|
|
98
|
+
stack->head = NULL;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
inline static void
|
|
103
|
+
stack_push(ValStack stack, VALUE val, ValNext next) {
|
|
104
|
+
if (stack->end <= stack->tail) {
|
|
105
|
+
size_t len = stack->end - stack->head;
|
|
106
|
+
size_t toff = stack->tail - stack->head;
|
|
107
|
+
Val head = stack->head;
|
|
108
|
+
|
|
109
|
+
// A realloc can trigger a GC so make sure it happens outside the lock
|
|
110
|
+
// but lock before changing pointers.
|
|
111
|
+
if (stack->base == stack->head) {
|
|
112
|
+
head = ALLOC_N(struct _Val, len + STACK_INC);
|
|
113
|
+
memcpy(head, stack->base, sizeof(struct _Val) * len);
|
|
114
|
+
} else {
|
|
115
|
+
REALLOC_N(head, struct _Val, len + STACK_INC);
|
|
116
|
+
}
|
|
117
|
+
#if USE_PTHREAD_MUTEX
|
|
118
|
+
pthread_mutex_lock(&stack->mutex);
|
|
119
|
+
#elif USE_RB_MUTEX
|
|
120
|
+
rb_mutex_lock(stack->mutex);
|
|
121
|
+
#endif
|
|
122
|
+
stack->head = head;
|
|
123
|
+
stack->tail = stack->head + toff;
|
|
124
|
+
stack->end = stack->head + len + STACK_INC;
|
|
125
|
+
#if USE_PTHREAD_MUTEX
|
|
126
|
+
pthread_mutex_unlock(&stack->mutex);
|
|
127
|
+
#elif USE_RB_MUTEX
|
|
128
|
+
rb_mutex_unlock(stack->mutex);
|
|
129
|
+
#endif
|
|
130
|
+
}
|
|
131
|
+
stack->tail->val = val;
|
|
132
|
+
stack->tail->next = next;
|
|
133
|
+
stack->tail->classname = NULL;
|
|
134
|
+
stack->tail->clas = Qundef;
|
|
135
|
+
stack->tail->key = 0;
|
|
136
|
+
stack->tail->key_val = Qundef;
|
|
137
|
+
stack->tail->clen = 0;
|
|
138
|
+
stack->tail->klen = 0;
|
|
139
|
+
stack->tail->kalloc = 0;
|
|
140
|
+
stack->tail++;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
inline static size_t
|
|
144
|
+
stack_size(ValStack stack) {
|
|
145
|
+
return stack->tail - stack->head;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
inline static Val
|
|
149
|
+
stack_peek(ValStack stack) {
|
|
150
|
+
if (stack->head < stack->tail) {
|
|
151
|
+
return stack->tail - 1;
|
|
152
|
+
}
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
inline static Val
|
|
157
|
+
stack_peek_up(ValStack stack) {
|
|
158
|
+
if (stack->head < stack->tail - 1) {
|
|
159
|
+
return stack->tail - 2;
|
|
160
|
+
}
|
|
161
|
+
return 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
inline static Val
|
|
165
|
+
stack_prev(ValStack stack) {
|
|
166
|
+
return stack->tail;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
inline static VALUE
|
|
170
|
+
stack_head_val(ValStack stack) {
|
|
171
|
+
if (Qundef != stack->head->val) {
|
|
172
|
+
return stack->head->val;
|
|
173
|
+
}
|
|
174
|
+
return Qnil;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
inline static Val
|
|
178
|
+
stack_pop(ValStack stack) {
|
|
179
|
+
if (stack->head < stack->tail) {
|
|
180
|
+
stack->tail--;
|
|
181
|
+
return stack->tail;
|
|
182
|
+
}
|
|
183
|
+
return 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
extern const char* oj_stack_next_string(ValNext n);
|
|
187
|
+
|
|
188
|
+
#endif /* __OJ_VAL_STACK_H__ */
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
require 'active_support/time'
|
|
3
|
+
|
|
4
|
+
module Oj
|
|
5
|
+
|
|
6
|
+
# Exists only to handle the ActiveSupport::TimeWithZone.
|
|
7
|
+
class ActiveSupportHelper
|
|
8
|
+
|
|
9
|
+
def self.createTimeWithZone(utc, zone)
|
|
10
|
+
ActiveSupport::TimeWithZone.new(utc - utc.gmt_offset, ActiveSupport::TimeZone[zone])
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
Oj.register_odd(ActiveSupport::TimeWithZone, Oj::ActiveSupportHelper, :createTimeWithZone, :utc, 'time_zone.name')
|
|
17
|
+
|
|
18
|
+
# This is a hack to work around an oddness with DateTime and the ActiveSupport
|
|
19
|
+
# that causes a hang when some methods are called from C. Hour, min(ute),
|
|
20
|
+
# sec(ond) and other methods are special but they can be called from C until
|
|
21
|
+
# activesupport/time is required. After that they can not be even though
|
|
22
|
+
# resond_to? returns true. By defining methods to call super the problem goes
|
|
23
|
+
# away. There is obviously some magic going on under the covers that I don't
|
|
24
|
+
# understand.
|
|
25
|
+
class DateTime
|
|
26
|
+
def hour()
|
|
27
|
+
super
|
|
28
|
+
end
|
|
29
|
+
def min()
|
|
30
|
+
super
|
|
31
|
+
end
|
|
32
|
+
def sec()
|
|
33
|
+
super
|
|
34
|
+
end
|
|
35
|
+
def sec_fraction()
|
|
36
|
+
super
|
|
37
|
+
end
|
|
38
|
+
def offset()
|
|
39
|
+
super
|
|
40
|
+
end
|
|
41
|
+
end
|
data/lib/oj/bag.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Oj
|
|
|
13
13
|
# value. This is intended for testing purposes only.
|
|
14
14
|
# @example Oj::Bag.new(:@x => 42, :@y => 57)
|
|
15
15
|
# @param [Hash] args instance variable symbols and their values
|
|
16
|
-
def initialize(args={
|
|
16
|
+
def initialize(args = {})
|
|
17
17
|
args.each do |k,v|
|
|
18
18
|
self.instance_variable_set(k, v)
|
|
19
19
|
end
|
|
@@ -25,8 +25,7 @@ module Oj
|
|
|
25
25
|
# variable reader, otherwise false.
|
|
26
26
|
def respond_to?(m)
|
|
27
27
|
return true if super
|
|
28
|
-
|
|
29
|
-
instance_variables.include?(at_m)
|
|
28
|
+
instance_variables.include?(:"@#{m}")
|
|
30
29
|
end
|
|
31
30
|
|
|
32
31
|
# Handles requests for variable values. Others cause an Exception to be
|
|
@@ -37,7 +36,7 @@ module Oj
|
|
|
37
36
|
# @raise [NoMethodError] if the instance variable is not defined.
|
|
38
37
|
def method_missing(m, *args, &block)
|
|
39
38
|
raise ArgumentError.new("wrong number of arguments (#{args.size} for 0) to method #{m}") unless args.nil? or args.empty?
|
|
40
|
-
at_m =
|
|
39
|
+
at_m = :"@#{m}"
|
|
41
40
|
raise NoMethodError.new("undefined method #{m}", m) unless instance_variable_defined?(at_m)
|
|
42
41
|
instance_variable_get(at_m)
|
|
43
42
|
end
|
|
@@ -50,13 +49,10 @@ module Oj
|
|
|
50
49
|
ova = other.instance_variables
|
|
51
50
|
iv = instance_variables
|
|
52
51
|
return false if ova.size != iv.size
|
|
53
|
-
iv.
|
|
54
|
-
return false if instance_variable_get(vid) != other.instance_variable_get(vid)
|
|
55
|
-
end
|
|
56
|
-
true
|
|
52
|
+
iv.all? { |vid| instance_variable_get(vid) != other.instance_variable_get(vid) }
|
|
57
53
|
end
|
|
58
54
|
alias == eql?
|
|
59
|
-
|
|
55
|
+
|
|
60
56
|
# Define a new class based on the Oj::Bag class. This is used internally in
|
|
61
57
|
# the Oj module and is available to service wrappers that receive XML
|
|
62
58
|
# requests that include Objects of Classes not defined in the storage
|
|
@@ -66,7 +62,7 @@ module Oj
|
|
|
66
62
|
# @raise [NameError] if the classname is invalid.
|
|
67
63
|
def self.define_class(classname)
|
|
68
64
|
classname = classname.to_s unless classname.is_a?(String)
|
|
69
|
-
tokens = classname.split('::').map
|
|
65
|
+
tokens = classname.split('::').map(&:to_sym)
|
|
70
66
|
raise NameError.new("Invalid classname '#{classname}") if tokens.empty?
|
|
71
67
|
m = Object
|
|
72
68
|
tokens[0..-2].each do |sym|
|
data/lib/oj/easy_hash.rb
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
|
|
2
|
+
module Oj
|
|
3
|
+
|
|
4
|
+
# A Hash subclass that normalizes the hash keys to allow lookup by the
|
|
5
|
+
# key.to_s or key.to_sym. It also supports looking up hash values by methods
|
|
6
|
+
# that match the keys.
|
|
7
|
+
class EasyHash < Hash
|
|
8
|
+
|
|
9
|
+
# Initializes the instance to an empty Hash.
|
|
10
|
+
def initialize()
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Replaces the Object.respond_to?() method.
|
|
14
|
+
# @param [Symbol] m method symbol
|
|
15
|
+
# @return [Boolean] true for any method that matches an instance
|
|
16
|
+
# variable reader, otherwise false.
|
|
17
|
+
def respond_to?(m)
|
|
18
|
+
return true if super
|
|
19
|
+
return true if has_key?(key)
|
|
20
|
+
return true if has_key?(key.to_s)
|
|
21
|
+
has_key?(key.to_sym)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def [](key)
|
|
25
|
+
return fetch(key, nil) if has_key?(key)
|
|
26
|
+
return fetch(key.to_s, nil) if has_key?(key.to_s)
|
|
27
|
+
fetch(key.to_sym, nil)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Handles requests for Hash values. Others cause an Exception to be raised.
|
|
31
|
+
# @param [Symbol|String] m method symbol
|
|
32
|
+
# @return [Boolean] the value of the specified instance variable.
|
|
33
|
+
# @raise [ArgumentError] if an argument is given. Zero arguments expected.
|
|
34
|
+
# @raise [NoMethodError] if the instance variable is not defined.
|
|
35
|
+
def method_missing(m, *args, &block)
|
|
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
|
|
48
|
+
raise NoMethodError.new("undefined method #{m}", m)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end # EasyHash
|
|
52
|
+
end # Oj
|
data/lib/oj/json.rb
ADDED
|
@@ -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
|