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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8275f7a7bc4675418e94fb048888662e5b9e9292eb0e8a7d3f5bd1cb2c4d6cc
4
- data.tar.gz: b8aa813939f082f384d4300cfe56fb41e660c366b18709a0dc8efe97336baa44
3
+ metadata.gz: 718229e62c9fde37495f36cb674b79025c626a934d188698a0e2c87937566809
4
+ data.tar.gz: 490a556129f5d13bc29c1b422e0af6cded6d97c88ead6b953ada4abf06ada594
5
5
  SHA512:
6
- metadata.gz: 965b4a25bd1fa1549dcb20162b0f80a6963d29352a5b2333ddc6590b3b32fa0b25e6627470aa94c327cd103472f62669f47e5c823050d4a5038ba8c6b66b10c8
7
- data.tar.gz: 688d27daf26686b8b5dfd71d926d35e3f91adcdb430d21b388dd077fd05f9e2974b296e8eb520543ab7a2f4e1e5587b2152a3437026e8a3d74591e2a436197e4
6
+ metadata.gz: 92ddcdc95170deef8d6854a879c5c910181ab6a16bbdb175e8d92ab67169ca80ee36d7ddfdcbf3aa45c036955c60d6642c53e45d9bbed3f3584aac61335c83cf
7
+ data.tar.gz: a45c33ee35937db46ee01819b25264b9d7e9336a014a93edaba0cf878b5ad5d3a4a3303f8357b9848253d2953a50c2679469cc52e62ceabeb462da2616f43338
data/.gitignore CHANGED
@@ -13,3 +13,4 @@
13
13
  *.bundle
14
14
  Makefile
15
15
  *.o
16
+ *.so
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- oj-introspect (0.4.0)
5
- oj (>= 3.13.22)
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.22)
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 = '{ "foo": "bar" }'
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("Introspected") do
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
- } *IntrospectDelegate;
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
- // We are cheating with the mark, free, and options functions. Since struct
104
- // _usual is the first member of struct _introspect the cast to Usual in the
105
- // usual.c mark() function should still work just fine.
193
+ d->delegated_option_func = p->option;
194
+ p->option = option;
106
195
 
107
- // PCO - do you need the location of sub-objects and arrays or just top
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->close_object = close_object_introspected;
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
 
@@ -1,5 +1,5 @@
1
1
  module Oj
2
2
  class Introspect
3
- VERSION = "0.4.0"
3
+ VERSION = "0.6.0"
4
4
  end
5
5
  end
@@ -24,5 +24,5 @@ Gem::Specification.new do |spec|
24
24
  spec.require_paths = ["lib"]
25
25
  spec.extensions = ["ext/oj-introspect/extconf.rb"]
26
26
 
27
- spec.add_dependency "oj", ">=3.13.22"
27
+ spec.add_dependency "oj", ">=3.13.23"
28
28
  end
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.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-02 00:00:00.000000000 Z
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.22
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.22
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: