oj 3.11.5 → 3.12.3
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 +4 -4
- data/README.md +5 -1
- data/ext/oj/compat.c +32 -27
- data/ext/oj/custom.c +3 -15
- data/ext/oj/dump.c +39 -42
- data/ext/oj/dump_strict.c +1 -1
- data/ext/oj/fast.c +53 -22
- data/ext/oj/hash.c +41 -4
- data/ext/oj/hash.h +2 -0
- data/ext/oj/mimic_json.c +15 -13
- data/ext/oj/object.c +33 -5
- data/ext/oj/oj.c +116 -33
- data/ext/oj/oj.h +3 -1
- data/ext/oj/parse.c +1 -1
- data/ext/oj/parse.h +3 -0
- data/ext/oj/rails.c +2 -1
- data/ext/oj/scp.c +4 -16
- data/ext/oj/strict.c +67 -22
- data/ext/oj/wab.c +35 -18
- data/lib/oj/mimic.rb +2 -0
- data/lib/oj/version.rb +1 -1
- data/pages/Modes.md +2 -0
- data/pages/Options.md +23 -5
- data/test/foo.rb +2 -44
- data/test/perf.rb +1 -1
- data/test/perf_scp.rb +11 -10
- data/test/perf_strict.rb +17 -23
- data/test/test_fast.rb +32 -2
- data/test/test_various.rb +2 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 125ec67a260b09db65d47add3487d46c55ee805ebaa721d3bf841ef27fe3ade7
|
4
|
+
data.tar.gz: a1cd38c40217e8c5ffd24f8759ff00f0d6770dcab56a736bd0c4ba52d5f3a03a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63496098643062caf40131db78e9ef1ccd75f9fd56f32e49538ccb6e005a42dcc86198d202562edc0b149b7ee649492376584d21554423846ac078efec700899
|
7
|
+
data.tar.gz: 9d619857d1f9f217d5e7c27c8a999013516680de8e28bc835ee2e267e60eee5dacde1a69e2de694d99d8caf21eb7e5c0c5a51ab9407d03b509423af894913985
|
data/README.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# [](http://www.ohler.com/oj) gem
|
2
2
|
|
3
|
-
[](https://github.com/ohler55/oj/actions/workflows/CI.yml)
|
4
|
+

|
5
|
+

|
6
|
+
[](https://dependabot.com/compatibility-score.html?dependency-name=oj&package-manager=bundler&version-scheme=semver)
|
7
|
+
[](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
|
4
8
|
|
5
9
|
A *fast* JSON parser and Object marshaller as a Ruby gem.
|
6
10
|
|
data/ext/oj/compat.c
CHANGED
@@ -23,14 +23,34 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
|
|
23
23
|
parent->classname = oj_strndup(str, len);
|
24
24
|
parent->clen = len;
|
25
25
|
} else {
|
26
|
-
volatile VALUE rstr =
|
26
|
+
volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
27
27
|
|
28
28
|
if (Qundef == rkey) {
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
if (Yes != pi->options.cache_keys) {
|
30
|
+
rkey = rb_str_new(key, klen);
|
31
|
+
rkey = oj_encode(rkey);
|
32
|
+
if (Yes == pi->options.sym_key) {
|
33
|
+
rkey = rb_str_intern(rkey);
|
34
|
+
}
|
35
|
+
} else {
|
36
|
+
VALUE *slot;
|
37
|
+
|
38
|
+
if (Yes == pi->options.sym_key) {
|
39
|
+
if (Qnil == (rkey = oj_sym_hash_get(key, klen, &slot))) {
|
40
|
+
rkey = rb_str_new(key, klen);
|
41
|
+
rkey = oj_encode(rkey);
|
42
|
+
rkey = rb_str_intern(rkey);
|
43
|
+
*slot = rkey;
|
44
|
+
rb_gc_register_address(slot);
|
45
|
+
}
|
46
|
+
} else {
|
47
|
+
if (Qnil == (rkey = oj_str_hash_get(key, klen, &slot))) {
|
48
|
+
rkey = rb_str_new(key, klen);
|
49
|
+
rkey = oj_encode(rkey);
|
50
|
+
*slot = rkey;
|
51
|
+
rb_gc_register_address(slot);
|
52
|
+
}
|
53
|
+
}
|
34
54
|
}
|
35
55
|
}
|
36
56
|
if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
|
@@ -93,23 +113,9 @@ static void end_hash(struct _parseInfo *pi) {
|
|
93
113
|
}
|
94
114
|
}
|
95
115
|
|
96
|
-
static VALUE calc_hash_key(ParseInfo pi, Val parent) {
|
97
|
-
volatile VALUE rkey = parent->key_val;
|
98
|
-
|
99
|
-
if (Qundef == rkey) {
|
100
|
-
rkey = rb_str_new(parent->key, parent->klen);
|
101
|
-
}
|
102
|
-
rkey = oj_encode(rkey);
|
103
|
-
if (Yes == pi->options.sym_key) {
|
104
|
-
rkey = rb_str_intern(rkey);
|
105
|
-
}
|
106
|
-
return rkey;
|
107
|
-
}
|
108
|
-
|
109
116
|
static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
110
|
-
volatile VALUE rstr =
|
117
|
+
volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
111
118
|
|
112
|
-
rstr = oj_encode(rstr);
|
113
119
|
if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
|
114
120
|
VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
|
115
121
|
|
@@ -142,10 +148,10 @@ static void hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) {
|
|
142
148
|
rb_funcall(stack_peek(&pi->stack)->val,
|
143
149
|
rb_intern("[]="),
|
144
150
|
2,
|
145
|
-
|
151
|
+
oj_calc_hash_key(pi, parent),
|
146
152
|
rval);
|
147
153
|
} else {
|
148
|
-
rb_hash_aset(stack_peek(&pi->stack)->val,
|
154
|
+
rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), rval);
|
149
155
|
}
|
150
156
|
if (Yes == pi->options.trace) {
|
151
157
|
oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
|
@@ -161,10 +167,10 @@ static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
|
|
161
167
|
rb_funcall(stack_peek(&pi->stack)->val,
|
162
168
|
rb_intern("[]="),
|
163
169
|
2,
|
164
|
-
|
170
|
+
oj_calc_hash_key(pi, parent),
|
165
171
|
value);
|
166
172
|
} else {
|
167
|
-
rb_hash_aset(stack_peek(&pi->stack)->val,
|
173
|
+
rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), value);
|
168
174
|
}
|
169
175
|
if (Yes == pi->options.trace) {
|
170
176
|
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
|
@@ -199,9 +205,8 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
|
|
199
205
|
}
|
200
206
|
|
201
207
|
static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
202
|
-
volatile VALUE rstr =
|
208
|
+
volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
203
209
|
|
204
|
-
rstr = oj_encode(rstr);
|
205
210
|
if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
|
206
211
|
VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
|
207
212
|
|
data/ext/oj/custom.c
CHANGED
@@ -955,6 +955,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
|
|
955
955
|
}
|
956
956
|
}
|
957
957
|
} else {
|
958
|
+
//volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
958
959
|
volatile VALUE rstr = rb_str_new(str, len);
|
959
960
|
|
960
961
|
if (Qundef == rkey) {
|
@@ -1010,19 +1011,6 @@ static void end_hash(struct _parseInfo *pi) {
|
|
1010
1011
|
}
|
1011
1012
|
}
|
1012
1013
|
|
1013
|
-
static VALUE calc_hash_key(ParseInfo pi, Val parent) {
|
1014
|
-
volatile VALUE rkey = parent->key_val;
|
1015
|
-
|
1016
|
-
if (Qundef == rkey) {
|
1017
|
-
rkey = rb_str_new(parent->key, parent->klen);
|
1018
|
-
}
|
1019
|
-
rkey = oj_encode(rkey);
|
1020
|
-
if (Yes == pi->options.sym_key) {
|
1021
|
-
rkey = rb_str_intern(rkey);
|
1022
|
-
}
|
1023
|
-
return rkey;
|
1024
|
-
}
|
1025
|
-
|
1026
1014
|
static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
|
1027
1015
|
Val parent = stack_peek(&pi->stack);
|
1028
1016
|
volatile VALUE rval = oj_num_as_value(ni);
|
@@ -1067,7 +1055,7 @@ static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
|
|
1067
1055
|
}
|
1068
1056
|
rval = parent->val;
|
1069
1057
|
} else {
|
1070
|
-
rb_hash_aset(parent->val,
|
1058
|
+
rb_hash_aset(parent->val, oj_calc_hash_key(pi, kval), rval);
|
1071
1059
|
}
|
1072
1060
|
break;
|
1073
1061
|
default: break;
|
@@ -1082,7 +1070,7 @@ static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
|
1082
1070
|
|
1083
1071
|
switch (rb_type(parent->val)) {
|
1084
1072
|
case T_OBJECT: oj_set_obj_ivar(parent, kval, value); break;
|
1085
|
-
case T_HASH: rb_hash_aset(parent->val,
|
1073
|
+
case T_HASH: rb_hash_aset(parent->val, oj_calc_hash_key(pi, kval), value); break;
|
1086
1074
|
default: break;
|
1087
1075
|
}
|
1088
1076
|
if (Yes == pi->options.trace) {
|
data/ext/oj/dump.c
CHANGED
@@ -535,59 +535,57 @@ void oj_dump_xml_time(VALUE obj, Out out) {
|
|
535
535
|
}
|
536
536
|
if ((0 == nsec && !out->opts->sec_prec_set) || 0 == out->opts->sec_prec) {
|
537
537
|
if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
|
538
|
-
sprintf(buf,
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
oj_dump_cstr(buf,
|
538
|
+
int len = sprintf(buf,
|
539
|
+
"%04d-%02d-%02dT%02d:%02d:%02dZ",
|
540
|
+
ti.year,
|
541
|
+
ti.mon,
|
542
|
+
ti.day,
|
543
|
+
ti.hour,
|
544
|
+
ti.min,
|
545
|
+
ti.sec);
|
546
|
+
oj_dump_cstr(buf, len, 0, 0, out);
|
547
547
|
} else {
|
548
|
-
sprintf(buf,
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
oj_dump_cstr(buf,
|
548
|
+
int len = sprintf(buf,
|
549
|
+
"%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
|
550
|
+
ti.year,
|
551
|
+
ti.mon,
|
552
|
+
ti.day,
|
553
|
+
ti.hour,
|
554
|
+
ti.min,
|
555
|
+
ti.sec,
|
556
|
+
tzsign,
|
557
|
+
tzhour,
|
558
|
+
tzmin);
|
559
|
+
oj_dump_cstr(buf, len, 0, 0, out);
|
560
560
|
}
|
561
561
|
} else if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
|
562
562
|
char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ";
|
563
|
-
int len
|
563
|
+
int len;
|
564
564
|
|
565
565
|
if (9 > out->opts->sec_prec) {
|
566
566
|
format[32] = '0' + out->opts->sec_prec;
|
567
|
-
len -= 9 - out->opts->sec_prec;
|
568
567
|
}
|
569
|
-
sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec);
|
568
|
+
len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec);
|
570
569
|
oj_dump_cstr(buf, len, 0, 0, out);
|
571
570
|
} else {
|
572
571
|
char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ld%c%02d:%02d";
|
573
|
-
int len
|
572
|
+
int len;
|
574
573
|
|
575
574
|
if (9 > out->opts->sec_prec) {
|
576
575
|
format[32] = '0' + out->opts->sec_prec;
|
577
|
-
len -= 9 - out->opts->sec_prec;
|
578
576
|
}
|
579
|
-
sprintf(buf,
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
577
|
+
len = sprintf(buf,
|
578
|
+
format,
|
579
|
+
ti.year,
|
580
|
+
ti.mon,
|
581
|
+
ti.day,
|
582
|
+
ti.hour,
|
583
|
+
ti.min,
|
584
|
+
ti.sec,
|
585
|
+
(long)nsec,
|
586
|
+
tzsign,
|
587
|
+
tzhour,
|
588
|
+
tzmin);
|
591
589
|
oj_dump_cstr(buf, len, 0, 0, out);
|
592
590
|
}
|
593
591
|
}
|
@@ -827,9 +825,8 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
827
825
|
if (is_sym) {
|
828
826
|
*out->cur++ = ':';
|
829
827
|
}
|
830
|
-
|
831
|
-
|
832
|
-
}
|
828
|
+
memcpy(out->cur, str, cnt);
|
829
|
+
out->cur += cnt;
|
833
830
|
*out->cur++ = '"';
|
834
831
|
} else {
|
835
832
|
const char *end = str + cnt;
|
@@ -1206,7 +1203,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1206
1203
|
if ((int)sizeof(buf) <= cnt) {
|
1207
1204
|
cnt = sizeof(buf) - 1;
|
1208
1205
|
}
|
1209
|
-
|
1206
|
+
memcpy(buf, rb_string_value_ptr((VALUE *)&rstr), cnt);
|
1210
1207
|
buf[cnt] = '\0';
|
1211
1208
|
} else {
|
1212
1209
|
cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, out->opts->float_fmt);
|
data/ext/oj/dump_strict.c
CHANGED
@@ -98,7 +98,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
98
98
|
if ((int)sizeof(buf) <= cnt) {
|
99
99
|
cnt = sizeof(buf) - 1;
|
100
100
|
}
|
101
|
-
|
101
|
+
memcpy(buf, rb_string_value_ptr((VALUE *)&rstr), cnt);
|
102
102
|
buf[cnt] = '\0';
|
103
103
|
} else {
|
104
104
|
cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, out->opts->float_fmt);
|
data/ext/oj/fast.c
CHANGED
@@ -80,22 +80,6 @@ static Leaf get_doc_leaf(Doc doc, const char *path);
|
|
80
80
|
static Leaf get_leaf(Leaf *stack, Leaf *lp, const char *path);
|
81
81
|
static void each_value(Doc doc, Leaf leaf);
|
82
82
|
|
83
|
-
static void doc_init(Doc doc);
|
84
|
-
static void doc_free(Doc doc);
|
85
|
-
static VALUE doc_open(VALUE clas, VALUE str);
|
86
|
-
static VALUE doc_open_file(VALUE clas, VALUE filename);
|
87
|
-
static VALUE doc_where(VALUE self);
|
88
|
-
static VALUE doc_local_key(VALUE self);
|
89
|
-
static VALUE doc_home(VALUE self);
|
90
|
-
static VALUE doc_type(int argc, VALUE *argv, VALUE self);
|
91
|
-
static VALUE doc_fetch(int argc, VALUE *argv, VALUE self);
|
92
|
-
static VALUE doc_each_leaf(int argc, VALUE *argv, VALUE self);
|
93
|
-
static VALUE doc_move(VALUE self, VALUE str);
|
94
|
-
static VALUE doc_each_child(int argc, VALUE *argv, VALUE self);
|
95
|
-
static VALUE doc_each_value(int argc, VALUE *argv, VALUE self);
|
96
|
-
static VALUE doc_dump(int argc, VALUE *argv, VALUE self);
|
97
|
-
static VALUE doc_size(VALUE self);
|
98
|
-
|
99
83
|
VALUE oj_doc_class = Qundef;
|
100
84
|
|
101
85
|
// This is only for CentOS 5.4 with Ruby 1.9.3-p0.
|
@@ -899,12 +883,14 @@ static Leaf get_leaf(Leaf *stack, Leaf *lp, const char *path) {
|
|
899
883
|
} else {
|
900
884
|
return 0;
|
901
885
|
}
|
902
|
-
} else if (
|
886
|
+
} else if (NULL == leaf->elements) {
|
887
|
+
leaf = NULL;
|
888
|
+
} else if (COL_VAL == leaf->value_type) {
|
903
889
|
Leaf first = leaf->elements->next;
|
904
890
|
Leaf e = first;
|
905
891
|
int type = leaf->rtype;
|
906
892
|
|
907
|
-
leaf =
|
893
|
+
leaf = NULL;
|
908
894
|
if (T_ARRAY == type) {
|
909
895
|
int cnt = 0;
|
910
896
|
|
@@ -929,6 +915,7 @@ static Leaf get_leaf(Leaf *stack, Leaf *lp, const char *path) {
|
|
929
915
|
const char *slash = next_slash(path);
|
930
916
|
int klen;
|
931
917
|
|
918
|
+
leaf = NULL;
|
932
919
|
if (0 == slash) {
|
933
920
|
klen = (int)strlen(key);
|
934
921
|
path += klen;
|
@@ -1217,7 +1204,7 @@ static char *append_key(char *p, const char *key) {
|
|
1217
1204
|
* @see Oj::Doc.open
|
1218
1205
|
*/
|
1219
1206
|
|
1220
|
-
/* @overload where
|
1207
|
+
/* @overload where() => String
|
1221
1208
|
*
|
1222
1209
|
* Returns a String that describes the absolute path to the current location
|
1223
1210
|
* in the JSON document.
|
@@ -1259,6 +1246,25 @@ static VALUE doc_where(VALUE self) {
|
|
1259
1246
|
}
|
1260
1247
|
}
|
1261
1248
|
|
1249
|
+
/* @overload where?() => String
|
1250
|
+
* @deprecated
|
1251
|
+
* Returns a String that describes the absolute path to the current location
|
1252
|
+
* in the JSON document.
|
1253
|
+
*/
|
1254
|
+
static VALUE doc_where_q(VALUE self) {
|
1255
|
+
return doc_where(self);
|
1256
|
+
}
|
1257
|
+
|
1258
|
+
/* @overload path() => String
|
1259
|
+
*
|
1260
|
+
* Returns a String that describes the absolute path to the current location
|
1261
|
+
* in the JSON document.
|
1262
|
+
*/
|
1263
|
+
static VALUE doc_path(VALUE self) {
|
1264
|
+
return doc_where(self);
|
1265
|
+
}
|
1266
|
+
|
1267
|
+
|
1262
1268
|
/* @overload local_key() => String, Fixnum, nil
|
1263
1269
|
*
|
1264
1270
|
* Returns the final key to the current location.
|
@@ -1340,14 +1346,14 @@ static VALUE doc_type(int argc, VALUE *argv, VALUE self) {
|
|
1340
1346
|
return type;
|
1341
1347
|
}
|
1342
1348
|
|
1343
|
-
/* @overload fetch(path=nil) => nil, true, false, Fixnum, Float, String, Array,
|
1349
|
+
/* @overload fetch(path=nil,default=nil) => nil, true, false, Fixnum, Float, String, Array,
|
1344
1350
|
* Hash
|
1345
1351
|
*
|
1346
1352
|
* Returns the value at the location identified by the path or the current
|
1347
1353
|
* location if the path is nil or not provided. This method will create and
|
1348
1354
|
* return an Array or Hash if that is the type of Object at the location
|
1349
1355
|
* specified. This is more expensive than navigating to the leaves of the JSON
|
1350
|
-
* document.
|
1356
|
+
* document. If a default is provided that is used if no value if found.
|
1351
1357
|
* @param [String] path path to the location to get the type of if provided
|
1352
1358
|
* @example
|
1353
1359
|
* Oj::Doc.open('[1,2]') { |doc| doc.fetch() } #=> [1, 2]
|
@@ -1373,6 +1379,28 @@ static VALUE doc_fetch(int argc, VALUE *argv, VALUE self) {
|
|
1373
1379
|
return val;
|
1374
1380
|
}
|
1375
1381
|
|
1382
|
+
/* @overload exists?(path) => true, false
|
1383
|
+
*
|
1384
|
+
* Returns true if the value at the location identified by the path exists.
|
1385
|
+
* @param [String] path path to the location
|
1386
|
+
* @example
|
1387
|
+
* Oj::Doc.open('[1,2]') { |doc| doc.exists('/1') } #=> true
|
1388
|
+
* Oj::Doc.open('[1,2]') { |doc| doc.exists('/3') } #=> false
|
1389
|
+
*/
|
1390
|
+
static VALUE doc_exists(VALUE self, VALUE str) {
|
1391
|
+
Doc doc;
|
1392
|
+
Leaf leaf;
|
1393
|
+
|
1394
|
+
doc = self_doc(self);
|
1395
|
+
Check_Type(str, T_STRING);
|
1396
|
+
if (0 != (leaf = get_doc_leaf(doc, StringValuePtr(str)))) {
|
1397
|
+
if (NULL != leaf) {
|
1398
|
+
return Qtrue;
|
1399
|
+
}
|
1400
|
+
}
|
1401
|
+
return Qfalse;
|
1402
|
+
}
|
1403
|
+
|
1376
1404
|
/* @overload each_leaf(path=nil) => nil
|
1377
1405
|
*
|
1378
1406
|
* Yields to the provided block for each leaf node with the identified
|
@@ -1695,11 +1723,14 @@ void oj_init_doc() {
|
|
1695
1723
|
rb_define_singleton_method(oj_doc_class, "open", doc_open, 1);
|
1696
1724
|
rb_define_singleton_method(oj_doc_class, "open_file", doc_open_file, 1);
|
1697
1725
|
rb_define_singleton_method(oj_doc_class, "parse", doc_open, 1);
|
1698
|
-
rb_define_method(oj_doc_class, "where?",
|
1726
|
+
rb_define_method(oj_doc_class, "where?", doc_where_q, 0);
|
1727
|
+
rb_define_method(oj_doc_class, "where", doc_where, 0);
|
1728
|
+
rb_define_method(oj_doc_class, "path", doc_path, 0);
|
1699
1729
|
rb_define_method(oj_doc_class, "local_key", doc_local_key, 0);
|
1700
1730
|
rb_define_method(oj_doc_class, "home", doc_home, 0);
|
1701
1731
|
rb_define_method(oj_doc_class, "type", doc_type, -1);
|
1702
1732
|
rb_define_method(oj_doc_class, "fetch", doc_fetch, -1);
|
1733
|
+
rb_define_method(oj_doc_class, "exists?", doc_exists, 1);
|
1703
1734
|
rb_define_method(oj_doc_class, "each_leaf", doc_each_leaf, -1);
|
1704
1735
|
rb_define_method(oj_doc_class, "move", doc_move, 1);
|
1705
1736
|
rb_define_method(oj_doc_class, "each_child", doc_each_child, -1);
|
data/ext/oj/hash.c
CHANGED
@@ -5,8 +5,8 @@
|
|
5
5
|
|
6
6
|
#include <stdint.h>
|
7
7
|
|
8
|
-
#define
|
9
|
-
#define HASH_SLOT_CNT
|
8
|
+
#define HASH_SLOT_CNT ((uint32_t)8192)
|
9
|
+
#define HASH_MASK (HASH_SLOT_CNT - 1)
|
10
10
|
|
11
11
|
typedef struct _keyVal {
|
12
12
|
struct _keyVal *next;
|
@@ -20,6 +20,8 @@ struct _hash {
|
|
20
20
|
};
|
21
21
|
|
22
22
|
struct _hash class_hash;
|
23
|
+
struct _hash str_hash;
|
24
|
+
struct _hash sym_hash;
|
23
25
|
struct _hash intern_hash;
|
24
26
|
|
25
27
|
// almost the Murmur hash algorithm
|
@@ -64,6 +66,8 @@ static uint32_t hash_calc(const uint8_t *key, size_t len) {
|
|
64
66
|
|
65
67
|
void oj_hash_init() {
|
66
68
|
memset(class_hash.slots, 0, sizeof(class_hash.slots));
|
69
|
+
memset(str_hash.slots, 0, sizeof(str_hash.slots));
|
70
|
+
memset(sym_hash.slots, 0, sizeof(sym_hash.slots));
|
67
71
|
memset(intern_hash.slots, 0, sizeof(intern_hash.slots));
|
68
72
|
}
|
69
73
|
|
@@ -100,8 +104,8 @@ static VALUE hash_get(Hash hash, const char *key, size_t len, VALUE **slotp, VAL
|
|
100
104
|
}
|
101
105
|
|
102
106
|
void oj_hash_print() {
|
103
|
-
|
104
|
-
KeyVal
|
107
|
+
uint32_t i;
|
108
|
+
KeyVal b;
|
105
109
|
|
106
110
|
for (i = 0; i < HASH_SLOT_CNT; i++) {
|
107
111
|
printf("%4d:", i);
|
@@ -112,11 +116,44 @@ void oj_hash_print() {
|
|
112
116
|
}
|
113
117
|
}
|
114
118
|
|
119
|
+
void oj_hash_sizes() {
|
120
|
+
uint32_t i;
|
121
|
+
KeyVal b;
|
122
|
+
int max = 0;
|
123
|
+
int min = 1000000;
|
124
|
+
|
125
|
+
for (i = 0; i < HASH_SLOT_CNT; i++) {
|
126
|
+
int cnt = 0;
|
127
|
+
|
128
|
+
for (b = str_hash.slots + i; 0 != b && 0 != b->key; b = b->next) {
|
129
|
+
cnt++;
|
130
|
+
}
|
131
|
+
// printf(" %4d\n", cnt);
|
132
|
+
if (max < cnt) {
|
133
|
+
max = cnt;
|
134
|
+
}
|
135
|
+
if (cnt < min) {
|
136
|
+
min = cnt;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
printf("min: %d max: %d\n", min, max);
|
140
|
+
}
|
141
|
+
|
115
142
|
VALUE
|
116
143
|
oj_class_hash_get(const char *key, size_t len, VALUE **slotp) {
|
117
144
|
return hash_get(&class_hash, key, len, slotp, Qnil);
|
118
145
|
}
|
119
146
|
|
147
|
+
VALUE
|
148
|
+
oj_str_hash_get(const char *key, size_t len, VALUE **slotp) {
|
149
|
+
return hash_get(&str_hash, key, len, slotp, Qnil);
|
150
|
+
}
|
151
|
+
|
152
|
+
VALUE
|
153
|
+
oj_sym_hash_get(const char *key, size_t len, VALUE **slotp) {
|
154
|
+
return hash_get(&sym_hash, key, len, slotp, Qnil);
|
155
|
+
}
|
156
|
+
|
120
157
|
ID oj_attr_hash_get(const char *key, size_t len, ID **slotp) {
|
121
158
|
return (ID)hash_get(&intern_hash, key, len, (VALUE **)slotp, 0);
|
122
159
|
}
|