5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
# File 'ext/array_collapse/array_collapse.c', line 5
VALUE method_collapse(VALUE self, VALUE args) {
long len = RARRAY_LEN(self);
VALUE result = rb_ary_new2(len);
VALUE stack = rb_ary_new();
st_table *seen_nodes;
st_data_t id;
seen_nodes = st_init_numtable();
st_insert(seen_nodes, (st_data_t)self, (st_data_t)Qtrue);
#ifdef LOGGING
FILE *f = fopen("clog.txt", "w");
if (f == NULL) {
printf("no log file found\n");
exit(1);
}
fprintf(f, "len: %lu\n", len);
fprintf(f, "array: %s\n", RSTRING_PTR(rb_ary_to_s(self)));
#endif
rb_ary_push(stack,self);
while(RARRAY_LEN(stack) > 0) {
VALUE array = rb_ary_pop(stack);
long i;
for(i = 0; i < RARRAY_LEN(array); i++) {
VALUE e = RARRAY_AREF(array,i);
id = (st_data_t)e;
if (st_lookup(seen_nodes, id, 0)) {
// drop recursive node
break;
}
switch (TYPE(e)) {
case T_ARRAY:
st_insert(seen_nodes, id, (st_data_t)Qtrue);
rb_ary_push(stack, e);
break;
default:
if (rb_block_given_p()) {
e = rb_yield(e);
}
if (!NIL_P(e)) {
rb_ary_push(result, e);
}
break;
}
}
}
st_free_table(seen_nodes);
return result;
}
|