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:

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.



299
300
301
302
303
# File 'ext/strscan/strscan.c', line 299

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"


392
393
394
395
396
397
398
399
400
401
# File 'ext/strscan/strscan.c', line 392

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                        # -> ""


1150
1151
1152
1153
1154
1155
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
# File 'ext/strscan/strscan.c', line 1150

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 (!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 iff 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)


991
992
993
994
995
996
997
998
999
1000
# File 'ext/strscan/strscan.c', line 991

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


1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
# File 'ext/strscan/strscan.c', line 1216

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ädeföghi")
s.charpos           # -> 0
s.scan_until(/ä/)   # -> "abcä"
s.pos               # -> 5
s.charpos           # -> 4


439
440
441
442
443
444
445
446
447
448
449
450
# File 'ext/strscan/strscan.c', line 439

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

    GET_SCANNER(self, p);

    substr = rb_funcall(p->str, id_byteslice, 2, INT2FIX(0), INT2NUM(p->curr));

    return rb_str_length(substr);
}

#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.



708
709
710
711
712
# File 'ext/strscan/strscan.c', line 708

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.



802
803
804
805
806
# File 'ext/strscan/strscan.c', line 802

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.



341
342
343
344
345
346
# File 'ext/strscan/strscan.c', line 341

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"


392
393
394
395
396
397
398
399
400
401
# File 'ext/strscan/strscan.c', line 392

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)


1025
1026
1027
1028
1029
1030
# File 'ext/strscan/strscan.c', line 1025

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)


1012
1013
1014
1015
1016
1017
1018
1019
# File 'ext/strscan/strscan.c', line 1012

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)


761
762
763
764
765
# File 'ext/strscan/strscan.c', line 761

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)


1448
1449
1450
1451
1452
1453
1454
# File 'ext/strscan/strscan.c', line 1448

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

$KCODE = 'EUC'
s = StringScanner.new("\244\242")
s.get_byte         # => "\244"
s.get_byte         # => "\242"
s.get_byte         # => nil


887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
# File 'ext/strscan/strscan.c', line 887

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.



910
911
912
913
914
915
# File 'ext/strscan/strscan.c', line 910

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

$KCODE = 'EUC'
s = StringScanner.new("\244\242")
s.getch           # => "\244\242"   # Japanese hira-kana "A" in EUC-JP
s.getch           # => nil


849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
# File 'ext/strscan/strscan.c', line 849

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…”>’



1370
1371
1372
1373
1374
1375
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
# File 'ext/strscan/strscan.c', line 1370

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 infect(a, p);
    }
    if (EOS_P(p)) {
	a = rb_sprintf("#<%"PRIsVALUE" fin>", rb_obj_class(self));
	return infect(a, p);
    }
    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 infect(a, p);
    }
    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 infect(a, p);
}

#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)


663
664
665
666
667
# File 'ext/strscan/strscan.c', line 663

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"


1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
# File 'ext/strscan/strscan.c', line 1074

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 iff 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)


1058
1059
1060
1061
1062
1063
1064
1065
# File 'ext/strscan/strscan.c', line 1058

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 (see #matched), or nil if there was no recent match.

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


1096
1097
1098
1099
1100
1101
1102
1103
1104
# File 'ext/strscan/strscan.c', line 1096

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

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

#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"


928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
# File 'ext/strscan/strscan.c', line 928

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 infect(str_new(p, "", 0), p);

    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.



948
949
950
951
952
953
# File 'ext/strscan/strscan.c', line 948

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


417
418
419
420
421
422
423
424
# File 'ext/strscan/strscan.c', line 417

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"


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

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 INT2NUM(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


417
418
419
420
421
422
423
424
# File 'ext/strscan/strscan.c', line 417

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"


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

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 INT2NUM(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"


1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
# File 'ext/strscan/strscan.c', line 1301

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"


1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
# File 'ext/strscan/strscan.c', line 1280

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.



308
309
310
311
312
313
314
315
316
317
# File 'ext/strscan/strscan.c', line 308

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 "".



1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
# File 'ext/strscan/strscan.c', line 1317

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

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

#rest?Boolean

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

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

Returns:

  • (Boolean)


1040
1041
1042
1043
1044
1045
1046
1047
# File 'ext/strscan/strscan.c', line 1040

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.



1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
# File 'ext/strscan/strscan.c', line 1332

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.



1350
1351
1352
1353
1354
1355
# File 'ext/strscan/strscan.c', line 1350

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)


645
646
647
648
649
# File 'ext/strscan/strscan.c', line 645

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”.



724
725
726
727
728
# File 'ext/strscan/strscan.c', line 724

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


742
743
744
745
746
# File 'ext/strscan/strscan.c', line 742

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.



817
818
819
820
821
# File 'ext/strscan/strscan.c', line 817

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


1194
1195
1196
1197
1198
1199
1200
1201
1202
# File 'ext/strscan/strscan.c', line 1194

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


687
688
689
690
691
# File 'ext/strscan/strscan.c', line 687

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                           #


783
784
785
786
787
# File 'ext/strscan/strscan.c', line 783

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

#stringObject

Returns the string being scanned.



351
352
353
354
355
356
357
358
# File 'ext/strscan/strscan.c', line 351

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.



366
367
368
369
370
371
372
373
374
375
376
# File 'ext/strscan/strscan.c', line 366

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.



326
327
328
329
330
331
332
333
334
335
# File 'ext/strscan/strscan.c', line 326

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


966
967
968
969
970
971
972
973
974
975
976
977
# File 'ext/strscan/strscan.c', line 966

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)


1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
# File 'ext/strscan/strscan.c', line 1253

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;
}