Class: StringScanner

Inherits:
Object
  • Object
show all
Defined in:
ext/strscan/strscan.c,
ext/strscan/strscan.c

Overview

StringScanner provides for lexical scanning operations on a String. Here is an example of its usage:

require 'strscan'

s = StringScanner.new('This is an example string')
s.eos?               # -> false

p s.scan(/\w+/)      # -> "This"
p s.scan(/\w+/)      # -> nil
p s.scan(/\s+/)      # -> " "
p s.scan(/\s+/)      # -> nil
p s.scan(/\w+/)      # -> "is"
s.eos?               # -> false

p s.scan(/\s+/)      # -> " "
p s.scan(/\w+/)      # -> "an"
p s.scan(/\s+/)      # -> " "
p s.scan(/\w+/)      # -> "example"
p s.scan(/\s+/)      # -> " "
p s.scan(/\w+/)      # -> "string"
s.eos?               # -> true

p s.scan(/\s+/)      # -> nil
p s.scan(/\w+/)      # -> nil

Scanning a string means remembering the position of a scan pointer, which is just an index. The point of scanning is to move forward a bit at a time, so matches are sought after the scan pointer; usually immediately after it.

Given the string “test string”, here are the pertinent scan pointer positions:

  t e s t   s t r i n g
0 1 2 ...             1
                      0

When you #scan for a pattern (a regular expression), the match must occur at the character after the scan pointer. If you use #scan_until, then the match can occur anywhere after the scan pointer. In both cases, the scan pointer moves just beyond the last character of the match, ready to scan again from the next character onwards. This is demonstrated by the example above.

Method Categories

There are other methods besides the plain scanners. You can look ahead in the string without actually scanning. You can access the most recent match. You can modify the string being scanned, reset or terminate the scanner, find out or change the position of the scan pointer, skip ahead, and so on.

Advancing the Scan Pointer

  • #getch

  • #get_byte

  • #scan

  • #scan_until

  • #skip

  • #skip_until

Looking Ahead

  • #check

  • #check_until

  • #exist?

  • #match?

  • #peek

Finding Where we Are

  • #beginning_of_line? (#bol?)

  • #eos?

  • #rest?

  • #rest_size

  • #pos

Setting Where we Are

  • #reset

  • #terminate

  • #pos=

Match Data

  • #matched

  • #matched?

  • #matched_size

  • #[]

  • #pre_match

  • #post_match

Miscellaneous

  • <<

  • #concat

  • #string

  • #string=

  • #unscan

There are aliases to several of the methods.

Defined Under Namespace

Classes: Error

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.must_C_versionObject

This method is defined for backward compatibility.



304
305
306
307
308
# File 'ext/strscan/strscan.c', line 304

static VALUE
strscan_s_mustc(VALUE self)
{
    return self;
}

Instance Method Details

#concat(str) ⇒ Object #<<(str) ⇒ Object

Appends str to the string being scanned. This method does not affect scan pointer.

s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan(/Fri /)
s << " +1000 GMT"
s.string            # -> "Fri Dec 12 1975 14:39 +1000 GMT"
s.scan(/Dec/)       # -> "Dec"


397
398
399
400
401
402
403
404
405
406
# File 'ext/strscan/strscan.c', line 397

static VALUE
strscan_concat(VALUE self, VALUE str)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    StringValue(str);
    rb_str_append(p->str, str);
    return self;
}

#[](n) ⇒ Object

Returns the n-th subgroup in the most recent match.

s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan(/(\w+) (\w+) (\d+) /)       # -> "Fri Dec 12 "
s[0]                               # -> "Fri Dec 12 "
s[1]                               # -> "Fri"
s[2]                               # -> "Dec"
s[3]                               # -> "12"
s.post_match                       # -> "1975 14:39"
s.pre_match                        # -> ""

s.reset
s.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)       # -> "Fri Dec 12 "
s[0]                               # -> "Fri Dec 12 "
s[1]                               # -> "Fri"
s[2]                               # -> "Dec"
s[3]                               # -> "12"
s[:wday]                           # -> "Fri"
s[:month]                          # -> "Dec"
s[:day]                            # -> "12"
s.post_match                       # -> "1975 14:39"
s.pre_match                        # -> ""


1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
# File 'ext/strscan/strscan.c', line 1156

static VALUE
strscan_aref(VALUE self, VALUE idx)
{
    const char *name;
    struct strscanner *p;
    long i;

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

    switch (TYPE(idx)) {
        case T_SYMBOL:
            idx = rb_sym2str(idx);
            /* fall through */
        case T_STRING:
            if (!RTEST(p->regex)) return Qnil;
            RSTRING_GETMEM(idx, name, i);
            i = name_to_backref_number(&(p->regs), p->regex, name, name + i, rb_enc_get(idx));
            break;
        default:
            i = NUM2LONG(idx);
    }

    if (i < 0)
        i += p->regs.num_regs;
    if (i < 0)                 return Qnil;
    if (i >= p->regs.num_regs) return Qnil;
    if (p->regs.beg[i] == -1)  return Qnil;

    return extract_range(p,
                         adjust_register_position(p, p->regs.beg[i]),
                         adjust_register_position(p, p->regs.end[i]));
}

#beginning_of_line?Boolean

Returns true if and only if the scan pointer is at the beginning of the line.

s = StringScanner.new("test\ntest\n")
s.bol?           # => true
s.scan(/te/)
s.bol?           # => false
s.scan(/st\n/)
s.bol?           # => true
s.terminate
s.bol?           # => true

Returns:

  • (Boolean)


995
996
997
998
999
1000
1001
1002
1003
1004
# File 'ext/strscan/strscan.c', line 995

static VALUE
strscan_bol_p(VALUE self)
{
    struct strscanner *p;

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

#capturesObject

Returns the subgroups in the most recent match (not including the full match). If nothing was priorly matched, it returns nil.

s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan(/(\w+) (\w+) (\d+) /)       # -> "Fri Dec 12 "
s.captures                         # -> ["Fri", "Dec", "12"]
s.scan(/(\w+) (\w+) (\d+) /)       # -> nil
s.captures                         # -> nil


1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
# File 'ext/strscan/strscan.c', line 1222

static VALUE
strscan_captures(VALUE self)
{
    struct strscanner *p;
    int   i, num_regs;
    VALUE new_ary;

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

    num_regs = p->regs.num_regs;
    new_ary  = rb_ary_new2(num_regs);

    for (i = 1; i < num_regs; i++) {
        VALUE str = extract_range(p,
                                  adjust_register_position(p, p->regs.beg[i]),
                                  adjust_register_position(p, p->regs.end[i]));
        rb_ary_push(new_ary, str);
    }

    return new_ary;
}

#charposObject

Returns the character position of the scan pointer. In the ‘reset’ position, this value is zero. In the ‘terminated’ position (i.e. the string is exhausted), this value is the size of the string.

In short, it’s a 0-based index into the string.

s = StringScanner.new("abc\u00e4def\u00f6ghi")
s.charpos                # -> 0
s.scan_until(/\u00e4/)   # -> "abc\u00E4"
s.pos                    # -> 5
s.charpos                # -> 4


444
445
446
447
448
449
450
451
452
# File 'ext/strscan/strscan.c', line 444

static VALUE
strscan_get_charpos(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);

    return LONG2NUM(rb_enc_strlen(S_PBEG(p), CURPTR(p), rb_enc_get(p->str)));
}

#check(pattern) ⇒ Object

This returns the value that #scan would return, without advancing the scan pointer. The match register is affected, though.

s = StringScanner.new("Fri Dec 12 1975 14:39")
s.check /Fri/               # -> "Fri"
s.pos                       # -> 0
s.matched                   # -> "Fri"
s.check /12/                # -> nil
s.matched                   # -> nil

Mnemonic: it “checks” to see whether a #scan will return a value.



714
715
716
717
718
# File 'ext/strscan/strscan.c', line 714

static VALUE
strscan_check(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 0, 1, 1);
}

#check_until(pattern) ⇒ Object

This returns the value that #scan_until would return, without advancing the scan pointer. The match register is affected, though.

s = StringScanner.new("Fri Dec 12 1975 14:39")
s.check_until /12/          # -> "Fri Dec 12"
s.pos                       # -> 0
s.matched                   # -> 12

Mnemonic: it “checks” to see whether a #scan_until will return a value.



808
809
810
811
812
# File 'ext/strscan/strscan.c', line 808

static VALUE
strscan_check_until(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 0, 1, 0);
}

#clearObject

Equivalent to #terminate. This method is obsolete; use #terminate instead.



346
347
348
349
350
351
# File 'ext/strscan/strscan.c', line 346

static VALUE
strscan_clear(VALUE self)
{
    rb_warning("StringScanner#clear is obsolete; use #terminate instead");
    return strscan_terminate(self);
}

#concat(str) ⇒ Object #<<(str) ⇒ Object

Appends str to the string being scanned. This method does not affect scan pointer.

s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan(/Fri /)
s << " +1000 GMT"
s.string            # -> "Fri Dec 12 1975 14:39 +1000 GMT"
s.scan(/Dec/)       # -> "Dec"


397
398
399
400
401
402
403
404
405
406
# File 'ext/strscan/strscan.c', line 397

static VALUE
strscan_concat(VALUE self, VALUE str)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    StringValue(str);
    rb_str_append(p->str, str);
    return self;
}

#empty?Boolean

Equivalent to #eos?. This method is obsolete, use #eos? instead.

Returns:

  • (Boolean)


1029
1030
1031
1032
1033
1034
# File 'ext/strscan/strscan.c', line 1029

static VALUE
strscan_empty_p(VALUE self)
{
    rb_warning("StringScanner#empty? is obsolete; use #eos? instead");
    return strscan_eos_p(self);
}

#eos?Boolean

Returns true if the scan pointer is at the end of the string.

s = StringScanner.new('test string')
p s.eos?          # => false
s.scan(/test/)
p s.eos?          # => false
s.terminate
p s.eos?          # => true

Returns:

  • (Boolean)


1016
1017
1018
1019
1020
1021
1022
1023
# File 'ext/strscan/strscan.c', line 1016

static VALUE
strscan_eos_p(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    return EOS_P(p) ? Qtrue : Qfalse;
}

#exist?(pattern) ⇒ Boolean

Looks ahead to see if the pattern exists anywhere in the string, without advancing the scan pointer. This predicates whether a #scan_until will return a value.

s = StringScanner.new('test string')
s.exist? /s/            # -> 3
s.scan /test/           # -> "test"
s.exist? /s/            # -> 2
s.exist? /e/            # -> nil

Returns:

  • (Boolean)


767
768
769
770
771
# File 'ext/strscan/strscan.c', line 767

static VALUE
strscan_exist_p(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 0, 0, 0);
}

#fixed_anchor?Boolean

Whether scanner uses fixed anchor mode or not.

If fixed anchor mode is used, \A always matches the beginning of the string. Otherwise, \A always matches the current position.

Returns:

  • (Boolean)


1454
1455
1456
1457
1458
1459
1460
# File 'ext/strscan/strscan.c', line 1454

static VALUE
strscan_fixed_anchor_p(VALUE self)
{
    struct strscanner *p;
    p = check_strscan(self);
    return p->fixed_anchor_p ? Qtrue : Qfalse;
}

#get_byteObject

Scans one byte and returns it. This method is not multibyte character sensitive. See also: #getch.

s = StringScanner.new('ab')
s.get_byte         # => "a"
s.get_byte         # => "b"
s.get_byte         # => nil

s = StringScanner.new("\244\242".force_encoding("euc-jp"))
s.get_byte         # => "\xA4"
s.get_byte         # => "\xA2"
s.get_byte         # => nil


891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
# File 'ext/strscan/strscan.c', line 891

static VALUE
strscan_get_byte(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    CLEAR_MATCH_STATUS(p);
    if (EOS_P(p))
        return Qnil;

    p->prev = p->curr;
    p->curr++;
    MATCHED(p);
    adjust_registers_to_matched(p);
    return extract_range(p,
                         adjust_register_position(p, p->regs.beg[0]),
                         adjust_register_position(p, p->regs.end[0]));
}

#getbyteObject

Equivalent to #get_byte. This method is obsolete; use #get_byte instead.



914
915
916
917
918
919
# File 'ext/strscan/strscan.c', line 914

static VALUE
strscan_getbyte(VALUE self)
{
    rb_warning("StringScanner#getbyte is obsolete; use #get_byte instead");
    return strscan_get_byte(self);
}

#getchObject

Scans one character and returns it. This method is multibyte character sensitive.

s = StringScanner.new("ab")
s.getch           # => "a"
s.getch           # => "b"
s.getch           # => nil

s = StringScanner.new("\244\242".force_encoding("euc-jp"))
s.getch           # => "\x{A4A2}"   # Japanese hira-kana "A" in EUC-JP
s.getch           # => nil


854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
# File 'ext/strscan/strscan.c', line 854

static VALUE
strscan_getch(VALUE self)
{
    struct strscanner *p;
    long len;

    GET_SCANNER(self, p);
    CLEAR_MATCH_STATUS(p);
    if (EOS_P(p))
        return Qnil;

    len = rb_enc_mbclen(CURPTR(p), S_PEND(p), rb_enc_get(p->str));
    len = minl(len, S_RESTLEN(p));
    p->prev = p->curr;
    p->curr += len;
    MATCHED(p);
    adjust_registers_to_matched(p);
    return extract_range(p,
                         adjust_register_position(p, p->regs.beg[0]),
                         adjust_register_position(p, p->regs.end[0]));
}

#inspectObject

Returns a string that represents the StringScanner object, showing:

  • the current position

  • the size of the string

  • the characters surrounding the scan pointer

    s = StringScanner.new(“Fri Dec 12 1975 14:39”) s.inspect # -> ‘#<StringScanner 0/21 @ “Fri D…”>’ s.scan_until /12/ # -> “Fri Dec 12” s.inspect # -> ‘#<StringScanner 10/21 “…ec 12” @ “ 1975…”>’



1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
# File 'ext/strscan/strscan.c', line 1376

static VALUE
strscan_inspect(VALUE self)
{
    struct strscanner *p;
    VALUE a, b;

    p = check_strscan(self);
    if (NIL_P(p->str)) {
	a = rb_sprintf("#<%"PRIsVALUE" (uninitialized)>", rb_obj_class(self));
	return a;
    }
    if (EOS_P(p)) {
	a = rb_sprintf("#<%"PRIsVALUE" fin>", rb_obj_class(self));
	return a;
    }
    if (p->curr == 0) {
	b = inspect2(p);
	a = rb_sprintf("#<%"PRIsVALUE" %ld/%ld @ %"PRIsVALUE">",
		       rb_obj_class(self),
		       p->curr, S_LEN(p),
		       b);
	return a;
    }
    a = inspect1(p);
    b = inspect2(p);
    a = rb_sprintf("#<%"PRIsVALUE" %ld/%ld %"PRIsVALUE" @ %"PRIsVALUE">",
		   rb_obj_class(self),
		   p->curr, S_LEN(p),
		   a, b);
    return a;
}

#match?(pattern) ⇒ Boolean

Tests whether the given pattern is matched from the current scan pointer. Returns the length of the match, or nil. The scan pointer is not advanced.

s = StringScanner.new('test string')
p s.match?(/\w+/)   # -> 4
p s.match?(/\w+/)   # -> 4
p s.match?("test")  # -> 4
p s.match?(/\s+/)   # -> nil

Returns:

  • (Boolean)


669
670
671
672
673
# File 'ext/strscan/strscan.c', line 669

static VALUE
strscan_match_p(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 0, 0, 1);
}

#matchedObject

Returns the last matched string.

s = StringScanner.new('test string')
s.match?(/\w+/)     # -> 4
s.matched           # -> "test"


1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
# File 'ext/strscan/strscan.c', line 1079

static VALUE
strscan_matched(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    if (! MATCHED_P(p)) return Qnil;
    return extract_range(p,
                         adjust_register_position(p, p->regs.beg[0]),
                         adjust_register_position(p, p->regs.end[0]));
}

#matched?Boolean

Returns true if and only if the last match was successful.

s = StringScanner.new('test string')
s.match?(/\w+/)     # => 4
s.matched?          # => true
s.match?(/\d+/)     # => nil
s.matched?          # => false

Returns:

  • (Boolean)


1063
1064
1065
1066
1067
1068
1069
1070
# File 'ext/strscan/strscan.c', line 1063

static VALUE
strscan_matched_p(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    return MATCHED_P(p) ? Qtrue : Qfalse;
}

#matched_sizeObject

Returns the size of the most recent match in bytes, or nil if there was no recent match. This is different than matched.size, which will return the size in characters.

s = StringScanner.new('test string')
s.check /\w+/           # -> "test"
s.matched_size          # -> 4
s.check /\d+/           # -> nil
s.matched_size          # -> nil


1102
1103
1104
1105
1106
1107
1108
1109
1110
# File 'ext/strscan/strscan.c', line 1102

static VALUE
strscan_matched_size(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    if (! MATCHED_P(p)) return Qnil;
    return LONG2NUM(p->regs.end[0] - p->regs.beg[0]);
}

#named_capturesHash

Returns a hash of string variables matching the regular expression.

scan = StringScanner.new('foobarbaz')
scan.match?(/(?<f>foo)(?<r>bar)(?<z>baz)/)
scan.named_captures # -> {"f"=>"foo", "r"=>"bar", "z"=>"baz"}

Returns:

  • (Hash)


1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
# File 'ext/strscan/strscan.c', line 1497

static VALUE
strscan_named_captures(VALUE self)
{
    struct strscanner *p;
    GET_SCANNER(self, p);
    named_captures_data data;
    data.self = self;
    data.captures = rb_hash_new();
    onig_foreach_name(RREGEXP_PTR(p->regex), named_captures_iter, &data);

    return data.captures;
}

#peek(len) ⇒ Object

Extracts a string corresponding to string[pos,len], without advancing the scan pointer.

s = StringScanner.new('test string')
s.peek(7)          # => "test st"
s.peek(7)          # => "test st"


932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
# File 'ext/strscan/strscan.c', line 932

static VALUE
strscan_peek(VALUE self, VALUE vlen)
{
    struct strscanner *p;
    long len;

    GET_SCANNER(self, p);

    len = NUM2LONG(vlen);
    if (EOS_P(p))
        return str_new(p, "", 0);

    len = minl(len, S_RESTLEN(p));
    return extract_beg_len(p, p->curr, len);
}

#peep(vlen) ⇒ Object

Equivalent to #peek. This method is obsolete; use #peek instead.



952
953
954
955
956
957
# File 'ext/strscan/strscan.c', line 952

static VALUE
strscan_peep(VALUE self, VALUE vlen)
{
    rb_warning("StringScanner#peep is obsolete; use #peek instead");
    return strscan_peek(self, vlen);
}

#pointerObject

Returns the byte position of the scan pointer. In the ‘reset’ position, this value is zero. In the ‘terminated’ position (i.e. the string is exhausted), this value is the bytesize of the string.

In short, it’s a 0-based index into bytes of the string.

s = StringScanner.new('test string')
s.pos               # -> 0
s.scan_until /str/  # -> "test str"
s.pos               # -> 8
s.terminate         # -> #<StringScanner fin>
s.pos               # -> 11


422
423
424
425
426
427
428
429
# File 'ext/strscan/strscan.c', line 422

static VALUE
strscan_get_pos(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    return INT2FIX(p->curr);
}

#pos=(n) ⇒ Object

Sets the byte position of the scan pointer.

s = StringScanner.new('test string')
s.pos = 7            # -> 7
s.rest               # -> "ring"


463
464
465
466
467
468
469
470
471
472
473
474
475
476
# File 'ext/strscan/strscan.c', line 463

static VALUE
strscan_set_pos(VALUE self, VALUE v)
{
    struct strscanner *p;
    long i;

    GET_SCANNER(self, p);
    i = NUM2INT(v);
    if (i < 0) i += S_LEN(p);
    if (i < 0) rb_raise(rb_eRangeError, "index out of range");
    if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range");
    p->curr = i;
    return LONG2NUM(i);
}

#posObject

Returns the byte position of the scan pointer. In the ‘reset’ position, this value is zero. In the ‘terminated’ position (i.e. the string is exhausted), this value is the bytesize of the string.

In short, it’s a 0-based index into bytes of the string.

s = StringScanner.new('test string')
s.pos               # -> 0
s.scan_until /str/  # -> "test str"
s.pos               # -> 8
s.terminate         # -> #<StringScanner fin>
s.pos               # -> 11


422
423
424
425
426
427
428
429
# File 'ext/strscan/strscan.c', line 422

static VALUE
strscan_get_pos(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    return INT2FIX(p->curr);
}

#pos=(n) ⇒ Object

Sets the byte position of the scan pointer.

s = StringScanner.new('test string')
s.pos = 7            # -> 7
s.rest               # -> "ring"


463
464
465
466
467
468
469
470
471
472
473
474
475
476
# File 'ext/strscan/strscan.c', line 463

static VALUE
strscan_set_pos(VALUE self, VALUE v)
{
    struct strscanner *p;
    long i;

    GET_SCANNER(self, p);
    i = NUM2INT(v);
    if (i < 0) i += S_LEN(p);
    if (i < 0) rb_raise(rb_eRangeError, "index out of range");
    if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range");
    p->curr = i;
    return LONG2NUM(i);
}

#post_matchObject

Returns the post-match (in the regular expression sense) of the last scan.

s = StringScanner.new('test string')
s.scan(/\w+/)           # -> "test"
s.scan(/\s+/)           # -> " "
s.pre_match             # -> "test"
s.post_match            # -> "string"


1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
# File 'ext/strscan/strscan.c', line 1307

static VALUE
strscan_post_match(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    if (! MATCHED_P(p)) return Qnil;
    return extract_range(p,
                         adjust_register_position(p, p->regs.end[0]),
                         S_LEN(p));
}

#pre_matchObject

Returns the pre-match (in the regular expression sense) of the last scan.

s = StringScanner.new('test string')
s.scan(/\w+/)           # -> "test"
s.scan(/\s+/)           # -> " "
s.pre_match             # -> "test"
s.post_match            # -> "string"


1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
# File 'ext/strscan/strscan.c', line 1286

static VALUE
strscan_pre_match(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    if (! MATCHED_P(p)) return Qnil;
    return extract_range(p,
                         0,
                         adjust_register_position(p, p->regs.beg[0]));
}

#resetObject

Reset the scan pointer (index 0) and clear matching data.



313
314
315
316
317
318
319
320
321
322
# File 'ext/strscan/strscan.c', line 313

static VALUE
strscan_reset(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    p->curr = 0;
    CLEAR_MATCH_STATUS(p);
    return self;
}

#restObject

Returns the “rest” of the string (i.e. everything after the scan pointer). If there is no more data (eos? = true), it returns "".



1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
# File 'ext/strscan/strscan.c', line 1323

static VALUE
strscan_rest(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    if (EOS_P(p)) {
        return str_new(p, "", 0);
    }
    return extract_range(p, p->curr, S_LEN(p));
}

#rest?Boolean

Returns true if and only if there is more data in the string. See #eos?. This method is obsolete; use #eos? instead.

s = StringScanner.new('test string')
# These two are opposites
s.eos? # => false
s.rest? # => true

Returns:

  • (Boolean)


1045
1046
1047
1048
1049
1050
1051
1052
# File 'ext/strscan/strscan.c', line 1045

static VALUE
strscan_rest_p(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    return EOS_P(p) ? Qfalse : Qtrue;
}

#rest_sizeObject

s.rest_size is equivalent to s.rest.size.



1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
# File 'ext/strscan/strscan.c', line 1338

static VALUE
strscan_rest_size(VALUE self)
{
    struct strscanner *p;
    long i;

    GET_SCANNER(self, p);
    if (EOS_P(p)) {
        return INT2FIX(0);
    }
    i = S_RESTLEN(p);
    return INT2FIX(i);
}

#restsizeObject

s.restsize is equivalent to s.rest_size. This method is obsolete; use #rest_size instead.



1356
1357
1358
1359
1360
1361
# File 'ext/strscan/strscan.c', line 1356

static VALUE
strscan_restsize(VALUE self)
{
    rb_warning("StringScanner#restsize is obsolete; use #rest_size instead");
    return strscan_rest_size(self);
}

#scan(pattern) ⇒ String

Tries to match with pattern at the current position. If there’s a match, the scanner advances the “scan pointer” and returns the matched string. Otherwise, the scanner returns nil.

s = StringScanner.new('test string')
p s.scan(/\w+/)   # -> "test"
p s.scan(/\w+/)   # -> nil
p s.scan(/\s+/)   # -> " "
p s.scan("str")   # -> "str"
p s.scan(/\w+/)   # -> "ing"
p s.scan(/./)     # -> nil

Returns:

  • (String)


651
652
653
654
655
# File 'ext/strscan/strscan.c', line 651

static VALUE
strscan_scan(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 1, 1, 1);
}

#scan_full(pattern, advance_pointer_p, return_string_p) ⇒ Object

Tests whether the given pattern is matched from the current scan pointer. Advances the scan pointer if advance_pointer_p is true. Returns the matched string if return_string_p is true. The match register is affected.

“full” means “#scan with full parameters”.



730
731
732
733
734
# File 'ext/strscan/strscan.c', line 730

static VALUE
strscan_scan_full(VALUE self, VALUE re, VALUE s, VALUE f)
{
    return strscan_do_scan(self, re, RTEST(s), RTEST(f), 1);
}

#scan_until(pattern) ⇒ Object

Scans the string until the pattern is matched. Returns the substring up to and including the end of the match, advancing the scan pointer to that location. If there is no match, nil is returned.

s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan_until(/1/)        # -> "Fri Dec 1"
s.pre_match              # -> "Fri Dec "
s.scan_until(/XYZ/)      # -> nil


748
749
750
751
752
# File 'ext/strscan/strscan.c', line 748

static VALUE
strscan_scan_until(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 1, 1, 0);
}

#search_full(pattern, advance_pointer_p, return_string_p) ⇒ Object

Scans the string until the pattern is matched. Advances the scan pointer if advance_pointer_p, otherwise not. Returns the matched string if return_string_p is true, otherwise returns the number of bytes advanced. This method does affect the match register.



823
824
825
826
827
# File 'ext/strscan/strscan.c', line 823

static VALUE
strscan_search_full(VALUE self, VALUE re, VALUE s, VALUE f)
{
    return strscan_do_scan(self, re, RTEST(s), RTEST(f), 0);
}

#sizeObject

Returns the amount of subgroups in the most recent match. The full match counts as a subgroup.

s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan(/(\w+) (\w+) (\d+) /)       # -> "Fri Dec 12 "
s.size                             # -> 4


1200
1201
1202
1203
1204
1205
1206
1207
1208
# File 'ext/strscan/strscan.c', line 1200

static VALUE
strscan_size(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    if (! MATCHED_P(p))        return Qnil;
    return INT2FIX(p->regs.num_regs);
}

#skip(pattern) ⇒ Object

Attempts to skip over the given pattern beginning with the scan pointer. If it matches, the scan pointer is advanced to the end of the match, and the length of the match is returned. Otherwise, nil is returned.

It’s similar to #scan, but without returning the matched string.

s = StringScanner.new('test string')
p s.skip(/\w+/)   # -> 4
p s.skip(/\w+/)   # -> nil
p s.skip(/\s+/)   # -> 1
p s.skip("st")    # -> 2
p s.skip(/\w+/)   # -> 4
p s.skip(/./)     # -> nil


693
694
695
696
697
# File 'ext/strscan/strscan.c', line 693

static VALUE
strscan_skip(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 1, 0, 1);
}

#skip_until(pattern) ⇒ Object

Advances the scan pointer until pattern is matched and consumed. Returns the number of bytes advanced, or nil if no match was found.

Look ahead to match pattern, and advance the scan pointer to the end of the match. Return the number of characters advanced, or nil if the match was unsuccessful.

It’s similar to #scan_until, but without returning the intervening string.

s = StringScanner.new("Fri Dec 12 1975 14:39")
s.skip_until /12/           # -> 10
s                           #


789
790
791
792
793
# File 'ext/strscan/strscan.c', line 789

static VALUE
strscan_skip_until(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 1, 0, 0);
}

#stringObject

Returns the string being scanned.



356
357
358
359
360
361
362
363
# File 'ext/strscan/strscan.c', line 356

static VALUE
strscan_get_string(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    return p->str;
}

#string=(str) ⇒ Object

Changes the string being scanned to str and resets the scanner. Returns str.



371
372
373
374
375
376
377
378
379
380
381
# File 'ext/strscan/strscan.c', line 371

static VALUE
strscan_set_string(VALUE self, VALUE str)
{
    struct strscanner *p = check_strscan(self);

    StringValue(str);
    p->str = str;
    p->curr = 0;
    CLEAR_MATCH_STATUS(p);
    return str;
}

#terminateObject #clearObject

Sets the scan pointer to the end of the string and clear matching data.



331
332
333
334
335
336
337
338
339
340
# File 'ext/strscan/strscan.c', line 331

static VALUE
strscan_terminate(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    p->curr = S_LEN(p);
    CLEAR_MATCH_STATUS(p);
    return self;
}

#unscanObject

Sets the scan pointer to the previous position. Only one previous position is remembered, and it changes with each scanning operation.

s = StringScanner.new('test string')
s.scan(/\w+/)        # => "test"
s.unscan
s.scan(/../)         # => "te"
s.scan(/\d/)         # => nil
s.unscan             # ScanError: unscan failed: previous match record not exist


970
971
972
973
974
975
976
977
978
979
980
981
# File 'ext/strscan/strscan.c', line 970

static VALUE
strscan_unscan(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    if (! MATCHED_P(p))
        rb_raise(ScanError, "unscan failed: previous match record not exist");
    p->curr = p->prev;
    CLEAR_MATCH_STATUS(p);
    return self;
}

#values_at(i1, i2, ...iN) ⇒ Array

Returns the subgroups in the most recent match at the given indices. If nothing was priorly matched, it returns nil.

s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan(/(\w+) (\w+) (\d+) /)       # -> "Fri Dec 12 "
s.values_at 0, -1, 5, 2            # -> ["Fri Dec 12 ", "12", nil, "Dec"]
s.scan(/(\w+) (\w+) (\d+) /)       # -> nil
s.values_at 0, -1, 5, 2            # -> nil

Returns:

  • (Array)


1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
# File 'ext/strscan/strscan.c', line 1259

static VALUE
strscan_values_at(int argc, VALUE *argv, VALUE self)
{
    struct strscanner *p;
    long i;
    VALUE new_ary;

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

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

    return new_ary;
}