fast_method_source 0.1.1 → 0.2.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
  SHA1:
3
- metadata.gz: 8a8566fbdf9afc48e1122cd29d4ee799a455fd10
4
- data.tar.gz: 3894ea5f9ab5e1b784b8c64078accf4b309323fb
3
+ metadata.gz: 5d4abbc77bfa1ddd3f7d8c335e4ed45de99d1d6f
4
+ data.tar.gz: 412abc3f1f3278f2a25041e3dcfc689e4c00b83d
5
5
  SHA512:
6
- metadata.gz: 7ebf626281536e5d5ec319bc5bf3eb820cfa2e1191f07c5d7d7b94afcc1de95a0be63acafd01bbc93800e53753c399527243a27cd9e372da28b05a5133dc1557
7
- data.tar.gz: f6a255e157ba75498e4b1005d462c9851da0c762cb9b81b096f754051b5e9ba056687c7ccc590e9229fda724928f37b1ba49ab35e42138e2737ac37b78a165a3
6
+ metadata.gz: 15c8a178256a9f168e2a2bf49a0f7a2dcba1a968664c1887d642de15685bf446d0b020eceb8fc322a1bb9e3172c158c2b28c3dc294ac8e46cc8c2406e7e479e6
7
+ data.tar.gz: 2930a5f50f0cf4d7b8745d0b44ca377a312cd06bdde2944ba38686fe782c7ec1fb0d232be6dd535e547aa4214a9f8528734882ed9d9820becf4a255e2c66c20d
@@ -1,6 +1,13 @@
1
1
  Fast Method Source changelog
2
2
  ============================
3
3
 
4
+ ### v0.2.0 (June 11, 2015)
5
+
6
+ * Significantly reduced memory consumption
7
+ * The time of calculations has increased by 6%
8
+ * Fixed memory not being freed on exceptions
9
+ * Fixed exit code value for shells [→](https://github.com/kyrylo/fast_method_source/pull/2)
10
+
4
11
  ### v0.1.1 (June 9, 2015)
5
12
 
6
13
  * Fixed segfault on any C method query
data/README.md CHANGED
@@ -63,13 +63,9 @@ This is a utility method and method_source doesn't feature it.
63
63
  Processor: Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
64
64
  Platform: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
65
65
  Counting the number of sample methods...
66
- Sample methods: 19439
67
- Rehearsal ---------------------------------------------------------------------------
68
- FastMethodSource#comment_and_source_for 24.080000 1.900000 25.980000 ( 28.425889)
69
- ----------------------------------------------------------------- total: 25.980000sec
70
-
71
- user system total real
72
- FastMethodSource#comment_and_source_for 23.130000 1.710000 24.840000 ( 27.097578)
66
+ Sample methods: 19438
67
+ user system total real
68
+ FastMethodSource#comment_and_source_for 26.050000 1.420000 27.470000 ( 30.528066)
73
69
  ```
74
70
 
75
71
  #### #source
@@ -79,15 +75,15 @@ FastMethodSource#comment_and_source_for 23.130000 1.710000 24.840000 ( 27.09
79
75
  Processor: Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
80
76
  Platform: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
81
77
  Counting the number of sample methods...
82
- Sample methods: 19438
83
- Rehearsal -----------------------------------------------------------
84
- FastMethodSource#source 18.760000 1.290000 20.050000 ( 21.802014)
85
- MethodSource#source 100.100000 0.440000 100.540000 (122.748676)
86
- ------------------------------------------------ total: 120.590000sec
78
+ Sample methods: 19596
79
+ Rehearsal ------------------------------------------------------------
80
+ FastMethodSource#comment 4.730000 0.300000 5.030000 ( 5.590186)
81
+ MethodSource#comment 73.660000 0.340000 74.000000 ( 89.475399)
82
+ -------------------------------------------------- total: 79.030000sec
87
83
 
88
- user system total real
89
- FastMethodSource#source 19.040000 1.170000 20.210000 ( 22.079805)
90
- MethodSource#source 92.740000 0.300000 93.040000 (103.833941)
84
+ user system total real
85
+ FastMethodSource#comment 4.450000 0.300000 4.750000 ( 5.278761)
86
+ MethodSource#comment 69.880000 0.110000 69.990000 ( 77.663383)
91
87
  ```
92
88
 
93
89
  #### #comment
@@ -97,15 +93,15 @@ MethodSource#source 92.740000 0.300000 93.040000 (103.833941)
97
93
  Processor: Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
98
94
  Platform: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
99
95
  Counting the number of sample methods...
100
- Sample methods: 19595
101
- Rehearsal ------------------------------------------------------------
102
- FastMethodSource#comment 4.120000 0.520000 4.640000 ( 5.188443)
103
- MethodSource#comment 82.480000 0.330000 82.810000 (103.135012)
104
- -------------------------------------------------- total: 87.450000sec
96
+ Sample methods: 19438
97
+ Rehearsal -----------------------------------------------------------
98
+ FastMethodSource#source 20.610000 1.290000 21.900000 ( 24.341358)
99
+ MethodSource#source 92.730000 0.470000 93.200000 (111.384362)
100
+ ------------------------------------------------ total: 115.100000sec
105
101
 
106
- user system total real
107
- FastMethodSource#comment 3.580000 0.370000 3.950000 ( 4.398557)
108
- MethodSource#comment 73.390000 0.150000 73.540000 ( 81.880220)
102
+ user system total real
103
+ FastMethodSource#source 20.990000 1.150000 22.140000 ( 24.612721)
104
+ MethodSource#source 86.390000 0.290000 86.680000 ( 96.241494)
109
105
  ```
110
106
 
111
107
  ### Correctness of output
@@ -133,18 +129,17 @@ Output.
133
129
 
134
130
  ### RAM consumption
135
131
 
136
- Memory consumption is considerably higher for Fast Method Source (for the
137
- benchmarks it used about 800-1500 MB of RES RAM). In fact, since the library is
138
- very young, it *may* have memory leaks.
132
+ The [`comment_and_source`](/benchmarks/comment_and_source_for.rb) benchmark
133
+ shows that at this moment the library uses about 450 MB of RAM.
139
134
 
140
135
  API
141
136
  ---
142
137
 
143
138
  ### General description
144
139
 
145
- The library provides two methods `#source` and `#comment`. There are two ways to
146
- use Fast Method Source. One way is to monkey-patch relevant core Ruby classes
147
- and use the methods directly.
140
+ The library provides the following methods: `#comment`, `#source` and
141
+ `#comment_and_source`. There are two ways to use Fast Method Source. One way is
142
+ to monkey-patch relevant core Ruby classes and use the methods directly.
148
143
 
149
144
  ```ruby
150
145
  require 'fast_method_source'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
@@ -1,5 +1,5 @@
1
1
  require 'mkmf'
2
2
 
3
- $CFLAGS << ' -std=c99 -Wno-declaration-after-statement'
3
+ $CFLAGS << ' -std=c99 -Wno-declaration-after-statement -O3'
4
4
 
5
5
  create_makefile('fast_method_source/fast_method_source')
@@ -1,31 +1,96 @@
1
- #include "fast_method_source.h"
1
+ // For getline(), fileno() and friends
2
+ #define _XOPEN_SOURCE 700
3
+
4
+ #include <stdio.h>
5
+ #include <stdlib.h>
6
+ #include <ruby.h>
7
+
8
+ #include "node.h"
9
+
10
+ #ifdef _WIN32
11
+ #include <io.h>
12
+ static const char *null_filename = "NUL";
13
+ #define DUP(fd) _dup(fd)
14
+ #define DUP2(fd, newfd) _dup2(fd, newfd)
15
+ #else
16
+ #include <unistd.h>
17
+ static const char *null_filename = "/dev/null";
18
+ #define DUP(fd) dup(fd)
19
+ #define DUP2(fd, newfd) dup2(fd, newfd)
20
+ #endif
21
+
22
+ #define MAXLINES 600
23
+ #define MAXLINELEN 90
24
+ #define COMMENT_SIZE 1000
25
+ #define SAFE_CHAR 'z'
26
+
27
+ typedef struct {
28
+ int forward : 1;
29
+ int backward : 1;
30
+ } read_order;
31
+
32
+ struct filebuf {
33
+ unsigned method_location;
34
+ const char *filename;
35
+ VALUE method_name;
36
+ char **lines;
37
+ unsigned relevant_lines;
38
+ };
39
+
40
+ struct retval {
41
+ VALUE val;
42
+ VALUE method_name;
43
+ };
44
+
45
+ static void read_lines(read_order order, struct filebuf *filebuf);
46
+ static void read_lines_before(struct filebuf *filebuf);
47
+ static void read_lines_after(struct filebuf *filebuf);
48
+ static void reallocate_filebuf(char **lines[], unsigned rl_len);
49
+ static void reallocate_linebuf(char **linebuf, const unsigned cl_len);
50
+ static VALUE find_source(struct filebuf *filebuf);
51
+ static VALUE find_comment(struct filebuf *filebuf);
52
+ static VALUE mMethodExtensions_source(VALUE self);
53
+ static NODE *parse_expr(VALUE rb_str);
54
+ static NODE *parse_with_silenced_stderr(VALUE rb_str);
55
+ static void filter_interp(char *line);
56
+ static char **allocate_memory_for_file(void);
57
+ static void free_memory_for_file(char **file[], const unsigned relevant_lines_n);
58
+ static int contains_end_kw(const char *line);
59
+ static int is_comment(const char *line, const size_t line_len);
60
+ static int is_static_definition(const char *line);
61
+ static int is_accessor(const char *line);
62
+ static int is_dangling_literal_end(const char *line);
63
+ static int is_dangling_literal_begin(const char *line);
64
+ static void strnprep(char *s, const char *t, size_t len);
65
+ static void raise_if_nil(VALUE val, VALUE method_name);
66
+ static VALUE raise_if_nil_safe(VALUE args);
67
+ static void realloc_comment(char **comment, unsigned len);
68
+ static void filebuf_init(VALUE self, struct filebuf *filebuf);
69
+ static void free_filebuf(VALUE retval, struct filebuf *filebuf);
2
70
 
3
71
  static VALUE rb_eSourceNotFoundError;
4
72
 
5
- static unsigned
6
- read_lines_after(const unsigned method_location,
7
- const char *filename, char **filebuf[])
73
+ static void
74
+ read_lines_after(struct filebuf *filebuf)
8
75
  {
9
76
  read_order order = {1, 0};
10
- return read_lines(order, method_location, filename, filebuf);
77
+ read_lines(order, filebuf);
11
78
  }
12
79
 
13
- static unsigned
14
- read_lines_before(const unsigned method_location,
15
- const char *filename, char **filebuf[])
80
+ static void
81
+ read_lines_before(struct filebuf *filebuf)
16
82
  {
17
83
  read_order order = {0, 1};
18
- return read_lines(order, method_location, filename, filebuf);
84
+ read_lines(order, filebuf);
19
85
  }
20
86
 
21
- static unsigned
22
- read_lines(read_order order, const unsigned method_location,
23
- const char *filename, char **filebuf[])
87
+ static void
88
+ read_lines(read_order order, struct filebuf *filebuf)
24
89
  {
25
90
  FILE *fp;
26
91
 
27
- if ((fp = fopen(filename, "r")) == NULL) {
28
- rb_raise(rb_eIOError, "No such file or directory - %s", filename);
92
+ if ((fp = fopen(filebuf->filename, "r")) == NULL) {
93
+ rb_raise(rb_eIOError, "No such file or directory - %s", filebuf->filename);
29
94
  }
30
95
 
31
96
  ssize_t cl_len;
@@ -39,20 +104,20 @@ read_lines(read_order order, const unsigned method_location,
39
104
  while ((cl_len = getline(&current_line, &current_linebuf_size, fp)) != -1) {
40
105
  line_count++;
41
106
  if (order.forward) {
42
- if (line_count < method_location) {
107
+ if (line_count < filebuf->method_location) {
43
108
  continue;
44
109
  }
45
110
  } else if (order.backward) {
46
- if (line_count > method_location) {
111
+ if (line_count > filebuf->method_location) {
47
112
  break;
48
113
  }
49
114
  }
50
115
 
51
116
  if ((rl_n != 0) && (rl_n % (MAXLINES-1) == 0)) {
52
- reallocate_filebuf(filebuf, rl_n);
117
+ reallocate_filebuf(&filebuf->lines, rl_n);
53
118
  }
54
119
 
55
- current_linebuf = &(*filebuf)[rl_n];
120
+ current_linebuf = &(filebuf->lines)[rl_n];
56
121
 
57
122
  if (cl_len >= MAXLINELEN) {
58
123
  reallocate_linebuf(current_linebuf, cl_len);
@@ -65,19 +130,13 @@ read_lines(read_order order, const unsigned method_location,
65
130
 
66
131
  free(current_line);
67
132
  fclose(fp);
68
-
69
- return rl_n;
133
+ filebuf->relevant_lines = rl_n;
70
134
  }
71
135
 
72
136
  static void
73
137
  reallocate_linebuf(char **linebuf, const unsigned cl_len)
74
138
  {
75
- char *tmp_line;
76
-
77
- if ((tmp_line = realloc(*linebuf, cl_len + 1)) == NULL) {
78
- rb_raise(rb_eNoMemError, "failed to allocate memory");
79
- }
80
-
139
+ char *tmp_line = REALLOC_N(*linebuf, char, cl_len + 1);
81
140
  *linebuf = tmp_line;
82
141
  }
83
142
 
@@ -85,26 +144,28 @@ static void
85
144
  reallocate_filebuf(char **lines[], unsigned rl_len)
86
145
  {
87
146
  unsigned new_size = rl_len + MAXLINES + 1;
88
- char **temp_lines = realloc(*lines, sizeof(*temp_lines) * new_size);
147
+ char **temp_lines = REALLOC_N(*lines, char *, new_size);
89
148
 
90
- if (temp_lines == NULL) {
91
- rb_raise(rb_eNoMemError, "failed to allocate memory");
92
- } else {
93
- *lines = temp_lines;
149
+ *lines = temp_lines;
94
150
 
95
- for (int i = 0; i < MAXLINES; i++) {
96
- if (((*lines)[rl_len + i] = malloc(sizeof(char) * MAXLINELEN)) == NULL) {
97
- rb_raise(rb_eNoMemError, "failed to allocate memory");
98
- }
99
- }
151
+ for (int i = 0; i < MAXLINES; i++) {
152
+ (*lines)[rl_len + i] = ALLOC_N(char, MAXLINELEN);
100
153
  }
101
154
  }
102
155
 
156
+ static void
157
+ realloc_comment(char **comment, unsigned len)
158
+ {
159
+ char *tmp_comment = REALLOC_N(*comment, char, len);
160
+ *comment = tmp_comment;
161
+ }
162
+
103
163
  static NODE *
104
164
  parse_with_silenced_stderr(VALUE rb_str)
105
165
  {
106
166
  int old_stderr;
107
167
  FILE *null_fd;
168
+ VALUE last_exception = rb_errinfo();
108
169
 
109
170
  old_stderr = DUP(STDERR_FILENO);
110
171
  fflush(stderr);
@@ -114,6 +175,7 @@ parse_with_silenced_stderr(VALUE rb_str)
114
175
  volatile VALUE vparser = rb_parser_new();
115
176
  NODE *node = rb_parser_compile_string(vparser, "-", rb_str, 1);
116
177
  rb_str_free(rb_str);
178
+ rb_set_errinfo(last_exception);
117
179
 
118
180
  fflush(stderr);
119
181
  fclose(null_fd);
@@ -221,22 +283,22 @@ is_dangling_literal_begin(const char *line)
221
283
  }
222
284
 
223
285
  static VALUE
224
- find_source(char **filebuf[], const unsigned relevant_lines_n)
286
+ find_source(struct filebuf *filebuf)
225
287
  {
226
288
  VALUE rb_expr;
227
289
 
228
- const unsigned expr_size = relevant_lines_n * MAXLINELEN;
229
- char *expr = malloc(expr_size);
290
+ const unsigned expr_size = filebuf->relevant_lines * MAXLINELEN;
291
+ char *expr = ALLOC_N(char, expr_size);
230
292
  expr[0] = '\0';
231
- char *parseable_expr = malloc(expr_size);
293
+ char *parseable_expr = ALLOC_N(char, expr_size);
232
294
  parseable_expr[0] = '\0';
233
295
 
234
296
  int l = 0;
235
- while ((*filebuf)[l][0] == '\n') {
297
+ while (filebuf->lines[l][0] == '\n') {
236
298
  l++;
237
299
  continue;
238
300
  }
239
- char *first_line = (*filebuf)[l];
301
+ char *first_line = (filebuf->lines)[l];
240
302
 
241
303
  char *current_line = NULL;
242
304
  int should_parse = 0;
@@ -247,8 +309,8 @@ find_source(char **filebuf[], const unsigned relevant_lines_n)
247
309
  should_parse = 1;
248
310
  }
249
311
 
250
- for (unsigned i = l; i < relevant_lines_n; i++) {
251
- current_line = (*filebuf)[i];
312
+ for (unsigned i = l; i < filebuf->relevant_lines; i++) {
313
+ current_line = filebuf->lines[i];
252
314
  current_line_len = strlen(current_line);
253
315
 
254
316
  strncat(expr, current_line, current_line_len);
@@ -270,16 +332,15 @@ find_source(char **filebuf[], const unsigned relevant_lines_n)
270
332
  if (should_parse || contains_end_kw(current_line)) {
271
333
  if (parse_expr(rb_str_new2(parseable_expr)) != NULL) {
272
334
  rb_expr = rb_str_new2(expr);
273
- free(expr);
274
- free(parseable_expr);
335
+ xfree(expr);
336
+ xfree(parseable_expr);
275
337
  return rb_expr;
276
338
  }
277
339
  }
278
340
  }
279
341
 
280
- free(expr);
281
- free(parseable_expr);
282
- free_memory_for_file(filebuf, relevant_lines_n);
342
+ xfree(expr);
343
+ xfree(parseable_expr);
283
344
 
284
345
  return Qnil;
285
346
  }
@@ -297,47 +358,58 @@ strnprep(char *s, const char *t, size_t len)
297
358
  }
298
359
 
299
360
  static VALUE
300
- find_comment(char **filebuf[], const unsigned method_location,
301
- const unsigned relevant_lines_n)
361
+ find_comment(struct filebuf *filebuf)
302
362
  {
303
- char comment[COMMENT_SIZE];
363
+ size_t comment_len;
364
+ size_t current_line_len;
365
+ size_t future_bufsize;
366
+ char *current_line = NULL;
367
+ VALUE rb_comment;
368
+
369
+ unsigned long bufsize = COMMENT_SIZE;
370
+ char *comment = ALLOC_N(char, COMMENT_SIZE);
304
371
  comment[0] = '\0';
305
372
 
306
- int i = method_location - 2;
373
+ int i = filebuf->method_location - 2;
307
374
 
308
- while ((*filebuf)[i][0] == '\n') {
375
+ while (filebuf->lines[i][0] == '\n') {
309
376
  i--;
310
377
  continue;
311
378
  }
312
379
 
313
- if (!is_comment((*filebuf)[i], strlen((*filebuf)[i]))) {
380
+ if (!is_comment(filebuf->lines[i], strlen(filebuf->lines[i]))) {
314
381
  return rb_str_new("", 0);
315
382
  } else {
316
- while (is_comment((*filebuf)[i], strlen((*filebuf)[i]))) {
317
- strnprep(comment, (*filebuf)[i], strlen((*filebuf)[i]));
383
+ while ((current_line = filebuf->lines[i]) &&
384
+ is_comment(current_line, (current_line_len = strlen(current_line)))) {
385
+ comment_len = strlen(comment);
386
+ future_bufsize = comment_len + current_line_len;
387
+
388
+ if (future_bufsize >= bufsize) {
389
+ bufsize = future_bufsize + COMMENT_SIZE + 1;
390
+ realloc_comment(&comment, bufsize);
391
+ }
392
+ strnprep(comment, current_line, current_line_len);
318
393
  i--;
319
394
  }
320
395
 
321
- return rb_str_new2(comment);
396
+ rb_comment = rb_str_new2(comment);
397
+ xfree(comment);
398
+ return rb_comment;
322
399
  }
323
400
 
324
- free_memory_for_file(filebuf, relevant_lines_n);
401
+ xfree(comment);
402
+ free_memory_for_file(&filebuf->lines, filebuf->relevant_lines);
325
403
  return Qnil;
326
404
  }
327
405
 
328
406
  static char **
329
407
  allocate_memory_for_file(void)
330
408
  {
331
- char **file;
332
-
333
- if ((file = malloc(sizeof(*file) * MAXLINES)) == NULL) {
334
- rb_raise(rb_eNoMemError, "failed to allocate memory");
335
- }
409
+ char **file = ALLOC_N(char *, MAXLINES);
336
410
 
337
411
  for (int i = 0; i < MAXLINES; i++) {
338
- if ((file[i] = malloc(sizeof(char) * MAXLINELEN)) == NULL) {
339
- rb_raise(rb_eNoMemError, "failed to allocate memory");
340
- };
412
+ file[i] = ALLOC_N(char, MAXLINELEN);
341
413
  }
342
414
 
343
415
  return file;
@@ -349,78 +421,94 @@ free_memory_for_file(char **file[], const unsigned relevant_lines_n)
349
421
  int lines_to_free = relevant_lines_n >= MAXLINES ? relevant_lines_n : MAXLINES;
350
422
 
351
423
  for (int i = 0; i < lines_to_free; i++) {
352
- free((*file)[i]);
424
+ xfree((*file)[i]);
353
425
  }
354
426
 
355
- free(*file);
427
+ xfree(*file);
428
+ }
429
+
430
+ static VALUE
431
+ raise_if_nil_safe(VALUE args)
432
+ {
433
+ struct retval *retval = (struct retval *) args;
434
+ raise_if_nil(retval->val, retval->method_name);
435
+
436
+ return Qnil;
356
437
  }
357
438
 
358
439
  static void
359
- check_if_nil(VALUE val, VALUE name)
440
+ raise_if_nil(VALUE val, VALUE method_name)
360
441
  {
361
442
  if (NIL_P(val)) {
362
443
  rb_raise(rb_eSourceNotFoundError, "could not locate source for %s",
363
- RSTRING_PTR(rb_sym2str(name)));
444
+ RSTRING_PTR(rb_sym2str(method_name)));
364
445
  }
365
446
  }
366
447
 
367
- static VALUE
368
- mMethodExtensions_source(VALUE self)
448
+ static void
449
+ filebuf_init(VALUE self, struct filebuf *filebuf)
369
450
  {
370
451
  VALUE source_location = rb_funcall(self, rb_intern("source_location"), 0);
371
452
  VALUE name = rb_funcall(self, rb_intern("name"), 0);
372
453
 
373
- check_if_nil(source_location, name);
454
+ raise_if_nil(source_location, name);
374
455
 
375
456
  VALUE rb_filename = RARRAY_AREF(source_location, 0);
376
457
  VALUE rb_method_location = RARRAY_AREF(source_location, 1);
377
458
 
378
- check_if_nil(rb_filename, name);
379
- check_if_nil(rb_method_location, name);
459
+ raise_if_nil(rb_filename, name);
460
+ raise_if_nil(rb_method_location, name);
380
461
 
381
- const char *filename = RSTRING_PTR(rb_filename);
382
- const unsigned method_location = FIX2INT(rb_method_location);
462
+ filebuf->filename = RSTRING_PTR(rb_filename);
463
+ filebuf->method_location = FIX2INT(rb_method_location);
464
+ filebuf->method_name = name;
465
+ filebuf->lines = allocate_memory_for_file();
466
+ }
383
467
 
384
- char **filebuf = allocate_memory_for_file();
385
- const unsigned relevant_lines_n = read_lines_after(method_location,
386
- filename, &filebuf);
387
- VALUE source = find_source(&filebuf, relevant_lines_n);
468
+ static void
469
+ free_filebuf(VALUE val, struct filebuf *filebuf)
470
+ {
471
+ int failed;
472
+ struct retval retval = {val, filebuf->method_name};
388
473
 
389
- check_if_nil(source, name);
390
- free_memory_for_file(&filebuf, relevant_lines_n);
474
+ rb_protect(raise_if_nil_safe, (VALUE) &retval, &failed);
475
+ free_memory_for_file(&filebuf->lines, filebuf->relevant_lines);
391
476
 
392
- return source;
477
+ if (failed) {
478
+ rb_jump_tag(failed);
479
+ }
393
480
  }
394
481
 
395
482
  static VALUE
396
- mMethodExtensions_comment(VALUE self)
483
+ mMethodExtensions_source(VALUE self)
397
484
  {
398
- VALUE source_location = rb_funcall(self, rb_intern("source_location"), 0);
399
- VALUE name = rb_funcall(self, rb_intern("name"), 0);
485
+ struct filebuf filebuf;
400
486
 
401
- check_if_nil(source_location, name);
487
+ filebuf_init(self, &filebuf);
488
+ read_lines_after(&filebuf);
402
489
 
403
- VALUE rb_filename = RARRAY_AREF(source_location, 0);
404
- VALUE rb_method_location = RARRAY_AREF(source_location, 1);
490
+ VALUE source = find_source(&filebuf);
491
+
492
+ free_filebuf(source, &filebuf);
493
+
494
+ return source;
495
+ }
405
496
 
406
- check_if_nil(rb_filename, name);
407
- check_if_nil(rb_method_location, name);
497
+ static VALUE
498
+ mMethodExtensions_comment(VALUE self)
499
+ {
500
+ struct filebuf filebuf;
408
501
 
409
- const char *filename = RSTRING_PTR(rb_filename);
410
- const unsigned method_location = FIX2INT(rb_method_location);
502
+ filebuf_init(self, &filebuf);
503
+ read_lines_before(&filebuf);
411
504
 
412
- char **filebuf = allocate_memory_for_file();
413
- const unsigned relevant_lines_n = read_lines_before(method_location,
414
- filename, &filebuf);
415
- VALUE comment = find_comment(&filebuf, method_location, relevant_lines_n);
505
+ VALUE comment = find_comment(&filebuf);
416
506
 
417
- check_if_nil(comment, name);
418
- free_memory_for_file(&filebuf, relevant_lines_n);
507
+ free_filebuf(comment, &filebuf);
419
508
 
420
509
  return comment;
421
510
  }
422
511
 
423
-
424
512
  void Init_fast_method_source(void)
425
513
  {
426
514
  VALUE rb_mFastMethodSource = rb_define_module_under(rb_cObject, "FastMethodSource");
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fast_method_source
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyrylo Silin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-09 00:00:00.000000000 Z
11
+ date: 2015-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,7 +80,6 @@ files:
80
80
  - VERSION
81
81
  - ext/fast_method_source/extconf.rb
82
82
  - ext/fast_method_source/fast_method_source.c
83
- - ext/fast_method_source/fast_method_source.h
84
83
  - ext/fast_method_source/node.h
85
84
  - lib/fast_method_source.rb
86
85
  - lib/fast_method_source/core_ext.rb
@@ -1,53 +0,0 @@
1
- #define _XOPEN_SOURCE 700
2
- #include <stdio.h>
3
- #include <stdlib.h>
4
- #include <ruby.h>
5
- #include "node.h"
6
-
7
- #ifdef _WIN32
8
- #include <io.h>
9
- static const char *null_filename = "NUL";
10
- #define DUP(fd) _dup(fd)
11
- #define DUP2(fd, newfd) _dup2(fd, newfd)
12
- #else
13
- #include <unistd.h>
14
- static const char *null_filename = "/dev/null";
15
- #define DUP(fd) dup(fd)
16
- #define DUP2(fd, newfd) dup2(fd, newfd)
17
- #endif
18
-
19
- #define MAXLINES 1000
20
- #define MAXLINELEN 300
21
- #define COMMENT_SIZE 15000
22
-
23
- typedef struct {
24
- int forward : 1;
25
- int backward : 1;
26
- } read_order;
27
-
28
- static unsigned read_lines(read_order order, const unsigned method_location,
29
- const char *filename, char **filebuf[]);
30
- static unsigned read_lines_before(const unsigned method_location,
31
- const char *filename, char **filebuf[]);
32
- static unsigned read_lines_after(const unsigned method_location,
33
- const char *filename, char **filebuf[]);
34
- static void reallocate_filebuf(char **lines[], unsigned rl_len);
35
- static void reallocate_linebuf(char **linebuf, const unsigned cl_len);
36
- static VALUE find_source(char **filebuf[], const unsigned relevant_lines_n);
37
- static VALUE find_comment(char **filebuf[], const unsigned relevant_lines_n,
38
- const unsigned method_location);
39
- static VALUE mMethodExtensions_source(VALUE self);
40
- static NODE *parse_expr(VALUE rb_str);
41
- static NODE *parse_with_silenced_stderr(VALUE rb_str);
42
- static void filter_interp(char *line);
43
- static char **allocate_memory_for_file(void);
44
- static void free_memory_for_file(char **file[], const unsigned relevant_lines_n);
45
- static int contains_end_kw(const char *line);
46
- static int is_comment(const char *line, const size_t line_len);
47
- static int is_static_definition(const char *line);
48
- static int is_accessor(const char *line);
49
- static int is_dangling_literal_end(const char *line);
50
- static int is_dangling_literal_begin(const char *line);
51
- static void strnprep(char *s, const char *t, size_t len);
52
-
53
- #define SAFE_CHAR 'z'