rotoscope 0.3.0.pre.3 → 0.3.0.pre.4
Sign up to get free protection for your applications and to get access to all the features.
- 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