oj-introspect 0.4.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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: