DEFINITIONS
This source file includes following functions.
- rb_obj_freeze
- infect
- extract_range
- extract_beg_len
- strscan_mark
- strscan_free
- strscan_s_allocate
- strscan_initialize
- strscan_s_mustc
- strscan_reset
- strscan_terminate
- strscan_get_string
- strscan_set_string
- strscan_get_pos
- strscan_set_pos
- strscan_do_scan
- strscan_scan
- strscan_match_p
- strscan_skip
- strscan_check
- strscan_scan_full
- strscan_scan_until
- strscan_exist_p
- strscan_skip_until
- strscan_check_until
- strscan_search_full
- adjust_registers_to_matched
- strscan_getch
- strscan_get_byte
- strscan_peek
- strscan_unscan
- strscan_eos_p
- strscan_rest_p
- strscan_matched_p
- strscan_matched
- strscan_matched_size
- strscan_aref
- strscan_pre_match
- strscan_post_match
- strscan_rest
- strscan_rest_size
- strscan_inspect
- inspect_before
- inspect_after
- Init_strscan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 #include "ruby.h"
17 #include "re.h"
18 #include "version.h"
19
20 #if (RUBY_VERSION_CODE < 150)
21 # define rb_eRangeError rb_eArgError
22 # define rb_obj_freeze(obj) rb_str_freeze(obj)
23 #endif
24
25 #define STRSCAN_VERSION "0.7.0"
26
27
28
29
30
31 static VALUE StringScanner;
32 static VALUE ScanError;
33
34 struct strscanner
35 {
36
37 unsigned long flags;
38 #define FLAG_MATCHED (1 << 0)
39
40
41 VALUE str;
42
43
44 long prev;
45 long curr;
46
47
48 struct re_registers regs;
49 };
50
51 #define MATCHED_P(s) ((s)->flags & FLAG_MATCHED)
52 #define MATCHED(s) (s)->flags |= FLAG_MATCHED
53 #define CLEAR_MATCH_STATUS(s) (s)->flags &= ~FLAG_MATCHED
54
55 #define S_PTR(s) (RSTRING((s)->str)->ptr)
56 #define S_LEN(s) (RSTRING((s)->str)->len)
57 #define S_END(s) (S_PTR(s) + S_LEN(s))
58 #define CURPTR(s) (S_PTR(s) + (s)->curr)
59 #define S_RESTLEN(s) (S_LEN(s) - (s)->curr)
60
61 #define EOS_P(s) ((s)->curr >= RSTRING(p->str)->len)
62
63 #define GET_SCANNER(obj,var) do {\
64 Data_Get_Struct(obj, struct strscanner, var);\
65 if (NIL_P(var->str)) rb_raise(rb_eArgError, "uninitialized StringScanner object");\
66 } while (0)
67
68
69
70
71
72 static VALUE infect _((VALUE str, struct strscanner *p));
73 static VALUE extract_range _((struct strscanner *p, long beg_i, long end_i));
74 static VALUE extract_beg_len _((struct strscanner *p, long beg_i, long len));
75
76 static void strscan_mark _((struct strscanner *p));
77 static void strscan_free _((struct strscanner *p));
78 static VALUE strscan_s_allocate _((VALUE klass));
79 static VALUE strscan_initialize _((int argc, VALUE *argv, VALUE self));
80
81 static VALUE strscan_s_mustc _((VALUE self));
82 static VALUE strscan_terminate _((VALUE self));
83 static VALUE strscan_get_string _((VALUE self));
84 static VALUE strscan_set_string _((VALUE self, VALUE str));
85 static VALUE strscan_get_pos _((VALUE self));
86 static VALUE strscan_set_pos _((VALUE self, VALUE pos));
87 static VALUE strscan_do_scan _((VALUE self, VALUE regex,
88 int succptr, int getstr, int headonly));
89 static VALUE strscan_scan _((VALUE self, VALUE re));
90 static VALUE strscan_match_p _((VALUE self, VALUE re));
91 static VALUE strscan_skip _((VALUE self, VALUE re));
92 static VALUE strscan_check _((VALUE self, VALUE re));
93 static VALUE strscan_scan_full _((VALUE self, VALUE re,
94 VALUE succp, VALUE getp));
95 static VALUE strscan_scan_until _((VALUE self, VALUE re));
96 static VALUE strscan_skip_until _((VALUE self, VALUE re));
97 static VALUE strscan_check_until _((VALUE self, VALUE re));
98 static VALUE strscan_search_full _((VALUE self, VALUE re,
99 VALUE succp, VALUE getp));
100 static void adjust_registers_to_matched _((struct strscanner *p));
101 static VALUE strscan_getch _((VALUE self));
102 static VALUE strscan_get_byte _((VALUE self));
103 static VALUE strscan_peek _((VALUE self, VALUE len));
104 static VALUE strscan_unscan _((VALUE self));
105 static VALUE strscan_eos_p _((VALUE self));
106 static VALUE strscan_rest_p _((VALUE self));
107 static VALUE strscan_matched_p _((VALUE self));
108 static VALUE strscan_matched _((VALUE self));
109 static VALUE strscan_matched_size _((VALUE self));
110 static VALUE strscan_aref _((VALUE self, VALUE idx));
111 static VALUE strscan_pre_match _((VALUE self));
112 static VALUE strscan_post_match _((VALUE self));
113 static VALUE strscan_rest _((VALUE self));
114 static VALUE strscan_rest_size _((VALUE self));
115
116 static VALUE strscan_inspect _((VALUE self));
117 static char* inspect_before _((struct strscanner *p, char *buf));
118 static char* inspect_after _((struct strscanner *p, char *buf));
119
120
121
122
123
124 static VALUE
125 infect(str, p)
126 VALUE str;
127 struct strscanner *p;
128 {
129 OBJ_INFECT(str, p->str);
130 return str;
131 }
132
133 static VALUE
134 extract_range(p, beg_i, end_i)
135 struct strscanner *p;
136 long beg_i, end_i;
137 {
138 return infect(rb_str_new(S_PTR(p) + beg_i, end_i - beg_i), p);
139 }
140
141 static VALUE
142 extract_beg_len(p, beg_i, len)
143 struct strscanner *p;
144 long beg_i, len;
145 {
146 return infect(rb_str_new(S_PTR(p) + beg_i, len), p);
147 }
148
149
150
151
152
153
154
155 static void
156 strscan_mark(p)
157 struct strscanner *p;
158 {
159 rb_gc_mark(p->str);
160 }
161
162 static void
163 strscan_free(p)
164 struct strscanner *p;
165 {
166 re_free_registers(&(p->regs));
167 memset(p, sizeof(struct strscanner), 0);
168 free(p);
169 }
170
171 static VALUE
172 strscan_s_allocate(klass)
173 VALUE klass;
174 {
175 struct strscanner *p;
176
177 p = ALLOC(struct strscanner);
178 MEMZERO(p, struct strscanner, 1);
179 CLEAR_MATCH_STATUS(p);
180 MEMZERO(&(p->regs), struct re_registers, 1);
181 p->str = Qnil;
182 return Data_Wrap_Struct(klass, strscan_mark, strscan_free, p);
183 }
184
185 static VALUE
186 strscan_initialize(argc, argv, self)
187 int argc;
188 VALUE *argv;
189 VALUE self;
190 {
191 struct strscanner *p;
192 VALUE str, need_dup;
193
194 Data_Get_Struct(self, struct strscanner, p);
195 if (rb_scan_args(argc, argv, "11", &str, &need_dup) == 1)
196 need_dup = Qtrue;
197 StringValue(str);
198 p->str = RTEST(need_dup) ? rb_str_dup(str) : str;
199 rb_obj_freeze(p->str);
200
201 return self;
202 }
203
204
205
206
207
208
209 static VALUE
210 strscan_s_mustc(self)
211 VALUE self;
212 {
213 return self;
214 }
215
216 static VALUE
217 strscan_reset(self)
218 VALUE self;
219 {
220 struct strscanner *p;
221
222 GET_SCANNER(self, p);
223 p->curr = 0;
224 CLEAR_MATCH_STATUS(p);
225 return self;
226 }
227
228 static VALUE
229 strscan_terminate(self)
230 VALUE self;
231 {
232 struct strscanner *p;
233
234 GET_SCANNER(self, p);
235 p->curr = S_LEN(p);
236 CLEAR_MATCH_STATUS(p);
237 return self;
238 }
239
240 static VALUE
241 strscan_get_string(self)
242 VALUE self;
243 {
244 struct strscanner *p;
245
246 GET_SCANNER(self, p);
247 return p->str;
248 }
249
250 static VALUE
251 strscan_set_string(self, str)
252 VALUE self, str;
253 {
254 struct strscanner *p;
255
256 Data_Get_Struct(self, struct strscanner, p);
257 StringValue(str);
258 p->str = rb_str_dup(str);
259 rb_obj_freeze(p->str);
260 p->curr = 0;
261 CLEAR_MATCH_STATUS(p);
262 return str;
263 }
264
265 static VALUE
266 strscan_get_pos(self)
267 VALUE self;
268 {
269 struct strscanner *p;
270
271 GET_SCANNER(self, p);
272 return INT2FIX(p->curr);
273 }
274
275 static VALUE
276 strscan_set_pos(self, v)
277 VALUE self, v;
278 {
279 struct strscanner *p;
280 long i;
281
282 GET_SCANNER(self, p);
283 i = NUM2INT(v);
284 if (i < 0) i += S_LEN(p);
285 if (i < 0) rb_raise(rb_eRangeError, "index out of range");
286 if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range");
287 p->curr = i;
288 return INT2NUM(i);
289 }
290
291
292
293 #define strscan_prepare_re(re)
294
295 static VALUE
296 strscan_do_scan(self, regex, succptr, getstr, headonly)
297 VALUE self, regex;
298 int succptr, getstr, headonly;
299 {
300 struct strscanner *p;
301 int ret;
302
303 Check_Type(regex, T_REGEXP);
304 GET_SCANNER(self, p);
305
306 CLEAR_MATCH_STATUS(p);
307 strscan_prepare_re(regex);
308 if (headonly) {
309 ret = re_match(RREGEXP(regex)->ptr,
310 CURPTR(p), S_RESTLEN(p),
311 0,
312 &(p->regs));
313 }
314 else {
315 ret = re_search(RREGEXP(regex)->ptr,
316 CURPTR(p), S_RESTLEN(p),
317 0,
318 S_RESTLEN(p),
319 &(p->regs));
320 }
321
322 if (ret == -2) rb_raise(ScanError, "regexp buffer overflow");
323 if (ret < 0) {
324
325 return Qnil;
326 }
327
328 MATCHED(p);
329 p->prev = p->curr;
330 if (succptr) {
331 p->curr += p->regs.end[0];
332 }
333 if (getstr) {
334 return extract_beg_len(p, p->prev, p->regs.end[0]);
335 }
336 else {
337 return INT2FIX(p->regs.end[0]);
338 }
339 }
340
341 static VALUE
342 strscan_scan(self, re)
343 VALUE self, re;
344 {
345 return strscan_do_scan(self, re, 1, 1, 1);
346 }
347
348 static VALUE
349 strscan_match_p(self, re)
350 VALUE self, re;
351 {
352 return strscan_do_scan(self, re, 0, 0, 1);
353 }
354
355 static VALUE
356 strscan_skip(self, re)
357 VALUE self, re;
358 {
359 return strscan_do_scan(self, re, 1, 0, 1);
360 }
361
362 static VALUE
363 strscan_check(self, re)
364 VALUE self, re;
365 {
366 return strscan_do_scan(self, re, 0, 1, 1);
367 }
368
369 static VALUE
370 strscan_scan_full(self, re, s, f)
371 VALUE self, re, s, f;
372 {
373 return strscan_do_scan(self, re, RTEST(s), RTEST(f), 1);
374 }
375
376
377 static VALUE
378 strscan_scan_until(self, re)
379 VALUE self, re;
380 {
381 return strscan_do_scan(self, re, 1, 1, 0);
382 }
383
384 static VALUE
385 strscan_exist_p(self, re)
386 VALUE self, re;
387 {
388 return strscan_do_scan(self, re, 0, 0, 0);
389 }
390
391 static VALUE
392 strscan_skip_until(self, re)
393 VALUE self, re;
394 {
395 return strscan_do_scan(self, re, 1, 0, 0);
396 }
397
398 static VALUE
399 strscan_check_until(self, re)
400 VALUE self, re;
401 {
402 return strscan_do_scan(self, re, 0, 1, 0);
403 }
404
405 static VALUE
406 strscan_search_full(self, re, s, f)
407 VALUE self, re, s, f;
408 {
409 return strscan_do_scan(self, re, RTEST(s), RTEST(f), 0);
410 }
411
412
413 static void
414 adjust_registers_to_matched(p)
415 struct strscanner *p;
416 {
417 if (p->regs.allocated == 0) {
418 p->regs.beg = ALLOC_N(int, RE_NREGS);
419 p->regs.end = ALLOC_N(int, RE_NREGS);
420 p->regs.allocated = RE_NREGS;
421 }
422 p->regs.num_regs = 1;
423 p->regs.beg[0] = 0;
424 p->regs.end[0] = p->curr - p->prev;
425 }
426
427 static VALUE
428 strscan_getch(self)
429 VALUE self;
430 {
431 struct strscanner *p;
432 long len;
433
434 GET_SCANNER(self, p);
435 CLEAR_MATCH_STATUS(p);
436 if (EOS_P(p))
437 return Qnil;
438
439 len = mbclen(*CURPTR(p));
440 if (p->curr + len > S_LEN(p))
441 len = S_LEN(p) - p->curr;
442 p->prev = p->curr;
443 p->curr += len;
444 MATCHED(p);
445 adjust_registers_to_matched(p);
446 return extract_range(p, p->prev + p->regs.beg[0],
447 p->prev + p->regs.end[0]);
448 }
449
450 static VALUE
451 strscan_get_byte(self)
452 VALUE self;
453 {
454 struct strscanner *p;
455
456 GET_SCANNER(self, p);
457 CLEAR_MATCH_STATUS(p);
458 if (EOS_P(p))
459 return Qnil;
460
461 p->prev = p->curr;
462 p->curr++;
463 MATCHED(p);
464 adjust_registers_to_matched(p);
465 return extract_range(p, p->prev + p->regs.beg[0],
466 p->prev + p->regs.end[0]);
467 }
468
469
470 static VALUE
471 strscan_peek(self, vlen)
472 VALUE self, vlen;
473 {
474 struct strscanner *p;
475 long len;
476
477 GET_SCANNER(self, p);
478
479 len = NUM2LONG(vlen);
480 if (EOS_P(p))
481 return infect(rb_str_new("", 0), p);
482
483 if (p->curr + len > S_LEN(p))
484 len = S_LEN(p) - p->curr;
485 return extract_beg_len(p, p->curr, len);
486 }
487
488
489 static VALUE
490 strscan_unscan(self)
491 VALUE self;
492 {
493 struct strscanner *p;
494
495 GET_SCANNER(self, p);
496 if (! MATCHED_P(p))
497 rb_raise(ScanError, "cannot unscan: prev match had failed");
498
499 p->curr = p->prev;
500 CLEAR_MATCH_STATUS(p);
501 return self;
502 }
503
504
505 static VALUE
506 strscan_eos_p(self)
507 VALUE self;
508 {
509 struct strscanner *p;
510
511 GET_SCANNER(self, p);
512 if (EOS_P(p))
513 return Qtrue;
514 else
515 return Qfalse;
516 }
517
518 static VALUE
519 strscan_rest_p(self)
520 VALUE self;
521 {
522 struct strscanner *p;
523
524 GET_SCANNER(self, p);
525 if (EOS_P(p))
526 return Qfalse;
527 else
528 return Qtrue;
529 }
530
531
532 static VALUE
533 strscan_matched_p(self)
534 VALUE self;
535 {
536 struct strscanner *p;
537
538 GET_SCANNER(self, p);
539 if (MATCHED_P(p))
540 return Qtrue;
541 else
542 return Qfalse;
543 }
544
545 static VALUE
546 strscan_matched(self)
547 VALUE self;
548 {
549 struct strscanner *p;
550
551 GET_SCANNER(self, p);
552 if (! MATCHED_P(p)) return Qnil;
553
554 return extract_range(p, p->prev + p->regs.beg[0],
555 p->prev + p->regs.end[0]);
556 }
557
558 static VALUE
559 strscan_matched_size(self)
560 VALUE self;
561 {
562 struct strscanner *p;
563
564 GET_SCANNER(self, p);
565 if (! MATCHED_P(p)) return Qnil;
566
567 return INT2NUM(p->regs.end[0] - p->regs.beg[0]);
568 }
569
570 static VALUE
571 strscan_aref(self, idx)
572 VALUE self, idx;
573 {
574 struct strscanner *p;
575 long i;
576
577 GET_SCANNER(self, p);
578 if (! MATCHED_P(p)) return Qnil;
579
580 i = NUM2LONG(idx);
581 if (i < 0)
582 i += p->regs.num_regs;
583 if (i < 0) return Qnil;
584 if (i >= p->regs.num_regs) return Qnil;
585 if (p->regs.beg[i] == -1) return Qnil;
586
587 return extract_range(p, p->prev + p->regs.beg[i],
588 p->prev + p->regs.end[i]);
589 }
590
591 static VALUE
592 strscan_pre_match(self)
593 VALUE self;
594 {
595 struct strscanner *p;
596
597 GET_SCANNER(self, p);
598 if (! MATCHED_P(p)) return Qnil;
599
600 return extract_range(p, 0, p->prev + p->regs.beg[0]);
601 }
602
603 static VALUE
604 strscan_post_match(self)
605 VALUE self;
606 {
607 struct strscanner *p;
608
609 GET_SCANNER(self, p);
610 if (! MATCHED_P(p)) return Qnil;
611
612 return extract_range(p, p->prev + p->regs.end[0], S_LEN(p));
613 }
614
615
616 static VALUE
617 strscan_rest(self)
618 VALUE self;
619 {
620 struct strscanner *p;
621
622 GET_SCANNER(self, p);
623 if (EOS_P(p)) {
624 return infect(rb_str_new("", 0), p);
625 }
626 return extract_range(p, p->curr, S_LEN(p));
627 }
628
629 static VALUE
630 strscan_rest_size(self)
631 VALUE self;
632 {
633 struct strscanner *p;
634 long i;
635
636 GET_SCANNER(self, p);
637 if (EOS_P(p)) {
638 return INT2FIX(0);
639 }
640
641 i = S_LEN(p) - p->curr;
642 return INT2FIX(i);
643 }
644
645
646 #define INSPECT_LENGTH 5
647
648 static VALUE
649 strscan_inspect(self)
650 VALUE self;
651 {
652 struct strscanner *p;
653 char buf[256];
654 char buf_before[16];
655 char buf_after[16];
656 long len;
657
658 Data_Get_Struct(self, struct strscanner, p);
659 if (NIL_P(p->str)) {
660 len = sprintf(buf, "#<%s (uninitialized)>",
661 rb_class2name(CLASS_OF(self)));
662 return rb_str_new(buf, len);
663 }
664 if (EOS_P(p)) {
665 len = sprintf(buf, "#<%s fin>",
666 rb_class2name(CLASS_OF(self)));
667 return rb_str_new(buf, len);
668 }
669 len = sprintf(buf, "#<%s %ld/%ld %s@%s>",
670 rb_class2name(CLASS_OF(self)),
671 p->curr, S_LEN(p),
672 inspect_before(p, buf_before),
673 inspect_after(p, buf_after));
674 return rb_str_new(buf, len);
675 }
676
677 static char*
678 inspect_before(p, buf)
679 struct strscanner *p;
680 char *buf;
681 {
682 char *bp = buf;
683 long len;
684
685 if (p->curr == 0) return "";
686 *bp++ = '"';
687 if (p->curr > INSPECT_LENGTH) {
688 strcpy(bp, "..."); bp += 3;
689 len = INSPECT_LENGTH;
690 }
691 else {
692 len = p->curr;
693 }
694 memcpy(bp, CURPTR(p) - len, len); bp += len;
695 *bp++ = '"';
696 *bp++ = ' ';
697 *bp++ = '\0';
698 return buf;
699 }
700
701 static char*
702 inspect_after(p, buf)
703 struct strscanner *p;
704 char *buf;
705 {
706 char *bp = buf;
707 long len;
708
709 *bp++ = ' ';
710 *bp++ = '"';
711 len = S_LEN(p) - p->curr;
712 if (len > INSPECT_LENGTH) {
713 len = INSPECT_LENGTH;
714 memcpy(bp, CURPTR(p), len); bp += len;
715 strcpy(bp, "..."); bp += 3;
716 }
717 else {
718 memcpy(bp, CURPTR(p), len); bp += len;
719 }
720 *bp++ = '"';
721 *bp++ = '\0';
722 return buf;
723 }
724
725
726
727
728
729 void
730 Init_strscan()
731 {
732 ID id_scanerr = rb_intern("ScanError");
733 volatile VALUE tmp;
734
735 if (rb_const_defined(rb_cObject, id_scanerr)) {
736 ScanError = rb_const_get(rb_cObject, id_scanerr);
737 }
738 else {
739 ScanError = rb_define_class_id(id_scanerr, rb_eStandardError);
740 }
741
742 StringScanner = rb_define_class("StringScanner", rb_cObject);
743 tmp = rb_str_new2(STRSCAN_VERSION);
744 rb_obj_freeze(tmp);
745 rb_const_set(StringScanner, rb_intern("Version"), tmp);
746 tmp = rb_str_new2("$Id: strscan.c,v 1.4 2002/08/02 00:10:19 aamine Exp $");
747 rb_obj_freeze(tmp);
748 rb_const_set(StringScanner, rb_intern("Id"), tmp);
749
750 rb_define_singleton_method(StringScanner, "allocate",
751 strscan_s_allocate, 0);
752 rb_define_private_method(StringScanner, "initialize",
753 strscan_initialize, -1);
754 rb_define_singleton_method(StringScanner, "must_C_version",
755 strscan_s_mustc, 0);
756 rb_define_method(StringScanner, "reset", strscan_reset, 0);
757 rb_define_method(StringScanner, "terminate", strscan_terminate, 0);
758 rb_define_method(StringScanner, "clear", strscan_terminate, 0);
759 rb_define_method(StringScanner, "string", strscan_get_string, 0);
760 rb_define_method(StringScanner, "string=", strscan_set_string, 1);
761 rb_define_method(StringScanner, "pos", strscan_get_pos, 0);
762 rb_define_method(StringScanner, "pos=", strscan_set_pos, 1);
763 rb_define_method(StringScanner, "pointer", strscan_get_pos, 0);
764 rb_define_method(StringScanner, "pointer=", strscan_set_pos, 1);
765
766 rb_define_method(StringScanner, "scan", strscan_scan, 1);
767 rb_define_method(StringScanner, "skip", strscan_skip, 1);
768 rb_define_method(StringScanner, "match?", strscan_match_p, 1);
769 rb_define_method(StringScanner, "check", strscan_check, 1);
770 rb_define_method(StringScanner, "scan_full", strscan_scan_full, 3);
771
772 rb_define_method(StringScanner, "scan_until", strscan_scan_until, 1);
773 rb_define_method(StringScanner, "skip_until", strscan_skip_until, 1);
774 rb_define_method(StringScanner, "exist?", strscan_exist_p, 1);
775 rb_define_method(StringScanner, "check_until", strscan_check_until, 1);
776 rb_define_method(StringScanner, "search_full", strscan_search_full, 3);
777
778 rb_define_method(StringScanner, "getch", strscan_getch, 0);
779 rb_define_method(StringScanner, "get_byte", strscan_get_byte, 0);
780 rb_define_method(StringScanner, "getbyte", strscan_get_byte, 0);
781 rb_define_method(StringScanner, "peek", strscan_peek, 1);
782 rb_define_method(StringScanner, "peep", strscan_peek, 1);
783
784 rb_define_method(StringScanner, "unscan", strscan_unscan, 0);
785
786 rb_define_method(StringScanner, "eos?", strscan_eos_p, 0);
787 rb_define_method(StringScanner, "empty?", strscan_eos_p, 0);
788 rb_define_method(StringScanner, "rest?", strscan_rest_p, 0);
789
790 rb_define_method(StringScanner, "matched?", strscan_matched_p, 0);
791 rb_define_method(StringScanner, "matched", strscan_matched, 0);
792 rb_define_method(StringScanner, "matched_size", strscan_matched_size, 0);
793 rb_define_method(StringScanner, "matchedsize", strscan_matched_size, 0);
794 rb_define_method(StringScanner, "[]", strscan_aref, 1);
795 rb_define_method(StringScanner, "pre_match", strscan_pre_match, 0);
796 rb_define_method(StringScanner, "post_match", strscan_post_match, 0);
797
798 rb_define_method(StringScanner, "rest", strscan_rest, 0);
799 rb_define_method(StringScanner, "rest_size", strscan_rest_size, 0);
800 rb_define_method(StringScanner, "restsize", strscan_rest_size, 0);
801
802 rb_define_method(StringScanner, "inspect", strscan_inspect, 0);
803 }