oj-introspect 0.4.0 → 0.6.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 +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +3 -3
- data/bin/benchmark +7 -2
- data/ext/oj-introspect/introspect.c +102 -19
- data/lib/oj/introspect/version.rb +1 -1
- data/oj-introspect.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 718229e62c9fde37495f36cb674b79025c626a934d188698a0e2c87937566809
|
4
|
+
data.tar.gz: 490a556129f5d13bc29c1b422e0af6cded6d97c88ead6b953ada4abf06ada594
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92ddcdc95170deef8d6854a879c5c910181ab6a16bbdb175e8d92ab67169ca80ee36d7ddfdcbf3aa45c036955c60d6642c53e45d9bbed3f3584aac61335c83cf
|
7
|
+
data.tar.gz: a45c33ee35937db46ee01819b25264b9d7e9336a014a93edaba0cf878b5ad5d3a4a3303f8357b9848253d2953a50c2679469cc52e62ceabeb462da2616f43338
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
oj-introspect (0.
|
5
|
-
oj (>= 3.13.
|
4
|
+
oj-introspect (0.6.0)
|
5
|
+
oj (>= 3.13.23)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
@@ -11,7 +11,7 @@ GEM
|
|
11
11
|
coderay (1.1.3)
|
12
12
|
diff-lcs (1.5.0)
|
13
13
|
method_source (1.0.0)
|
14
|
-
oj (3.13.
|
14
|
+
oj (3.13.23)
|
15
15
|
pry (0.14.1)
|
16
16
|
coderay (~> 1.1)
|
17
17
|
method_source (~> 1.0)
|
data/bin/benchmark
CHANGED
@@ -5,16 +5,21 @@ require "oj/introspect"
|
|
5
5
|
require "json"
|
6
6
|
require "benchmark/ips"
|
7
7
|
|
8
|
-
TEST_JSON =
|
8
|
+
TEST_JSON = File.read("./spec/fixtures/vulnerabilities.json")
|
9
9
|
|
10
10
|
INTROSPECT_PARSER = Oj::Parser.introspect
|
11
|
+
FILTERED_INTROSPECT_PARSER = Oj::Introspect.new(filter: "remediations")
|
11
12
|
USUAL_PARSER = Oj::Parser.usual
|
12
13
|
|
13
14
|
Benchmark.ips do |b|
|
14
|
-
b.report("
|
15
|
+
b.report("Introspect") do
|
15
16
|
INTROSPECT_PARSER.parse(TEST_JSON)
|
16
17
|
end
|
17
18
|
|
19
|
+
b.report("Filtered introspect") do
|
20
|
+
FILTERED_INTROSPECT_PARSER.parse(TEST_JSON)
|
21
|
+
end
|
22
|
+
|
18
23
|
b.report("Oj usual") do
|
19
24
|
USUAL_PARSER.parse(TEST_JSON)
|
20
25
|
end
|
@@ -16,16 +16,24 @@ typedef struct _introspect_S {
|
|
16
16
|
struct _usual usual; // inherit all the attributes from `_usual` struct
|
17
17
|
struct _byte_offsets byte_offsets; // I think it's better to encapsulate common fields under a namespace
|
18
18
|
|
19
|
+
char *filter;
|
20
|
+
bool introspect;
|
21
|
+
|
19
22
|
void (*delegated_start_func)(struct _ojParser *p);
|
20
23
|
void (*delegated_free_func)(struct _ojParser *p);
|
24
|
+
VALUE (*delegated_option_func)(struct _ojParser *p, const char *key, VALUE value);
|
21
25
|
void (*delegated_open_object_func)(struct _ojParser *p);
|
22
26
|
void (*delegated_open_object_key_func)(struct _ojParser *p);
|
27
|
+
void (*delegated_open_array_key_func)(struct _ojParser *p);
|
23
28
|
void (*delegated_close_object_func)(struct _ojParser *p);
|
24
|
-
|
29
|
+
void (*delegated_close_object_key_func)(struct _ojParser *p);
|
30
|
+
void (*delegated_close_array_key_func)(struct _ojParser *p);
|
31
|
+
} * IntrospectDelegate;
|
25
32
|
|
26
33
|
static void dfree(ojParser p) {
|
27
34
|
IntrospectDelegate d = (IntrospectDelegate)p->ctx;
|
28
35
|
|
36
|
+
if(d->filter != NULL) xfree(d->filter);
|
29
37
|
xfree(d->byte_offsets.stack);
|
30
38
|
d->delegated_free_func(p);
|
31
39
|
}
|
@@ -36,6 +44,32 @@ static void start(ojParser p) {
|
|
36
44
|
d->delegated_start_func(p);
|
37
45
|
// Reset to zero so the parser and delegate can be reused.
|
38
46
|
d->byte_offsets.current = 0;
|
47
|
+
|
48
|
+
/*
|
49
|
+
* If the `filter` is provided we will start introspecting later
|
50
|
+
* once we encounter with the key provided.
|
51
|
+
*/
|
52
|
+
d->introspect = (d->filter == NULL);
|
53
|
+
}
|
54
|
+
|
55
|
+
static void copy_ruby_str(char **target, VALUE source) {
|
56
|
+
size_t len = RSTRING_LEN(source);
|
57
|
+
*target = ALLOC_N(char, len + 1);
|
58
|
+
memcpy(*target, RSTRING_PTR(source), len);
|
59
|
+
(*target)[len] = '\0'; // Parantheses are important as it means => (*target + sizeof(char) * len)
|
60
|
+
}
|
61
|
+
|
62
|
+
static VALUE option(ojParser p, const char *key, VALUE value) {
|
63
|
+
IntrospectDelegate d = (IntrospectDelegate)p->ctx;
|
64
|
+
|
65
|
+
if(strcmp(key, "filter=") == 0) {
|
66
|
+
Check_Type(value, T_STRING);
|
67
|
+
copy_ruby_str(&d->filter, value); // We need to copy the value as GC can free it later.
|
68
|
+
|
69
|
+
return Qtrue;
|
70
|
+
}
|
71
|
+
|
72
|
+
return d->delegated_option_func(p, key, value);
|
39
73
|
}
|
40
74
|
|
41
75
|
static void ensure_byte_offsets_stack(IntrospectDelegate d) {
|
@@ -65,16 +99,54 @@ static void open_object_introspected(ojParser p) {
|
|
65
99
|
d->delegated_open_object_func(p);
|
66
100
|
}
|
67
101
|
|
102
|
+
static char * previously_inserted_key(IntrospectDelegate d) {
|
103
|
+
Key key = (d->usual.ktail - 1);
|
104
|
+
|
105
|
+
return ((size_t)key->len < sizeof(key->buf)) ? key->buf : key->key;
|
106
|
+
}
|
107
|
+
|
108
|
+
static bool should_switch_introspection(IntrospectDelegate d) {
|
109
|
+
return strcmp(d->filter, previously_inserted_key(d)) == 0;
|
110
|
+
}
|
111
|
+
|
112
|
+
/*
|
113
|
+
* WHEN there is a filter
|
114
|
+
* AND
|
115
|
+
* WHEN the introspection is disabled
|
116
|
+
* AND the last inserted key matches the filter
|
117
|
+
* THEN enable introspection
|
118
|
+
* OR
|
119
|
+
* WHEN the introspection is enabled
|
120
|
+
* AND the last inserted key matches the filter
|
121
|
+
* THEN disable introspection
|
122
|
+
*/
|
123
|
+
static void switch_introspection(IntrospectDelegate d) {
|
124
|
+
if(d->filter == NULL) return;
|
125
|
+
|
126
|
+
d->introspect = should_switch_introspection(d) != d->introspect; // a XOR b
|
127
|
+
}
|
128
|
+
|
68
129
|
static void open_object_key_introspected(ojParser p) {
|
69
130
|
push(p);
|
70
131
|
|
71
132
|
IntrospectDelegate d = (IntrospectDelegate)p->ctx;
|
72
133
|
d->delegated_open_object_key_func(p);
|
134
|
+
|
135
|
+
if(!d->introspect) switch_introspection(d);
|
136
|
+
}
|
137
|
+
|
138
|
+
static void open_array_key_introspected(ojParser p) {
|
139
|
+
IntrospectDelegate d = (IntrospectDelegate)p->ctx;
|
140
|
+
d->delegated_open_array_key_func(p);
|
141
|
+
|
142
|
+
if(!d->introspect) switch_introspection(d);
|
73
143
|
}
|
74
144
|
|
75
145
|
static void set_introspection_values(ojParser p) {
|
76
146
|
IntrospectDelegate d = (IntrospectDelegate)p->ctx;
|
77
147
|
|
148
|
+
if(!d->introspect) return;
|
149
|
+
|
78
150
|
volatile VALUE obj = rb_hash_new();
|
79
151
|
rb_hash_aset(obj, ID2SYM(rb_intern("start_byte")), INT2FIX(pop(p)));
|
80
152
|
rb_hash_aset(obj, ID2SYM(rb_intern("end_byte")), INT2FIX(p->cur));
|
@@ -88,6 +160,24 @@ static void close_object_introspected(ojParser p) {
|
|
88
160
|
set_introspection_values(p);
|
89
161
|
}
|
90
162
|
|
163
|
+
// We switch introspection off only for object and array keys.
|
164
|
+
static void close_object_key_introspected(ojParser p) {
|
165
|
+
IntrospectDelegate d = (IntrospectDelegate)p->ctx;
|
166
|
+
d->delegated_close_object_func(p);
|
167
|
+
|
168
|
+
if(d->introspect) {
|
169
|
+
set_introspection_values(p);
|
170
|
+
switch_introspection(d);
|
171
|
+
}
|
172
|
+
}
|
173
|
+
|
174
|
+
static void close_array_key_introspected(ojParser p) {
|
175
|
+
IntrospectDelegate d = (IntrospectDelegate)p->ctx;
|
176
|
+
d->delegated_close_array_key_func(p);
|
177
|
+
|
178
|
+
if(d->introspect) switch_introspection(d);
|
179
|
+
}
|
180
|
+
|
91
181
|
static void init_introspect_parser(ojParser p, VALUE ropts) {
|
92
182
|
IntrospectDelegate d = ALLOC(struct _introspect_S);
|
93
183
|
|
@@ -100,12 +190,10 @@ static void init_introspect_parser(ojParser p, VALUE ropts) {
|
|
100
190
|
d->delegated_start_func = p->start;
|
101
191
|
p->start = start;
|
102
192
|
|
103
|
-
|
104
|
-
|
105
|
-
// usual.c mark() function should still work just fine.
|
193
|
+
d->delegated_option_func = p->option;
|
194
|
+
p->option = option;
|
106
195
|
|
107
|
-
//
|
108
|
-
// level objects?
|
196
|
+
// Wrap original functions to collect byte offsets
|
109
197
|
Funcs f = &p->funcs[TOP_FUN];
|
110
198
|
d->delegated_open_object_func = f->open_object;
|
111
199
|
d->delegated_close_object_func = f->close_object;
|
@@ -117,31 +205,26 @@ static void init_introspect_parser(ojParser p, VALUE ropts) {
|
|
117
205
|
f->close_object = close_object_introspected;
|
118
206
|
|
119
207
|
f = &p->funcs[OBJECT_FUN];
|
208
|
+
d->delegated_open_array_key_func = f->open_array;
|
120
209
|
d->delegated_open_object_key_func = f->open_object;
|
210
|
+
d->delegated_close_array_key_func = f->close_array;
|
211
|
+
d->delegated_close_object_key_func = f->close_object;
|
212
|
+
f->open_array = open_array_key_introspected;
|
121
213
|
f->open_object = open_object_key_introspected;
|
122
|
-
f->
|
214
|
+
f->close_array = close_array_key_introspected;
|
215
|
+
f->close_object = close_object_key_introspected;
|
123
216
|
|
124
217
|
// Init stack
|
125
218
|
d->byte_offsets.current = 0;
|
126
219
|
d->byte_offsets.stack = ALLOC_N(long, BYTE_OFFSETS_STACK_INC_SIZE);
|
127
220
|
d->byte_offsets.length = BYTE_OFFSETS_STACK_INC_SIZE;
|
128
221
|
|
222
|
+
d->filter = NULL;
|
223
|
+
|
129
224
|
// Process options.
|
130
225
|
oj_parser_set_option(p, ropts);
|
131
226
|
}
|
132
227
|
|
133
|
-
VALUE oj_get_parser_introspect() {
|
134
|
-
VALUE oj_parser = oj_parser_new();
|
135
|
-
struct _ojParser *p;
|
136
|
-
Data_Get_Struct(oj_parser, struct _ojParser, p);
|
137
|
-
|
138
|
-
init_introspect_parser(p, Qnil);
|
139
|
-
|
140
|
-
rb_gc_register_address(&oj_parser);
|
141
|
-
|
142
|
-
return oj_parser;
|
143
|
-
}
|
144
|
-
|
145
228
|
static VALUE rb_new_introspect_parser(int argc, VALUE *argv, VALUE self) {
|
146
229
|
rb_check_arity(argc, 0, 1);
|
147
230
|
|
data/oj-introspect.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj-introspect
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mehmet Emin INAC
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-11-
|
11
|
+
date: 2022-11-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oj
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 3.13.
|
19
|
+
version: 3.13.23
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 3.13.
|
26
|
+
version: 3.13.23
|
27
27
|
description: Embeds start and end byte offsets of JSON objects into generated Ruby
|
28
28
|
hashes.
|
29
29
|
email:
|