Project

General

Profile

Feature #836 ยป strscan.c

apeiros (Stefan Rusterholz), 12/08/2008 11:27 AM

 
1
/*
2
    $Id: strscan.c 11708 2007-02-12 23:01:19Z shyouhei $
3

    
4
    Copyright (c) 1999-2006 Minero Aoki
5

    
6
    This program is free software.
7
    You can distribute/modify this program under the terms of
8
    the Ruby License. For details, see the file COPYING.
9
*/
10

    
11
#include "ruby.h"
12
#include "re.h"
13

    
14
#define STRSCAN_VERSION "0.7.0"
15

    
16
/* =======================================================================
17
                         Data Type Definitions
18
   ======================================================================= */
19

    
20
static VALUE StringScanner;
21
static VALUE ScanError;
22

    
23
struct strscanner
24
{
25
    /* multi-purpose flags */
26
    unsigned long flags;
27
#define FLAG_MATCHED (1 << 0)
28

    
29
    /* the string to scan */
30
    VALUE str;
31
    
32
    /* scan pointers */
33
    long prev;   /* legal only when MATCHED_P(s) */
34
    long curr;   /* always legal */
35

    
36
    /* the regexp register; legal only when MATCHED_P(s) */
37
    struct re_registers regs;
38
};
39

    
40
#define MATCHED_P(s)          ((s)->flags & FLAG_MATCHED)
41
#define MATCHED(s)             (s)->flags |= FLAG_MATCHED
42
#define CLEAR_MATCH_STATUS(s)  (s)->flags &= ~FLAG_MATCHED
43

    
44
#define S_PBEG(s)  (RSTRING((s)->str)->ptr)
45
#define S_LEN(s)  (RSTRING((s)->str)->len)
46
#define S_PEND(s)  (S_PBEG(s) + S_LEN(s))
47
#define CURPTR(s) (S_PBEG(s) + (s)->curr)
48
#define S_RESTLEN(s) (S_LEN(s) - (s)->curr)
49

    
50
#define EOS_P(s) ((s)->curr >= RSTRING(p->str)->len)
51

    
52
#define GET_SCANNER(obj,var) do {\
53
    Data_Get_Struct(obj, struct strscanner, var);\
54
    if (NIL_P(var->str)) rb_raise(rb_eArgError, "uninitialized StringScanner object");\
55
} while (0)
56

    
57
/* =======================================================================
58
                            Function Prototypes
59
   ======================================================================= */
60

    
61
static VALUE infect _((VALUE str, struct strscanner *p));
62
static VALUE extract_range _((struct strscanner *p, long beg_i, long end_i));
63
static VALUE extract_beg_len _((struct strscanner *p, long beg_i, long len));
64

    
65
static void check_strscan _((VALUE obj));
66
static void strscan_mark _((struct strscanner *p));
67
static void strscan_free _((struct strscanner *p));
68
static VALUE strscan_s_allocate _((VALUE klass));
69
static VALUE strscan_initialize _((int argc, VALUE *argv, VALUE self));
70
static VALUE strscan_init_copy _((VALUE vself, VALUE vorig));
71

    
72
static VALUE strscan_s_mustc _((VALUE self));
73
static VALUE strscan_terminate _((VALUE self));
74
static VALUE strscan_clear _((VALUE self));
75
static VALUE strscan_get_string _((VALUE self));
76
static VALUE strscan_set_string _((VALUE self, VALUE str));
77
static VALUE strscan_concat _((VALUE self, VALUE str));
78
static VALUE strscan_get_pos _((VALUE self));
79
static VALUE strscan_set_pos _((VALUE self, VALUE pos));
80
static VALUE strscan_do_scan _((VALUE self, VALUE regex,
81
                                int succptr, int getstr, int headonly));
82
static VALUE strscan_scan _((VALUE self, VALUE re));
83
static VALUE strscan_match_p _((VALUE self, VALUE re));
84
static VALUE strscan_skip _((VALUE self, VALUE re));
85
static VALUE strscan_check _((VALUE self, VALUE re));
86
static VALUE strscan_scan_full _((VALUE self, VALUE re,
87
                                  VALUE succp, VALUE getp));
88
static VALUE strscan_scan_until _((VALUE self, VALUE re));
89
static VALUE strscan_skip_until _((VALUE self, VALUE re));
90
static VALUE strscan_check_until _((VALUE self, VALUE re));
91
static VALUE strscan_search_full _((VALUE self, VALUE re,
92
                                    VALUE succp, VALUE getp));
93
static void adjust_registers_to_matched _((struct strscanner *p));
94
static VALUE strscan_getch _((VALUE self));
95
static VALUE strscan_get_byte _((VALUE self));
96
static VALUE strscan_getbyte _((VALUE self));
97
static VALUE strscan_peek _((VALUE self, VALUE len));
98
static VALUE strscan_peep _((VALUE self, VALUE len));
99
static VALUE strscan_unscan _((VALUE self));
100
static VALUE strscan_bol_p _((VALUE self));
101
static VALUE strscan_eos_p _((VALUE self));
102
static VALUE strscan_empty_p _((VALUE self));
103
static VALUE strscan_rest_p _((VALUE self));
104
static VALUE strscan_matched_p _((VALUE self));
105
static VALUE strscan_matched _((VALUE self));
106
static VALUE strscan_matched_size _((VALUE self));
107
static VALUE strscan_aref _((VALUE self, VALUE idx));
108
static VALUE strscan_pre_match _((VALUE self));
109
static VALUE strscan_post_match _((VALUE self));
110
static VALUE strscan_rest _((VALUE self));
111
static VALUE strscan_rest_size _((VALUE self));
112

    
113
static VALUE strscan_inspect _((VALUE self));
114
static VALUE inspect1 _((struct strscanner *p));
115
static VALUE inspect2 _((struct strscanner *p));
116

    
117
/* =======================================================================
118
                                   Utils
119
   ======================================================================= */
120

    
121
static VALUE
122
infect(VALUE str, struct strscanner *p)
123
{
124
    OBJ_INFECT(str, p->str);
125
    return str;
126
}
127

    
128
static VALUE
129
extract_range(struct strscanner *p, long beg_i, long end_i)
130
{
131
    if (beg_i > S_LEN(p)) return Qnil;
132
    if (end_i > S_LEN(p))
133
        end_i = S_LEN(p);
134
    return infect(rb_str_new(S_PBEG(p) + beg_i, end_i - beg_i), p);
135
}
136

    
137
static VALUE
138
extract_beg_len(struct strscanner *p, long beg_i, long len)
139
{
140
    if (beg_i > S_LEN(p)) return Qnil;
141
    if (beg_i + len > S_LEN(p))
142
        len = S_LEN(p) - beg_i;
143
    return infect(rb_str_new(S_PBEG(p) + beg_i, len), p);
144
}
145

    
146
/* =======================================================================
147
                               Constructor
148
   ======================================================================= */
149

    
150
static void
151
strscan_mark(struct strscanner *p)
152
{
153
    rb_gc_mark(p->str);
154
}
155

    
156
static void
157
strscan_free(struct strscanner *p)
158
{
159
    re_free_registers(&(p->regs));
160
    free(p);
161
}
162

    
163
static VALUE
164
strscan_s_allocate(VALUE klass)
165
{
166
    struct strscanner *p;
167
    
168
    p = ALLOC(struct strscanner);
169
    MEMZERO(p, struct strscanner, 1);
170
    CLEAR_MATCH_STATUS(p);
171
    MEMZERO(&(p->regs), struct re_registers, 1);
172
    p->str = Qnil;
173
    return Data_Wrap_Struct(klass, strscan_mark, strscan_free, p);
174
}
175

    
176
/*
177
 * call-seq: StringScanner.new(string, dup = false)
178
 *
179
 * Creates a new StringScanner object to scan over the given +string+.
180
 * +dup+ argument is obsolete and not used now.
181
 */
182
static VALUE
183
strscan_initialize(int argc, VALUE *argv, VALUE self)
184
{
185
    struct strscanner *p;
186
    VALUE str, need_dup;
187

    
188
    Data_Get_Struct(self, struct strscanner, p);
189
    rb_scan_args(argc, argv, "11", &str, &need_dup);
190
    StringValue(str);
191
    p->str = str;
192

    
193
    return self;
194
}
195

    
196
static void
197
check_strscan(VALUE obj)
198
{
199
    if (TYPE(obj) != T_DATA || RDATA(obj)->dmark != (RUBY_DATA_FUNC)strscan_mark) {
200
        rb_raise(rb_eTypeError,
201
                 "wrong argument type %s (expected StringScanner)",
202
                 rb_obj_classname(obj));
203
    }
204
}
205

    
206
/*
207
 * call-seq:
208
 *   dup
209
 *   clone
210
 *
211
 * Duplicates a StringScanner object.
212
 */
213
static VALUE
214
strscan_init_copy(VALUE vself, VALUE vorig)
215
{
216
    struct strscanner *self, *orig;
217

    
218
    Data_Get_Struct(vself, struct strscanner, self);
219
    check_strscan(vorig);
220
    Data_Get_Struct(vorig, struct strscanner, orig);
221
    if (self != orig) {
222
        self->flags = orig->flags;
223
        self->str = orig->str;
224
        self->prev = orig->prev;
225
        self->curr = orig->curr;
226
        re_copy_registers(&self->regs, &orig->regs);
227
    }
228
    return vself;
229
}
230

    
231
/* =======================================================================
232
                          Instance Methods
233
   ======================================================================= */
234

    
235
/*
236
 * call-seq: StringScanner.must_C_version
237
 *
238
 * This method is defined for backward compatibility.
239
 */
240
static VALUE
241
strscan_s_mustc(VALUE self)
242
{
243
    return self;
244
}
245

    
246
/*
247
 * Reset the scan pointer (index 0) and clear matching data.
248
 */
249
static VALUE
250
strscan_reset(VALUE self)
251
{
252
    struct strscanner *p;
253

    
254
    GET_SCANNER(self, p);
255
    p->curr = 0;
256
    CLEAR_MATCH_STATUS(p);
257
    return self;
258
}
259

    
260
/*
261
 * call-seq:
262
 *   terminate
263
 *   clear
264
 *
265
 * Set the scan pointer to the end of the string and clear matching data.
266
 */
267
static VALUE
268
strscan_terminate(VALUE self)
269
{
270
    struct strscanner *p;
271

    
272
    GET_SCANNER(self, p);
273
    p->curr = S_LEN(p);
274
    CLEAR_MATCH_STATUS(p);
275
    return self;
276
}
277

    
278
/*
279
 * Equivalent to #terminate.
280
 * This method is obsolete; use #terminate instead.
281
 */
282
static VALUE
283
strscan_clear(VALUE self)
284
{
285
    rb_warning("StringScanner#clear is obsolete; use #terminate instead");
286
    return strscan_terminate(self);
287
}
288

    
289
/*
290
 * Returns the string being scanned.
291
 */
292
static VALUE
293
strscan_get_string(VALUE self)
294
{
295
    struct strscanner *p;
296

    
297
    GET_SCANNER(self, p);
298
    return p->str;
299
}
300

    
301
/*
302
 * call-seq: string=(str)
303
 *
304
 * Changes the string being scanned to +str+ and resets the scanner.
305
 * Returns +str+.
306
 */
307
static VALUE
308
strscan_set_string(VALUE self, VALUE str)
309
{
310
    struct strscanner *p;
311

    
312
    Data_Get_Struct(self, struct strscanner, p);
313
    StringValue(str);
314
    p->str = rb_str_dup(str);
315
    rb_obj_freeze(p->str);
316
    p->curr = 0;
317
    CLEAR_MATCH_STATUS(p);
318
    return str;
319
}
320

    
321
/*
322
 * call-seq:
323
 *   concat(str)
324
 *   <<(str)
325
 *
326
 * Appends +str+ to the string being scanned.
327
 * This method does not affect scan pointer.
328
 *
329
 *   s = StringScanner.new("Fri Dec 12 1975 14:39")
330
 *   s.scan(/Fri /)
331
 *   s << " +1000 GMT"
332
 *   s.string            # -> "Fri Dec 12 1975 14:39 +1000 GMT"
333
 *   s.scan(/Dec/)       # -> "Dec"
334
 */
335
static VALUE
336
strscan_concat(VALUE self, VALUE str)
337
{
338
    struct strscanner *p;
339

    
340
    GET_SCANNER(self, p);
341
    StringValue(str);
342
    rb_str_append(p->str, str);
343
    return self;
344
}
345

    
346
/*
347
 * Returns the position of the scan pointer.  In the 'reset' position, this
348
 * value is zero.  In the 'terminated' position (i.e. the string is exhausted),
349
 * this value is the length of the string.
350
 *
351
 * In short, it's a 0-based index into the string.
352
 *
353
 *   s = StringScanner.new('test string')
354
 *   s.pos               # -> 0
355
 *   s.scan_until /str/  # -> "test str"
356
 *   s.pos               # -> 8
357
 *   s.terminate         # -> #<StringScanner fin>
358
 *   s.pos               # -> 11
359
 */
360
static VALUE
361
strscan_get_pos(VALUE self)
362
{
363
    struct strscanner *p;
364

    
365
    GET_SCANNER(self, p);
366
    return INT2FIX(p->curr);
367
}
368

    
369
/*
370
 * call-seq: pos=(n)
371
 *
372
 * Modify the scan pointer.
373
 *
374
 *   s = StringScanner.new('test string')
375
 *   s.pos = 7            # -> 7
376
 *   s.rest               # -> "ring"
377
 */
378
static VALUE
379
strscan_set_pos(VALUE self, VALUE v)
380
{
381
    struct strscanner *p;
382
    long i;
383

    
384
    GET_SCANNER(self, p);
385
    i = NUM2INT(v);
386
    if (i < 0) i += S_LEN(p);
387
    if (i < 0) rb_raise(rb_eRangeError, "index out of range");
388
    if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range");
389
    p->curr = i;
390
    return INT2NUM(i);
391
}
392

    
393
static VALUE
394
strscan_do_scan(VALUE self, VALUE regex, int succptr, int getstr, int headonly)
395
{
396
    struct strscanner *p;
397
    int ret;
398

    
399
    Check_Type(regex, T_REGEXP);
400
    GET_SCANNER(self, p);
401

    
402
    CLEAR_MATCH_STATUS(p);
403
    if (S_RESTLEN(p) < 0) {
404
        return Qnil;
405
    }
406
    rb_kcode_set_option(regex);
407
    if (headonly) {
408
        ret = re_match(RREGEXP(regex)->ptr,
409
                       CURPTR(p), S_RESTLEN(p),
410
                       0,
411
                       &(p->regs));
412
    }
413
    else {
414
        ret = re_search(RREGEXP(regex)->ptr,
415
                        CURPTR(p), S_RESTLEN(p),
416
                        0,
417
                        S_RESTLEN(p),
418
                        &(p->regs));
419
    }
420
    rb_kcode_reset_option();
421

    
422
    if (ret == -2) rb_raise(ScanError, "regexp buffer overflow");
423
    if (ret < 0) {
424
        /* not matched */
425
        return Qnil;
426
    }
427

    
428
    MATCHED(p);
429
    p->prev = p->curr;
430
    if (succptr) {
431
        p->curr += p->regs.end[0];
432
    }
433
    if (getstr) {
434
        return extract_beg_len(p, p->prev, p->regs.end[0]);
435
    }
436
    else {
437
        return INT2FIX(p->regs.end[0]);
438
    }
439
}
440

    
441
/*
442
 * call-seq: scan(pattern) => String
443
 *
444
 * Tries to match with +pattern+ at the current position. If there's a match,
445
 * the scanner advances the "scan pointer" and returns the matched string.
446
 * Otherwise, the scanner returns +nil+.
447
 *
448
 *   s = StringScanner.new('test string')
449
 *   p s.scan(/\w+/)   # -> "test"
450
 *   p s.scan(/\w+/)   # -> nil
451
 *   p s.scan(/\s+/)   # -> " "
452
 *   p s.scan(/\w+/)   # -> "string"
453
 *   p s.scan(/./)     # -> nil
454
 *
455
 */
456
static VALUE
457
strscan_scan(VALUE self, VALUE re)
458
{
459
    return strscan_do_scan(self, re, 1, 1, 1);
460
}
461

    
462
/*
463
 * call-seq: match?(pattern)
464
 *
465
 * Tests whether the given +pattern+ is matched from the current scan pointer.
466
 * Returns the length of the match, or +nil+.  The scan pointer is not advanced.
467
 *
468
 *   s = StringScanner.new('test string')
469
 *   p s.match?(/\w+/)   # -> 4
470
 *   p s.match?(/\w+/)   # -> 4
471
 *   p s.match?(/\s+/)   # -> nil
472
 */
473
static VALUE
474
strscan_match_p(VALUE self, VALUE re)
475
{
476
    return strscan_do_scan(self, re, 0, 0, 1);
477
}
478

    
479
/*
480
 * call-seq: skip(pattern)
481
 *
482
 * Attempts to skip over the given +pattern+ beginning with the scan pointer.
483
 * If it matches, the scan pointer is advanced to the end of the match, and the
484
 * length of the match is returned.  Otherwise, +nil+ is returned.
485
 *
486
 * It's similar to #scan, but without returning the matched string.
487
 *
488
 *   s = StringScanner.new('test string')
489
 *   p s.skip(/\w+/)   # -> 4
490
 *   p s.skip(/\w+/)   # -> nil
491
 *   p s.skip(/\s+/)   # -> 1
492
 *   p s.skip(/\w+/)   # -> 6
493
 *   p s.skip(/./)     # -> nil
494
 *
495
 */
496
static VALUE
497
strscan_skip(VALUE self, VALUE re)
498
{
499
    return strscan_do_scan(self, re, 1, 0, 1);
500
}
501

    
502
/*
503
 * call-seq: check(pattern)
504
 *
505
 * This returns the value that #scan would return, without advancing the scan
506
 * pointer.  The match register is affected, though.
507
 *
508
 *   s = StringScanner.new("Fri Dec 12 1975 14:39")
509
 *   s.check /Fri/               # -> "Fri"
510
 *   s.pos                       # -> 0
511
 *   s.matched                   # -> "Fri"
512
 *   s.check /12/                # -> nil
513
 *   s.matched                   # -> nil
514
 *
515
 * Mnemonic: it "checks" to see whether a #scan will return a value.
516
 */
517
static VALUE
518
strscan_check(VALUE self, VALUE re)
519
{
520
    return strscan_do_scan(self, re, 0, 1, 1);
521
}
522

    
523
/*
524
 * call-seq: scan_full(pattern, return_string_p, advance_pointer_p)
525
 *
526
 * Tests whether the given +pattern+ is matched from the current scan pointer.
527
 * Returns the matched string if +return_string_p+ is true.
528
 * Advances the scan pointer if +advance_pointer_p+ is true.
529
 * The match register is affected.
530
 *
531
 * "full" means "#scan with full parameters".
532
 */
533
static VALUE
534
strscan_scan_full(VALUE self, VALUE re, VALUE s, VALUE f)
535
{
536
    return strscan_do_scan(self, re, RTEST(s), RTEST(f), 1);
537
}
538

    
539

    
540
/*
541
 * call-seq: scan_until(pattern)
542
 *
543
 * Scans the string _until_ the +pattern+ is matched.  Returns the substring up
544
 * to and including the end of the match, advancing the scan pointer to that
545
 * location. If there is no match, +nil+ is returned.
546
 *
547
 *   s = StringScanner.new("Fri Dec 12 1975 14:39")
548
 *   s.scan_until(/1/)        # -> "Fri Dec 1"
549
 *   s.pre_match              # -> "Fri Dec "
550
 *   s.scan_until(/XYZ/)      # -> nil
551
 */
552
static VALUE
553
strscan_scan_until(VALUE self, VALUE re)
554
{
555
    return strscan_do_scan(self, re, 1, 1, 0);
556
}
557

    
558
/*
559
 * call-seq: exist?(pattern)
560
 *
561
 * Looks _ahead_ to see if the +pattern+ exists _anywhere_ in the string,
562
 * without advancing the scan pointer.  This predicates whether a #scan_until
563
 * will return a value.
564
 *
565
 *   s = StringScanner.new('test string')
566
 *   s.exist? /s/            # -> 3
567
 *   s.scan /test/           # -> "test"
568
 *   s.exist? /s/            # -> 6
569
 *   s.exist? /e/            # -> nil
570
 */
571
static VALUE
572
strscan_exist_p(VALUE self, VALUE re)
573
{
574
    return strscan_do_scan(self, re, 0, 0, 0);
575
}
576

    
577
/*
578
 * call-seq: skip_until(pattern)
579
 *
580
 * Advances the scan pointer until +pattern+ is matched and consumed.  Returns
581
 * the number of bytes advanced, or +nil+ if no match was found.
582
 *
583
 * Look ahead to match +pattern+, and advance the scan pointer to the _end_
584
 * of the match.  Return the number of characters advanced, or +nil+ if the
585
 * match was unsuccessful.
586
 *
587
 * It's similar to #scan_until, but without returning the intervening string.
588
 *
589
 *   s = StringScanner.new("Fri Dec 12 1975 14:39")
590
 *   s.skip_until /12/           # -> 10
591
 *   s                           # 
592
 */
593
static VALUE
594
strscan_skip_until(VALUE self, VALUE re)
595
{
596
    return strscan_do_scan(self, re, 1, 0, 0);
597
}
598

    
599
/*
600
 * call-seq: check_until(pattern)
601
 *
602
 * This returns the value that #scan_until would return, without advancing the
603
 * scan pointer.  The match register is affected, though.
604
 *
605
 *   s = StringScanner.new("Fri Dec 12 1975 14:39")
606
 *   s.check_until /12/          # -> "Fri Dec 12"
607
 *   s.pos                       # -> 0
608
 *   s.matched                   # -> 12
609
 *
610
 * Mnemonic: it "checks" to see whether a #scan_until will return a value.
611
 */
612
static VALUE
613
strscan_check_until(VALUE self, VALUE re)
614
{
615
    return strscan_do_scan(self, re, 0, 1, 0);
616
}
617

    
618
/*
619
 * call-seq: search_full(pattern, return_string_p, advance_pointer_p)
620
 *
621
 * Scans the string _until_ the +pattern+ is matched.
622
 * Returns the matched string if +return_string_p+ is true, otherwise
623
 * returns the number of bytes advanced.
624
 * Advances the scan pointer if +advance_pointer_p+, otherwise not.
625
 * This method does affect the match register.
626
 */
627
static VALUE
628
strscan_search_full(VALUE self, VALUE re, VALUE s, VALUE f)
629
{
630
    return strscan_do_scan(self, re, RTEST(s), RTEST(f), 0);
631
}
632

    
633
/* DANGEROUS; need to synchronize with regex.c */
634
static void
635
adjust_registers_to_matched(struct strscanner *p)
636
{
637
    if (p->regs.allocated == 0) {
638
        p->regs.beg = ALLOC_N(int, RE_NREGS);
639
        p->regs.end = ALLOC_N(int, RE_NREGS);
640
        p->regs.allocated = RE_NREGS;
641
    }
642
    p->regs.num_regs = 1;
643
    p->regs.beg[0] = 0;
644
    p->regs.end[0] = p->curr - p->prev;
645
}
646

    
647
/*
648
 * Scans one character and returns it.
649
 * This method is multi-byte character sensitive.
650
 * See also #get_byte.
651
 *
652
 *   s = StringScanner.new('ab')
653
 *   s.getch           # => "a"
654
 *   s.getch           # => "b"
655
 *   s.getch           # => nil
656
 *
657
 *   $KCODE = 'EUC'
658
 *   s = StringScanner.new("\244\242")
659
 *   s.getch           # => "\244\242"   # Japanese hira-kana "A" in EUC-JP
660
 *   s.getch           # => nil
661
 */
662
static VALUE
663
strscan_getch(VALUE self)
664
{
665
    struct strscanner *p;
666
    long len;
667

    
668
    GET_SCANNER(self, p);
669
    CLEAR_MATCH_STATUS(p);
670
    if (EOS_P(p))
671
        return Qnil;
672
    len = mbclen(*CURPTR(p));
673
    if (p->curr + len > S_LEN(p)) {
674
        len = S_LEN(p) - p->curr;
675
    }
676
    p->prev = p->curr;
677
    p->curr += len;
678
    MATCHED(p);
679
    adjust_registers_to_matched(p);
680
    return extract_range(p, p->prev + p->regs.beg[0],
681
                            p->prev + p->regs.end[0]);
682
}
683

    
684
/*
685
 * Scans one byte and returns it.
686
 * This method is NOT multi-byte character sensitive.
687
 * See also #getch.
688
 *
689
 *   s = StringScanner.new('ab')
690
 *   s.get_byte         # => "a"
691
 *   s.get_byte         # => "b"
692
 *   s.get_byte         # => nil
693
 *
694
 *   s = StringScanner.new("\244\242")
695
 *   s.get_byte         # => "\244"
696
 *   s.get_byte         # => "\242"
697
 *   s.get_byte         # => nil
698
 */
699
static VALUE
700
strscan_get_byte(VALUE self)
701
{
702
    struct strscanner *p;
703

    
704
    GET_SCANNER(self, p);
705
    CLEAR_MATCH_STATUS(p);
706
    if (EOS_P(p)) {
707
        return Qnil;
708
    }
709
    p->prev = p->curr;
710
    p->curr++;
711
    MATCHED(p);
712
    adjust_registers_to_matched(p);
713
    return extract_range(p, p->prev + p->regs.beg[0],
714
                            p->prev + p->regs.end[0]);
715
}
716

    
717
/*
718
 * Equivalent to #get_byte.
719
 * This method is obsolete; use #get_byte instead.
720
 */
721
static VALUE
722
strscan_getbyte(VALUE self)
723
{
724
    rb_warning("StringScanner#getbyte is obsolete; use #get_byte instead");
725
    return strscan_get_byte(self);
726
}
727

    
728
/*
729
 * call-seq: peek(len)
730
 *
731
 * Extracts a string corresponding to <tt>string[pos,len]</tt>, without
732
 * advancing the scan pointer.
733
 *
734
 *   s = StringScanner.new('test string')
735
 *   s.peek(7)          # => "test st"
736
 *   s.peek(7)          # => "test st"
737
 *
738
 */
739
static VALUE
740
strscan_peek(VALUE self, VALUE vlen)
741
{
742
    struct strscanner *p;
743
    long len;
744

    
745
    GET_SCANNER(self, p);
746
    len = NUM2LONG(vlen);
747
    if (EOS_P(p)) {
748
        return infect(rb_str_new("", 0), p);
749
    }
750
    if (p->curr + len > S_LEN(p)) {
751
        len = S_LEN(p) - p->curr;
752
    }
753
    return extract_beg_len(p, p->curr, len);
754
}
755

    
756
/*
757
 * Equivalent to #peek.
758
 * This method is obsolete; use #peek instead.
759
 */
760
static VALUE
761
strscan_peep(VALUE self, VALUE vlen)
762
{
763
    rb_warning("StringScanner#peep is obsolete; use #peek instead");
764
    return strscan_peek(self, vlen);
765
}
766

    
767
/*
768
 * Set the scan pointer to the previous position.  Only one previous position is
769
 * remembered, and it changes with each scanning operation.
770
 *
771
 *   s = StringScanner.new('test string')
772
 *   s.scan(/\w+/)        # => "test"
773
 *   s.unscan
774
 *   s.scan(/../)         # => "te"
775
 *   s.scan(/\d/)         # => nil
776
 *   s.unscan             # ScanError: unscan failed: previous match had failed
777
 */
778
static VALUE
779
strscan_unscan(VALUE self)
780
{
781
    struct strscanner *p;
782

    
783
    GET_SCANNER(self, p);
784
    if (! MATCHED_P(p)) {
785
        rb_raise(ScanError, "unscan failed: previous match had failed");
786
    }
787
    p->curr = p->prev;
788
    CLEAR_MATCH_STATUS(p);
789
    return self;
790
}
791

    
792
/*
793
 * Returns +true+ iff the scan pointer is at the beginning of the line.
794
 *
795
 *   s = StringScanner.new("test\ntest\n")
796
 *   s.bol?           # => true
797
 *   s.scan(/te/)
798
 *   s.bol?           # => false
799
 *   s.scan(/st\n/)
800
 *   s.bol?           # => true
801
 *   s.terminate
802
 *   s.bol?           # => true
803
 */
804
static VALUE
805
strscan_bol_p(VALUE self)
806
{
807
    struct strscanner *p;
808

    
809
    GET_SCANNER(self, p);
810
    if (CURPTR(p) > S_PEND(p)) return Qnil;
811
    if (p->curr == 0) return Qtrue;
812
    return (*(CURPTR(p) - 1) == '\n') ? Qtrue : Qfalse;
813
}
814

    
815
/*
816
 * Returns +true+ if the scan pointer is at the end of the string.
817
 *
818
 *   s = StringScanner.new('test string')
819
 *   p s.eos?          # => false
820
 *   s.scan(/test/)
821
 *   p s.eos?          # => false
822
 *   s.terminate
823
 *   p s.eos?          # => true
824
 */
825
static VALUE
826
strscan_eos_p(VALUE self)
827
{
828
    struct strscanner *p;
829

    
830
    GET_SCANNER(self, p);
831
    return EOS_P(p) ? Qtrue : Qfalse;
832
}
833

    
834
/*
835
 * Equivalent to #eos?.
836
 * This method is obsolete, use #eos? instead.
837
 */
838
static VALUE
839
strscan_empty_p(VALUE self)
840
{
841
    rb_warning("StringScanner#empty? is obsolete; use #eos? instead");
842
    return strscan_eos_p(self);
843
}
844

    
845
/*
846
 * Returns true iff there is more data in the string.  See #eos?.
847
 * This method is obsolete; use #eos? instead.
848
 *
849
 *   s = StringScanner.new('test string')
850
 *   s.eos?              # These two
851
 *   s.rest?             # are opposites.
852
 */
853
static VALUE
854
strscan_rest_p(VALUE self)
855
{
856
    struct strscanner *p;
857

    
858
    GET_SCANNER(self, p);
859
    return EOS_P(p) ? Qfalse : Qtrue;
860
}
861

    
862
/*
863
 * Returns +true+ iff the last match was successful.
864
 *
865
 *   s = StringScanner.new('test string')
866
 *   s.match?(/\w+/)     # => 4
867
 *   s.matched?          # => true
868
 *   s.match?(/\d+/)     # => nil
869
 *   s.matched?          # => false
870
 */
871
static VALUE
872
strscan_matched_p(VALUE self)
873
{
874
    struct strscanner *p;
875

    
876
    GET_SCANNER(self, p);
877
    return MATCHED_P(p) ? Qtrue : Qfalse;
878
}
879

    
880
/*
881
 * Returns the last matched string.
882
 * 
883
 *   s = StringScanner.new('test string')
884
 *   s.match?(/\w+/)     # -> 4
885
 *   s.matched           # -> "test"
886
 */
887
static VALUE
888
strscan_matched(VALUE self)
889
{
890
    struct strscanner *p;
891

    
892
    GET_SCANNER(self, p);
893
    if (! MATCHED_P(p)) return Qnil;
894

    
895
    return extract_range(p, p->prev + p->regs.beg[0],
896
                            p->prev + p->regs.end[0]);
897
}
898

    
899
/*
900
 * Returns the size of the most recent match (see #matched), or +nil+ if there
901
 * was no recent match.
902
 *
903
 *   s = StringScanner.new('test string')
904
 *   s.check /\w+/           # -> "test"
905
 *   s.matched_size          # -> 4
906
 *   s.check /\d+/           # -> nil
907
 *   s.matched_size          # -> nil
908
 */
909
static VALUE
910
strscan_matched_size(VALUE self)
911
{
912
    struct strscanner *p;
913

    
914
    GET_SCANNER(self, p);
915
    if (! MATCHED_P(p)) return Qnil;
916

    
917
    return INT2NUM(p->regs.end[0] - p->regs.beg[0]);
918
}
919

    
920
/*
921
 * Equivalent to #matched_size.
922
 * This method is obsolete; use #matched_size instead.
923
 */
924
static VALUE
925
strscan_matchedsize(VALUE self)
926
{
927
    rb_warning("StringScanner#matchedsize is obsolete; use #matched_size instead");
928
    return strscan_matched_size(self);
929
}
930

    
931
/*
932
 * call-seq: [](n)
933
 *
934
 * Return the n-th subgroup in the most recent match.
935
 *
936
 *   s = StringScanner.new("Fri Dec 12 1975 14:39")
937
 *   s.scan(/(\w+) (\w+) (\d+) /)       # -> "Fri Dec 12 "
938
 *   s[0]                               # -> "Fri Dec 12 "
939
 *   s[1]                               # -> "Fri"
940
 *   s[2]                               # -> "Dec"
941
 *   s[3]                               # -> "12"
942
 *   s.post_match                       # -> "1975 14:39"
943
 *   s.pre_match                        # -> ""
944
 */
945
static VALUE
946
strscan_aref(VALUE self, VALUE idx)
947
{
948
    struct strscanner *p;
949
    long i;
950

    
951
    GET_SCANNER(self, p);
952
    if (! MATCHED_P(p))        return Qnil;
953
    
954
    i = NUM2LONG(idx);
955
    if (i < 0)
956
        i += p->regs.num_regs;
957
    if (i < 0)                 return Qnil;
958
    if (i >= p->regs.num_regs) return Qnil;
959
    if (p->regs.beg[i] == -1)  return Qnil;
960

    
961
    return extract_range(p, p->prev + p->regs.beg[i],
962
                            p->prev + p->regs.end[i]);
963
}
964

    
965
/*
966
 * call-seq: size
967
 *
968
 * Return the amount of subgroups in the most recent match.
969
 * The full match counts as a subgroup.
970
 *
971
 *   s = StringScanner.new("Fri Dec 12 1975 14:39")
972
 *   s.scan(/(\w+) (\w+) (\d+) /)       # -> "Fri Dec 12 "
973
 *   s.size                             # -> 4
974
 */
975
static VALUE
976
strscan_size(VALUE self)
977
{
978
    struct strscanner *p;
979

    
980
    GET_SCANNER(self, p);
981
    if (! MATCHED_P(p))        return Qnil;
982
    return INT2FIX(p->regs.num_regs);
983
}
984

    
985
/*
986
 * call-seq: size
987
 *
988
 * Returns the subgroups in the most recent match (not including the full match).
989
 * If nothing was priorly matched, it returns nil.
990
 *
991
 *   s = StringScanner.new("Fri Dec 12 1975 14:39")
992
 *   s.scan(/(\w+) (\w+) (\d+) /)       # -> "Fri Dec 12 "
993
 *   s.captures                         # -> ["Fri", "Dec", "12"]
994
 *   s.scan(/(\w+) (\w+) (\d+) /)       # -> nil
995
 *   s.captures                         # -> nil
996
 */
997
static VALUE
998
strscan_captures(VALUE self)
999
{
1000
    struct strscanner *p;
1001

    
1002
    GET_SCANNER(self, p);
1003
    if (! MATCHED_P(p))        return Qnil;
1004
    
1005
    int   i;
1006
    int   num_regs = p->regs.num_regs;
1007
    VALUE result   = rb_ary_new2(num_regs);
1008

    
1009
    for(i=1; i<num_regs; i++) {
1010
      rb_ary_push(
1011
        result,
1012
        extract_range(p, p->prev + p->regs.beg[i], p->prev + p->regs.end[i])
1013
      );
1014
    }
1015
    
1016
    return result;
1017
}
1018

    
1019
/*
1020
 *  call-seq:
1021
 *     scanner.values_at( i1, i2, ... iN )   -> an_array
1022
 *  
1023
 * Returns the subgroups in the most recent match at the given indices.
1024
 * If nothing was priorly matched, it returns nil.
1025
 *
1026
 *   s = StringScanner.new("Fri Dec 12 1975 14:39")
1027
 *   s.scan(/(\w+) (\w+) (\d+) /)       # -> "Fri Dec 12 "
1028
 *   s.values_at 0, -1, 5, 2            # -> ["Fri Dec 12 ", "12", nil, "Dec"]
1029
 *   s.scan(/(\w+) (\w+) (\d+) /)       # -> nil
1030
 *   s.captures                         # -> nil
1031
 */
1032

    
1033
static VALUE
1034
strscan_values_at(int argc, VALUE *argv, VALUE self)
1035
{
1036
    struct strscanner *p;
1037

    
1038
    GET_SCANNER(self, p);
1039
    if (! MATCHED_P(p))        return Qnil;
1040

    
1041
    long i;
1042
    VALUE new_ary = rb_ary_new2(argc);
1043

    
1044
    for (i=0; i<argc; i++) {
1045
        rb_ary_push(new_ary, strscan_aref(self, argv[i]));
1046
    }
1047

    
1048
    return new_ary;
1049
}
1050

    
1051
/*
1052
 * Return the <i><b>pre</b>-match</i> (in the regular expression sense) of the last scan.
1053
 *
1054
 *   s = StringScanner.new('test string')
1055
 *   s.scan(/\w+/)           # -> "test"
1056
 *   s.scan(/\s+/)           # -> " "
1057
 *   s.pre_match             # -> "test"
1058
 *   s.post_match            # -> "string"
1059
 */
1060
static VALUE
1061
strscan_pre_match(VALUE self)
1062
{
1063
    struct strscanner *p;
1064

    
1065
    GET_SCANNER(self, p);
1066
    if (! MATCHED_P(p)) return Qnil;
1067

    
1068
    return extract_range(p, 0, p->prev + p->regs.beg[0]);
1069
}
1070

    
1071
/*
1072
 * Return the <i><b>post</b>-match</i> (in the regular expression sense) of the last scan.
1073
 *
1074
 *   s = StringScanner.new('test string')
1075
 *   s.scan(/\w+/)           # -> "test"
1076
 *   s.scan(/\s+/)           # -> " "
1077
 *   s.pre_match             # -> "test"
1078
 *   s.post_match            # -> "string"
1079
 */
1080
static VALUE
1081
strscan_post_match(VALUE self)
1082
{
1083
    struct strscanner *p;
1084

    
1085
    GET_SCANNER(self, p);
1086
    if (! MATCHED_P(p)) return Qnil;
1087

    
1088
    return extract_range(p, p->prev + p->regs.end[0], S_LEN(p));
1089
}
1090

    
1091
/*
1092
 * Returns the "rest" of the string (i.e. everything after the scan pointer).
1093
 * If there is no more data (eos? = true), it returns <tt>""</tt>.
1094
 */
1095
static VALUE
1096
strscan_rest(VALUE self)
1097
{
1098
    struct strscanner *p;
1099

    
1100
    GET_SCANNER(self, p);
1101
    if (EOS_P(p)) {
1102
        return infect(rb_str_new("", 0), p);
1103
    }
1104
    return extract_range(p, p->curr, S_LEN(p));
1105
}
1106

    
1107
/*
1108
 * <tt>s.rest_size</tt> is equivalent to <tt>s.rest.size</tt>.
1109
 */
1110
static VALUE
1111
strscan_rest_size(VALUE self)
1112
{
1113
    struct strscanner *p;
1114
    long i;
1115

    
1116
    GET_SCANNER(self, p);
1117
    if (EOS_P(p)) {
1118
        return INT2FIX(0);
1119
    }
1120

    
1121
    i = S_LEN(p) - p->curr;
1122
    return INT2FIX(i);
1123
}
1124

    
1125
/*
1126
 * <tt>s.restsize</tt> is equivalent to <tt>s.rest_size</tt>.
1127
 * This method is obsolete; use #rest_size instead.
1128
 */
1129
static VALUE
1130
strscan_restsize(VALUE self)
1131
{
1132
    rb_warning("StringScanner#restsize is obsolete; use #rest_size instead");
1133
    return strscan_rest_size(self);
1134
}
1135

    
1136
#define INSPECT_LENGTH 5
1137
#define BUFSIZE 256
1138

    
1139
/*
1140
 * Returns a string that represents the StringScanner object, showing:
1141
 * - the current position
1142
 * - the size of the string
1143
 * - the characters surrounding the scan pointer
1144
 *
1145
 *   s = StringScanner.new("Fri Dec 12 1975 14:39")
1146
 *   s.inspect            # -> '#<StringScanner 0/21 @ "Fri D...">'
1147
 *   s.scan_until /12/    # -> "Fri Dec 12"
1148
 *   s.inspect            # -> '#<StringScanner 10/21 "...ec 12" @ " 1975...">'
1149
 */
1150
static VALUE
1151
strscan_inspect(VALUE self)
1152
{
1153
    struct strscanner *p;
1154
    char buf[BUFSIZE];
1155
    long len;
1156
    VALUE a, b;
1157

    
1158
    Data_Get_Struct(self, struct strscanner, p);
1159
    if (NIL_P(p->str)) {
1160
        len = snprintf(buf, BUFSIZE, "#<%s (uninitialized)>",
1161
                       rb_class2name(CLASS_OF(self)));
1162
        return infect(rb_str_new(buf, len), p);
1163
    }
1164
    if (EOS_P(p)) {
1165
        len = snprintf(buf, BUFSIZE, "#<%s fin>",
1166
                       rb_class2name(CLASS_OF(self)));
1167
        return infect(rb_str_new(buf, len), p);
1168
    }
1169
    if (p->curr == 0) {
1170
        b = inspect2(p);
1171
        len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld @ %s>",
1172
                       rb_class2name(CLASS_OF(self)),
1173
                       p->curr, S_LEN(p),
1174
                       RSTRING(b)->ptr);
1175
        return infect(rb_str_new(buf, len), p);
1176
    }
1177
    a = inspect1(p);
1178
    b = inspect2(p);
1179
    len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld %s @ %s>",
1180
                   rb_class2name(CLASS_OF(self)),
1181
                   p->curr, S_LEN(p),
1182
                   RSTRING(a)->ptr,
1183
                   RSTRING(b)->ptr);
1184
    return infect(rb_str_new(buf, len), p);
1185
}
1186

    
1187
static VALUE
1188
inspect1(struct strscanner *p)
1189
{
1190
    char buf[BUFSIZE];
1191
    char *bp = buf;
1192
    long len;
1193

    
1194
    if (p->curr == 0) return rb_str_new2("");
1195
    if (p->curr > INSPECT_LENGTH) {
1196
        strcpy(bp, "..."); bp += 3;
1197
        len = INSPECT_LENGTH;
1198
    }
1199
    else {
1200
        len = p->curr;
1201
    }
1202
    memcpy(bp, CURPTR(p) - len, len); bp += len;
1203
    return rb_str_dump(rb_str_new(buf, bp - buf));
1204
}
1205

    
1206
static VALUE
1207
inspect2(struct strscanner *p)
1208
{
1209
    char buf[BUFSIZE];
1210
    char *bp = buf;
1211
    long len;
1212

    
1213
    if (EOS_P(p)) return rb_str_new2("");
1214
    len = S_LEN(p) - p->curr;
1215
    if (len > INSPECT_LENGTH) {
1216
        len = INSPECT_LENGTH;
1217
        memcpy(bp, CURPTR(p), len); bp += len;
1218
        strcpy(bp, "..."); bp += 3;
1219
    }
1220
    else {
1221
        memcpy(bp, CURPTR(p), len); bp += len;
1222
    }
1223
    return rb_str_dump(rb_str_new(buf, bp - buf));
1224
}
1225

    
1226
/* =======================================================================
1227
                              Ruby Interface
1228
   ======================================================================= */
1229

    
1230
/*
1231
 * Document-class: StringScanner
1232
 * 
1233
 * StringScanner provides for lexical scanning operations on a String.  Here is
1234
 * an example of its usage:
1235
 *
1236
 *   s = StringScanner.new('This is an example string')
1237
 *   s.eos?               # -> false
1238
 *   
1239
 *   p s.scan(/\w+/)      # -> "This"
1240
 *   p s.scan(/\w+/)      # -> nil
1241
 *   p s.scan(/\s+/)      # -> " "
1242
 *   p s.scan(/\s+/)      # -> nil
1243
 *   p s.scan(/\w+/)      # -> "is"
1244
 *   s.eos?               # -> false
1245
 *   
1246
 *   p s.scan(/\s+/)      # -> " "
1247
 *   p s.scan(/\w+/)      # -> "an"
1248
 *   p s.scan(/\s+/)      # -> " "
1249
 *   p s.scan(/\w+/)      # -> "example"
1250
 *   p s.scan(/\s+/)      # -> " "
1251
 *   p s.scan(/\w+/)      # -> "string"
1252
 *   s.eos?               # -> true
1253
 *   
1254
 *   p s.scan(/\s+/)      # -> nil
1255
 *   p s.scan(/\w+/)      # -> nil
1256
 *
1257
 * Scanning a string means remembering the position of a <i>scan pointer</i>,
1258
 * which is just an index.  The point of scanning is to move forward a bit at
1259
 * a time, so matches are sought after the scan pointer; usually immediately
1260
 * after it.
1261
 *
1262
 * Given the string "test string", here are the pertinent scan pointer
1263
 * positions:
1264
 *
1265
 *     t e s t   s t r i n g
1266
 *   0 1 2 ...             1
1267
 *                         0
1268
 *
1269
 * When you #scan for a pattern (a regular expression), the match must occur
1270
 * at the character after the scan pointer.  If you use #scan_until, then the
1271
 * match can occur anywhere after the scan pointer.  In both cases, the scan
1272
 * pointer moves <i>just beyond</i> the last character of the match, ready to
1273
 * scan again from the next character onwards.  This is demonstrated by the
1274
 * example above.
1275
 *
1276
 * == Method Categories
1277
 *
1278
 * There are other methods besides the plain scanners.  You can look ahead in
1279
 * the string without actually scanning.  You can access the most recent match.
1280
 * You can modify the string being scanned, reset or terminate the scanner,
1281
 * find out or change the position of the scan pointer, skip ahead, and so on.
1282
 * 
1283
 * === Advancing the Scan Pointer
1284
 *
1285
 * - #getch
1286
 * - #get_byte
1287
 * - #scan
1288
 * - #scan_until
1289
 * - #skip
1290
 * - #skip_until
1291
 *
1292
 * === Looking Ahead
1293
 *
1294
 * - #check
1295
 * - #check_until
1296
 * - #exist?
1297
 * - #match?
1298
 * - #peek
1299
 *
1300
 * === Finding Where we Are
1301
 *
1302
 * - #beginning_of_line? (#bol?)
1303
 * - #eos?
1304
 * - #rest?
1305
 * - #rest_size
1306
 * - #pos
1307
 *
1308
 * === Setting Where we Are
1309
 *
1310
 * - #reset
1311
 * - #terminate
1312
 * - #pos=
1313
 * 
1314
 * === Match Data
1315
 *
1316
 * - #matched
1317
 * - #matched?
1318
 * - #matched_size
1319
 * - []
1320
 * - #pre_match
1321
 * - #post_match
1322
 *
1323
 * === Miscellaneous
1324
 *
1325
 * - <<
1326
 * - #concat
1327
 * - #string
1328
 * - #string=
1329
 * - #unscan
1330
 *
1331
 * There are aliases to several of the methods.
1332
 */
1333
void
1334
Init_strscan(void)
1335
{
1336
    ID id_scanerr = rb_intern("ScanError");
1337
    VALUE tmp;
1338

    
1339
    StringScanner = rb_define_class("StringScanner", rb_cObject);
1340
    ScanError = rb_define_class_under(StringScanner, "Error", rb_eStandardError);
1341
    if (!rb_const_defined(rb_cObject, id_scanerr)) {
1342
	rb_const_set(rb_cObject, id_scanerr, ScanError);
1343
    }
1344
    tmp = rb_str_new2(STRSCAN_VERSION);
1345
    rb_obj_freeze(tmp);
1346
    rb_const_set(StringScanner, rb_intern("Version"), tmp);
1347
    tmp = rb_str_new2("$Id: strscan.c 11708 2007-02-12 23:01:19Z shyouhei $");
1348
    rb_obj_freeze(tmp);
1349
    rb_const_set(StringScanner, rb_intern("Id"), tmp);
1350
    
1351
    rb_define_alloc_func(StringScanner, strscan_s_allocate);
1352
    rb_define_private_method(StringScanner, "initialize", strscan_initialize, -1);
1353
    rb_define_private_method(StringScanner, "initialize_copy", strscan_init_copy, 1);
1354
    rb_define_singleton_method(StringScanner, "must_C_version", strscan_s_mustc, 0);
1355
    rb_define_method(StringScanner, "reset",       strscan_reset,       0);
1356
    rb_define_method(StringScanner, "terminate",   strscan_terminate,   0);
1357
    rb_define_method(StringScanner, "clear",       strscan_clear,       0);
1358
    rb_define_method(StringScanner, "string",      strscan_get_string,  0);
1359
    rb_define_method(StringScanner, "string=",     strscan_set_string,  1);
1360
    rb_define_method(StringScanner, "concat",      strscan_concat,      1);
1361
    rb_define_method(StringScanner, "<<",          strscan_concat,      1);
1362
    rb_define_method(StringScanner, "pos",         strscan_get_pos,     0);
1363
    rb_define_method(StringScanner, "pos=",        strscan_set_pos,     1);
1364
    rb_define_method(StringScanner, "pointer",     strscan_get_pos,     0);
1365
    rb_define_method(StringScanner, "pointer=",    strscan_set_pos,     1);
1366

    
1367
    rb_define_method(StringScanner, "scan",        strscan_scan,        1);
1368
    rb_define_method(StringScanner, "skip",        strscan_skip,        1);
1369
    rb_define_method(StringScanner, "match?",      strscan_match_p,     1);
1370
    rb_define_method(StringScanner, "check",       strscan_check,       1);
1371
    rb_define_method(StringScanner, "scan_full",   strscan_scan_full,   3);
1372

    
1373
    rb_define_method(StringScanner, "scan_until",  strscan_scan_until,  1);
1374
    rb_define_method(StringScanner, "skip_until",  strscan_skip_until,  1);
1375
    rb_define_method(StringScanner, "exist?",      strscan_exist_p,     1);
1376
    rb_define_method(StringScanner, "check_until", strscan_check_until, 1);
1377
    rb_define_method(StringScanner, "search_full", strscan_search_full, 3);
1378

    
1379
    rb_define_method(StringScanner, "getch",       strscan_getch,       0);
1380
    rb_define_method(StringScanner, "get_byte",    strscan_get_byte,    0);
1381
    rb_define_method(StringScanner, "getbyte",     strscan_getbyte,     0);
1382
    rb_define_method(StringScanner, "peek",        strscan_peek,        1);
1383
    rb_define_method(StringScanner, "peep",        strscan_peep,        1);
1384

    
1385
    rb_define_method(StringScanner, "unscan",      strscan_unscan,      0);
1386

    
1387
    rb_define_method(StringScanner, "beginning_of_line?", strscan_bol_p, 0);
1388
    rb_alias(StringScanner, rb_intern("bol?"), rb_intern("beginning_of_line?"));
1389
    rb_define_method(StringScanner, "eos?",        strscan_eos_p,       0);
1390
    rb_define_method(StringScanner, "empty?",      strscan_empty_p,     0);
1391
    rb_define_method(StringScanner, "rest?",       strscan_rest_p,      0);
1392

    
1393
    rb_define_method(StringScanner, "matched?",    strscan_matched_p,   0);
1394
    rb_define_method(StringScanner, "matched",     strscan_matched,     0);
1395
    rb_define_method(StringScanner, "matched_size", strscan_matched_size, 0);
1396
    rb_define_method(StringScanner, "matchedsize", strscan_matchedsize, 0);
1397
    rb_define_method(StringScanner, "[]",          strscan_aref,        1);
1398
    rb_define_method(StringScanner, "pre_match",   strscan_pre_match,   0);
1399
    rb_define_method(StringScanner, "post_match",  strscan_post_match,  0);
1400
    rb_define_method(StringScanner, "size",        strscan_size,        0);
1401
    rb_define_method(StringScanner, "captures",    strscan_captures,    0);
1402
    rb_define_method(StringScanner, "values_at",   strscan_values_at,   -1);
1403

    
1404
    rb_define_method(StringScanner, "rest",        strscan_rest,        0);
1405
    rb_define_method(StringScanner, "rest_size",   strscan_rest_size,   0);
1406
    rb_define_method(StringScanner, "restsize",    strscan_restsize,    0);
1407

    
1408
    rb_define_method(StringScanner, "inspect",     strscan_inspect,     0);
1409
}