oj 3.11.5 → 3.12.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
# [![{}j](http://www.ohler.com/dev/images/oj_comet_64.svg)](http://www.ohler.com/oj) gem
|
2
2
|
|
3
|
-
[![Build Status](https://img.shields.io/
|
3
|
+
[![Build Status](https://img.shields.io/github/workflow/status/ohler55/oj/CI?logo=github)](https://github.com/ohler55/oj/actions/workflows/CI.yml)
|
4
|
+
![Gem](https://img.shields.io/gem/v/oj.svg)
|
5
|
+
![Gem](https://img.shields.io/gem/dt/oj.svg)
|
6
|
+
[![SemVer compatibility](https://api.dependabot.com/badges/compatibility_score?dependency-name=oj&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=oj&package-manager=bundler&version-scheme=semver)
|
7
|
+
[![TideLift](https://tidelift.com/badges/github/ohler55/oj)](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
|
}
|