rotoscope 0.3.0.pre.3 → 0.3.0.pre.4
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 +7 -7
- data/ext/rotoscope/rotoscope.c +48 -33
- data/ext/rotoscope/rotoscope.h +2 -1
- data/ext/rotoscope/stack.c +20 -11
- data/ext/rotoscope/stack.h +3 -3
- data/lib/rotoscope.rb +5 -5
- data/lib/rotoscope/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4fd8393cc33b1bc131fd9f8b59f5445df3ba615
|
4
|
+
data.tar.gz: e4dbe71f46625cc11039cf3fc2a97eae80226f35
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2516f3ec80a5de3fca9cfdb241e085fbb93cd8a29ad75dc050a210971547b59b530866aab8120bd8c142f219ce12137a8a569ea40cb6a4a76775b385ecb5c670
|
7
|
+
data.tar.gz: 0ed7735ef3e1a6bb3126ad2e79d72d7d3fc0c51b313a9b0d211e14755a51e7997df7e1aa5170c84f6b966329bf2f5d56bb7b39de6f127e240bcffef65926c292
|
data/README.md
CHANGED
@@ -85,8 +85,8 @@ IO,write,instance,example/flattened_dog.rb,11,IO,puts,instance
|
|
85
85
|
## API
|
86
86
|
|
87
87
|
- [Public Class Methods](#public-class-methods)
|
88
|
-
- [`trace`](#rotoscopetracedest-
|
89
|
-
- [`new`](#rotoscopenewdest-
|
88
|
+
- [`trace`](#rotoscopetracedest-blacklist--flatten-false)
|
89
|
+
- [`new`](#rotoscopenewdest-blacklist--flatten-false)
|
90
90
|
- [Public Instance Methods](#public-instance-methods)
|
91
91
|
- [`trace`](#rotoscopetraceblock)
|
92
92
|
- [`start_trace`](#rotoscopestart_trace)
|
@@ -101,23 +101,23 @@ IO,write,instance,example/flattened_dog.rb,11,IO,puts,instance
|
|
101
101
|
|
102
102
|
### Public Class Methods
|
103
103
|
|
104
|
-
#### `Rotoscope::trace(dest,
|
104
|
+
#### `Rotoscope::trace(dest, blacklist: [], flatten: false)`
|
105
105
|
|
106
|
-
Writes all calls and returns of methods to `dest`, except for those whose
|
106
|
+
Writes all calls and returns of methods to `dest`, except for those whose filepath contains any entry in `blacklist`. `dest` is either a filename or an `IO`. The `flatten` option reduces the output data to a deduplicated list of method invocations and their caller, instead of all `call` and `return` events. Methods invoked at the top of the trace will have a caller entity of `<ROOT>` and a caller method name of `<UNKNOWN>`.
|
107
107
|
|
108
108
|
```ruby
|
109
109
|
Rotoscope.trace(dest) { |rs| ... }
|
110
110
|
# or...
|
111
|
-
Rotoscope.trace(dest,
|
111
|
+
Rotoscope.trace(dest, blacklist: ["/.gem/"], flatten: true) { |rs| ... }
|
112
112
|
```
|
113
113
|
|
114
|
-
#### `Rotoscope::new(dest,
|
114
|
+
#### `Rotoscope::new(dest, blacklist: [], flatten: false)`
|
115
115
|
|
116
116
|
Same interface as `Rotoscope::trace`, but returns a `Rotoscope` instance, allowing fine-grain control via `Rotoscope#start_trace` and `Rotoscope#stop_trace`.
|
117
117
|
```ruby
|
118
118
|
rs = Rotoscope.new(dest)
|
119
119
|
# or...
|
120
|
-
rs = Rotoscope.new(dest,
|
120
|
+
rs = Rotoscope.new(dest, blacklist: ["/.gem/"], flatten: true)
|
121
121
|
```
|
122
122
|
|
123
123
|
---
|
data/ext/rotoscope/rotoscope.c
CHANGED
@@ -37,9 +37,12 @@ static const char *evflag2name(rb_event_flag_t evflag) {
|
|
37
37
|
}
|
38
38
|
}
|
39
39
|
|
40
|
-
static bool
|
41
|
-
|
42
|
-
|
40
|
+
static bool rejected_path(VALUE path, Rotoscope *config) {
|
41
|
+
for (unsigned long i = 0; i < config->blacklist_size; i++) {
|
42
|
+
if (strstr(StringValueCStr(path), config->blacklist[i])) return true;
|
43
|
+
}
|
44
|
+
|
45
|
+
return false;
|
43
46
|
}
|
44
47
|
|
45
48
|
static VALUE class_path(VALUE klass) {
|
@@ -123,14 +126,10 @@ static void log_trace_event(FILE *stream, rs_tracepoint_t *trace) {
|
|
123
126
|
unsigned char output_buffer[LOG_BUFFER_SIZE];
|
124
127
|
static void log_trace_event_with_caller(FILE *stream,
|
125
128
|
rs_stack_frame_t *stack_frame,
|
129
|
+
rs_stack_frame_t *caller_frame,
|
126
130
|
rs_strmemo_t **call_memo) {
|
127
|
-
rs_stack_frame_t *caller = stack_frame->caller;
|
128
|
-
while (caller->blacklisted) {
|
129
|
-
caller = caller->caller;
|
130
|
-
}
|
131
|
-
|
132
131
|
snprintf((char *)output_buffer, LOG_BUFFER_SIZE, RS_FLATTENED_CSV_FORMAT "\n",
|
133
|
-
RS_FLATTENED_CSV_VALUES(&stack_frame->tp, &
|
132
|
+
RS_FLATTENED_CSV_VALUES(&stack_frame->tp, &caller_frame->tp));
|
134
133
|
|
135
134
|
if (rs_strmemo_uniq(call_memo, output_buffer)) {
|
136
135
|
fputs((char *)output_buffer, stream);
|
@@ -151,38 +150,38 @@ static void event_hook(VALUE tpval, void *data) {
|
|
151
150
|
rb_event_flag_t event_flag = rb_tracearg_event_flag(trace_arg);
|
152
151
|
|
153
152
|
rs_callsite_t trace_path;
|
153
|
+
bool blacklisted;
|
154
154
|
if (event_flag & EVENT_CALL) {
|
155
155
|
trace_path = tracearg_path(trace_arg);
|
156
|
+
blacklisted = rejected_path(trace_path.filepath, config);
|
156
157
|
} else {
|
157
158
|
if (rs_stack_empty(&config->stack)) return;
|
158
159
|
rs_stack_frame_t *call_frame = rs_stack_peek(&config->stack);
|
159
160
|
trace_path = (rs_callsite_t){
|
160
161
|
.filepath = call_frame->tp.filepath, .lineno = call_frame->tp.lineno,
|
161
162
|
};
|
163
|
+
blacklisted = call_frame->blacklisted;
|
162
164
|
}
|
163
165
|
|
164
166
|
rs_tracepoint_t trace = extract_full_tracevals(trace_arg, &trace_path);
|
165
167
|
if (!strcmp("Rotoscope", StringValueCStr(trace.entity))) return;
|
166
168
|
|
167
|
-
bool blacklisted;
|
168
169
|
if (event_flag & EVENT_CALL) {
|
169
|
-
blacklisted = rejected_entity(trace.entity, config);
|
170
170
|
rs_stack_push(&config->stack, trace, blacklisted);
|
171
171
|
} else {
|
172
|
-
blacklisted = rs_stack_peek(&config->stack)->blacklisted;
|
173
172
|
rs_stack_pop(&config->stack);
|
174
173
|
}
|
175
174
|
if (blacklisted) return;
|
176
175
|
|
177
176
|
if (config->flatten_output) {
|
178
177
|
if (event_flag & EVENT_CALL) {
|
179
|
-
rs_stack_frame_t *caller = rs_stack_peek(&config->stack)
|
180
|
-
|
181
|
-
caller =
|
182
|
-
}
|
178
|
+
rs_stack_frame_t *caller = rs_stack_peek(&config->stack);
|
179
|
+
do {
|
180
|
+
caller = rs_stack_below(&config->stack, caller);
|
181
|
+
} while (caller && caller->blacklisted);
|
183
182
|
if (caller) {
|
184
183
|
log_trace_event_with_caller(config->log, rs_stack_peek(&config->stack),
|
185
|
-
&config->call_memo);
|
184
|
+
caller, &config->call_memo);
|
186
185
|
}
|
187
186
|
}
|
188
187
|
} else {
|
@@ -215,7 +214,6 @@ static void close_log_handle(Rotoscope *config) {
|
|
215
214
|
static void rs_gc_mark(Rotoscope *config) {
|
216
215
|
rb_gc_mark(config->log_path);
|
217
216
|
rb_gc_mark(config->tracepoint);
|
218
|
-
rb_gc_mark(config->entity_whitelist);
|
219
217
|
rs_stack_mark(&config->stack);
|
220
218
|
}
|
221
219
|
|
@@ -223,6 +221,7 @@ void rs_dealloc(Rotoscope *config) {
|
|
223
221
|
close_log_handle(config);
|
224
222
|
rs_stack_free(&config->stack);
|
225
223
|
rs_strmemo_free(config->call_memo);
|
224
|
+
xfree(config->blacklist);
|
226
225
|
xfree(config);
|
227
226
|
}
|
228
227
|
|
@@ -231,7 +230,6 @@ static VALUE rs_alloc(VALUE klass) {
|
|
231
230
|
VALUE self =
|
232
231
|
Data_Make_Struct(klass, Rotoscope, rs_gc_mark, rs_dealloc, config);
|
233
232
|
config->log_path = Qnil;
|
234
|
-
config->entity_whitelist = Qnil;
|
235
233
|
config->tracepoint = rb_tracepoint_new(Qnil, EVENT_CALL | EVENT_RETURN,
|
236
234
|
event_hook, (void *)config);
|
237
235
|
config->pid = getpid();
|
@@ -245,25 +243,42 @@ static Rotoscope *get_config(VALUE self) {
|
|
245
243
|
return config;
|
246
244
|
}
|
247
245
|
|
248
|
-
|
249
|
-
|
246
|
+
void copy_blacklist(Rotoscope *config, VALUE blacklist) {
|
247
|
+
Check_Type(blacklist, T_ARRAY);
|
248
|
+
|
249
|
+
size_t blacklist_malloc_size =
|
250
|
+
RARRAY_LEN(blacklist) * sizeof(*config->blacklist);
|
251
|
+
|
252
|
+
for (long i = 0; i < RARRAY_LEN(blacklist); i++) {
|
253
|
+
VALUE ruby_string = RARRAY_AREF(blacklist, i);
|
254
|
+
Check_Type(ruby_string, T_STRING);
|
255
|
+
blacklist_malloc_size += RSTRING_LEN(ruby_string) + 1;
|
256
|
+
}
|
257
|
+
|
258
|
+
config->blacklist = ruby_xmalloc(blacklist_malloc_size);
|
259
|
+
config->blacklist_size = RARRAY_LEN(blacklist);
|
260
|
+
char *str = (char *)(config->blacklist + config->blacklist_size);
|
261
|
+
|
262
|
+
for (unsigned long i = 0; i < config->blacklist_size; i++) {
|
263
|
+
VALUE ruby_string = RARRAY_AREF(blacklist, i);
|
264
|
+
|
265
|
+
config->blacklist[i] = str;
|
266
|
+
memcpy(str, RSTRING_PTR(ruby_string), RSTRING_LEN(ruby_string));
|
267
|
+
str += RSTRING_LEN(ruby_string);
|
268
|
+
*str = '\0';
|
269
|
+
str++;
|
270
|
+
}
|
250
271
|
}
|
251
272
|
|
252
273
|
VALUE initialize(int argc, VALUE *argv, VALUE self) {
|
253
274
|
Rotoscope *config = get_config(self);
|
254
|
-
VALUE output_path,
|
275
|
+
VALUE output_path, blacklist, flatten;
|
255
276
|
|
256
|
-
rb_scan_args(argc, argv, "12", &output_path, &
|
277
|
+
rb_scan_args(argc, argv, "12", &output_path, &blacklist, &flatten);
|
257
278
|
Check_Type(output_path, T_STRING);
|
258
279
|
|
259
|
-
if (!NIL_P(
|
260
|
-
|
261
|
-
config->entity_whitelist = rb_hash_new();
|
262
|
-
for (long i = 0; i < RARRAY_LEN(entity_whitelist); i++) {
|
263
|
-
VALUE item = RARRAY_AREF(entity_whitelist, i);
|
264
|
-
Check_Type(item, T_STRING);
|
265
|
-
rb_hash_aset(config->entity_whitelist, item, Qtrue);
|
266
|
-
}
|
280
|
+
if (!NIL_P(blacklist)) {
|
281
|
+
copy_blacklist(config, blacklist);
|
267
282
|
}
|
268
283
|
|
269
284
|
config->flatten_output = RTEST(flatten);
|
@@ -281,7 +296,7 @@ VALUE initialize(int argc, VALUE *argv, VALUE self) {
|
|
281
296
|
else
|
282
297
|
write_csv_header(config->log, RS_CSV_HEADER);
|
283
298
|
|
284
|
-
rs_stack_init(&config->stack, STACK_CAPACITY
|
299
|
+
rs_stack_init(&config->stack, STACK_CAPACITY);
|
285
300
|
config->call_memo = NULL;
|
286
301
|
config->state = RS_OPEN;
|
287
302
|
return self;
|
@@ -299,7 +314,7 @@ VALUE rotoscope_stop_trace(VALUE self) {
|
|
299
314
|
if (rb_tracepoint_enabled_p(config->tracepoint)) {
|
300
315
|
rb_tracepoint_disable(config->tracepoint);
|
301
316
|
config->state = RS_OPEN;
|
302
|
-
rs_stack_reset(&config->stack
|
317
|
+
rs_stack_reset(&config->stack);
|
303
318
|
}
|
304
319
|
|
305
320
|
return Qnil;
|
data/ext/rotoscope/rotoscope.h
CHANGED
data/ext/rotoscope/stack.c
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
#include "ruby.h"
|
6
6
|
#include "tracepoint.h"
|
7
7
|
|
8
|
-
static void insert_root_node(rs_stack_t *stack
|
8
|
+
static void insert_root_node(rs_stack_t *stack) {
|
9
9
|
VALUE rb_unknown_str = rb_str_new_cstr(UNKNOWN_STR);
|
10
10
|
rs_tracepoint_t root_trace =
|
11
11
|
(rs_tracepoint_t){.event = UNKNOWN_STR,
|
@@ -14,7 +14,7 @@ static void insert_root_node(rs_stack_t *stack, bool blacklisted) {
|
|
14
14
|
.method_name = rb_unknown_str,
|
15
15
|
.method_level = UNKNOWN_STR,
|
16
16
|
.lineno = 0};
|
17
|
-
rs_stack_push(stack, root_trace,
|
17
|
+
rs_stack_push(stack, root_trace, false);
|
18
18
|
}
|
19
19
|
|
20
20
|
static void resize_buffer(rs_stack_t *stack) {
|
@@ -37,10 +37,8 @@ rs_stack_frame_t rs_stack_push(rs_stack_t *stack, rs_tracepoint_t trace,
|
|
37
37
|
resize_buffer(stack);
|
38
38
|
}
|
39
39
|
|
40
|
-
rs_stack_frame_t
|
41
|
-
|
42
|
-
rs_stack_frame_t new_frame = (rs_stack_frame_t){
|
43
|
-
.tp = trace, .caller = caller, .blacklisted = blacklisted};
|
40
|
+
rs_stack_frame_t new_frame =
|
41
|
+
(rs_stack_frame_t){.tp = trace, .blacklisted = blacklisted};
|
44
42
|
|
45
43
|
stack->contents[++stack->top] = new_frame;
|
46
44
|
return new_frame;
|
@@ -64,9 +62,21 @@ rs_stack_frame_t *rs_stack_peek(rs_stack_t *stack) {
|
|
64
62
|
return &stack->contents[stack->top];
|
65
63
|
}
|
66
64
|
|
67
|
-
|
65
|
+
rs_stack_frame_t *rs_stack_below(rs_stack_t *stack, rs_stack_frame_t *frame) {
|
66
|
+
if (frame < stack->contents || frame > stack->contents + stack->top) {
|
67
|
+
fprintf(stderr, "Invalid stack frame (bottom: %p, frame: %p, top: %p)\n",
|
68
|
+
stack->contents, frame, &stack->contents[stack->top]);
|
69
|
+
exit(1);
|
70
|
+
} else if (stack->contents == frame) {
|
71
|
+
return NULL;
|
72
|
+
} else {
|
73
|
+
return frame - 1;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
void rs_stack_reset(rs_stack_t *stack) {
|
68
78
|
stack->top = -1;
|
69
|
-
insert_root_node(stack
|
79
|
+
insert_root_node(stack);
|
70
80
|
}
|
71
81
|
|
72
82
|
void rs_stack_free(rs_stack_t *stack) {
|
@@ -76,14 +86,13 @@ void rs_stack_free(rs_stack_t *stack) {
|
|
76
86
|
stack->capacity = 0;
|
77
87
|
}
|
78
88
|
|
79
|
-
void rs_stack_init(rs_stack_t *stack, unsigned int capacity
|
80
|
-
bool blacklisted_root) {
|
89
|
+
void rs_stack_init(rs_stack_t *stack, unsigned int capacity) {
|
81
90
|
rs_stack_frame_t *contents = ALLOC_N(rs_stack_frame_t, capacity);
|
82
91
|
stack->contents = contents;
|
83
92
|
stack->capacity = capacity;
|
84
93
|
stack->top = -1;
|
85
94
|
|
86
|
-
insert_root_node(stack
|
95
|
+
insert_root_node(stack);
|
87
96
|
}
|
88
97
|
|
89
98
|
void rs_stack_mark(rs_stack_t *stack) {
|
data/ext/rotoscope/stack.h
CHANGED
@@ -8,7 +8,6 @@
|
|
8
8
|
typedef struct rs_stack_frame_t {
|
9
9
|
struct rs_tracepoint_t tp;
|
10
10
|
bool blacklisted;
|
11
|
-
struct rs_stack_frame_t *caller;
|
12
11
|
} rs_stack_frame_t;
|
13
12
|
|
14
13
|
typedef struct {
|
@@ -17,14 +16,15 @@ typedef struct {
|
|
17
16
|
rs_stack_frame_t *contents;
|
18
17
|
} rs_stack_t;
|
19
18
|
|
20
|
-
void rs_stack_init(rs_stack_t *stack, unsigned int capacity
|
21
|
-
void rs_stack_reset(rs_stack_t *stack
|
19
|
+
void rs_stack_init(rs_stack_t *stack, unsigned int capacity);
|
20
|
+
void rs_stack_reset(rs_stack_t *stack);
|
22
21
|
void rs_stack_free(rs_stack_t *stack);
|
23
22
|
rs_stack_frame_t rs_stack_push(rs_stack_t *stack, rs_tracepoint_t trace, bool backlisted);
|
24
23
|
bool rs_stack_empty(rs_stack_t *stack);
|
25
24
|
bool rs_stack_full(rs_stack_t *stack);
|
26
25
|
rs_stack_frame_t rs_stack_pop(rs_stack_t *stack);
|
27
26
|
rs_stack_frame_t *rs_stack_peek(rs_stack_t *stack);
|
27
|
+
rs_stack_frame_t *rs_stack_below(rs_stack_t *stack, rs_stack_frame_t *frame);
|
28
28
|
void rs_stack_mark(rs_stack_t *stack);
|
29
29
|
|
30
30
|
#endif
|
data/lib/rotoscope.rb
CHANGED
@@ -6,12 +6,12 @@ require 'csv'
|
|
6
6
|
|
7
7
|
class Rotoscope
|
8
8
|
class << self
|
9
|
-
def new(output_path,
|
10
|
-
super(output_path,
|
9
|
+
def new(output_path, blacklist: [], flatten: false)
|
10
|
+
super(output_path, blacklist, flatten)
|
11
11
|
end
|
12
12
|
|
13
|
-
def trace(dest,
|
14
|
-
config = {
|
13
|
+
def trace(dest, blacklist: [], flatten: false, &block)
|
14
|
+
config = { blacklist: blacklist, flatten: flatten }
|
15
15
|
if dest.is_a?(String)
|
16
16
|
event_trace(dest, config, &block)
|
17
17
|
else
|
@@ -45,7 +45,7 @@ class Rotoscope
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def event_trace(dest_path, config)
|
48
|
-
rs = Rotoscope.new(dest_path,
|
48
|
+
rs = Rotoscope.new(dest_path, blacklist: config[:blacklist], flatten: config[:flatten])
|
49
49
|
rs.trace { yield rs }
|
50
50
|
rs
|
51
51
|
ensure
|
data/lib/rotoscope/version.rb
CHANGED