Class: StringScanner

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

Overview

:markup: markdown

:include: strscan/link_refs.txt :include: strscan/strscan.md

Defined Under Namespace

Classes: Error

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.must_C_versionObject

:nodoc:



325
326
327
328
329
# File 'strscan.c', line 325

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

Instance Method Details

#<<(str) ⇒ Object

:markup: markdown :include: strscan/link_refs.txt

call-seq:

concat(more_string) -> self
  • Appends the given ‘more_string` to the [stored string].

  • Returns ‘self`.

  • Does not affect the [positions] or [match values].

“‘rb scanner = StringScanner.new(’foo’) scanner.string # => “foo” scanner.terminate scanner.concat(‘barbaz’) # => #<StringScanner 3/9 “foo” @ “barba…”> scanner.string # => “foobarbaz” put_situation(scanner) # Situation: # pos: 3 # charpos: 3 # rest: “barbaz” # rest_size: 6 “‘



501
502
503
504
505
506
507
508
509
510
# File 'strscan.c', line 501

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

#[](idx) ⇒ Object

:markup: markdown :include: strscan/link_refs.txt

call-seq:

[](specifier) -> substring or nil

Returns a captured substring or ‘nil`; see [Captured Match Values].

When there are captures:

“‘rb scanner = StringScanner.new(’Fri Dec 12 1975 14:39’) scanner.scan(/(?<wday>w+) (?<month>w+) (?<day>d+) /) “‘

  • ‘specifier` zero: returns the entire matched substring:

    ```rb
    scanner[0]         # => "Fri Dec 12 "
    scanner.pre_match  # => ""
    scanner.post_match # => "1975 14:39"
    ```
    
  • ‘specifier` positive integer. returns the `n`th capture, or `nil` if out of range:

    ```rb
    scanner[1] # => "Fri"
    scanner[2] # => "Dec"
    scanner[3] # => "12"
    scanner[4] # => nil
    ```
    
  • ‘specifier` negative integer. counts backward from the last subgroup:

    ```rb
    scanner[-1] # => "12"
    scanner[-4] # => "Fri Dec 12 "
    scanner[-5] # => nil
    ```
    
  • ‘specifier` symbol or string. returns the named subgroup, or `nil` if no such:

    ```rb
    scanner[:wday]  # => "Fri"
    scanner['wday'] # => "Fri"
    scanner[:month] # => "Dec"
    scanner[:day]   # => "12"
    scanner[:nope]  # => nil
    ```
    

When there are no captures, only ‘[0]` returns non-`nil`:

“‘rb scanner = StringScanner.new(’foobarbaz’) scanner.exist?(/bar/) scanner # => “bar” scanner # => nil “‘

For a failed match, even ‘[0]` returns `nil`:

“‘rb scanner.scan(/nope/) # => nil scanner # => nil scanner # => nil “`



1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
# File 'strscan.c', line 1749

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

:markup: markdown :include: strscan/link_refs.txt

call-seq:

beginning_of_line? -> true or false

Returns whether the [position] is at the beginning of a line; that is, at the beginning of the [stored string] or immediately after a newline:

scanner = StringScanner.new(MULTILINE_TEXT)
scanner.string
# => "Go placidly amid the noise and haste,\nand remember what peace there may be in silence.\n"
scanner.pos                # => 0
scanner.beginning_of_line? # => true

scanner.scan_until(/,/)    # => "Go placidly amid the noise and haste,"
scanner.beginning_of_line? # => false

scanner.scan(/\n/)         # => "\n"
scanner.beginning_of_line? # => true

scanner.terminate
scanner.beginning_of_line? # => true

scanner.concat('x')
scanner.terminate
scanner.beginning_of_line? # => false

StringScanner#bol? is an alias for StringScanner#beginning_of_line?.

Returns:

  • (Boolean)


1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
# File 'strscan.c', line 1480

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

:markup: markdown :include: strscan/link_refs.txt

call-seq:

captures -> substring_array or nil

Returns the array of [captured match values] at indexes ‘(1..)` if the most recent match attempt succeeded, or `nil` otherwise:

“‘rb scanner = StringScanner.new(’Fri Dec 12 1975 14:39’) scanner.captures # => nil

scanner.exist?(/(?<wday>w+) (?<month>w+) (?<day>d+) /) scanner.captures # => [“Fri”, “Dec”, “12”] scanner.values_at(*0..4) # => [“Fri Dec 12 ”, “Fri”, “Dec”, “12”, nil]

scanner.exist?(/Fri/) scanner.captures # => []

scanner.scan(/nope/) scanner.captures # => nil “‘



1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
# File 'strscan.c', line 1843

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;
        if (p->regs.beg[i] == -1)
            str = Qnil;
        else
            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

:markup: markdown :include: strscan/link_refs.txt :include: strscan/methods/get_charpos.md



531
532
533
534
535
536
537
538
539
# File 'strscan.c', line 531

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(re) ⇒ Object

:markup: markdown :include: strscan/link_refs.txt

call-seq:

check(pattern) -> matched_substring or nil

Attempts to [match] the given ‘pattern` at the beginning of the [target substring]; does not modify the [positions].

If the match succeeds:

  • Returns the matched substring.

  • Sets all [match values].

“‘rb scanner = StringScanner.new(’foobarbaz’) scanner.pos = 3 scanner.check(‘bar’) # => “bar” put_match_values(scanner) # Basic match values: # matched?: true # matched_size: 3 # pre_match: “foo” # matched : “bar” # post_match: “baz” # Captured match values: # size: 1 # captures: [] # named_captures: {} # values_at: [“bar”, nil] # []: # [0]: “bar” # [1]: nil # => 0..1 put_situation(scanner) # Situation: # pos: 3 # charpos: 3 # rest: “barbaz” # rest_size: 6 “‘

If the match fails:

  • Returns ‘nil`.

  • Clears all [match values].

“‘rb scanner.check(/nope/) # => nil match_values_cleared?(scanner) # => true “`



903
904
905
906
907
# File 'strscan.c', line 903

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

#check_until(re) ⇒ Object

:markup: markdown :include: strscan/link_refs.txt

call-seq:

check_until(pattern) -> substring or nil

Attempts to [match] the given ‘pattern` anywhere (at any [position]) in the [target substring]; does not modify the [positions].

If the match succeeds:

  • Sets all [match values].

  • Returns the matched substring, which extends from the current [position] to the end of the matched substring.

“‘rb scanner = StringScanner.new(’foobarbazbatbam’) scanner.pos = 6 scanner.check_until(/bat/) # => “bazbat” put_match_values(scanner) # Basic match values: # matched?: true # matched_size: 3 # pre_match: “foobarbaz” # matched : “bat” # post_match: “bam” # Captured match values: # size: 1 # captures: [] # named_captures: {} # values_at: [“bat”, nil] # []: # [0]: “bat” # [1]: nil put_situation(scanner) # Situation: # pos: 6 # charpos: 6 # rest: “bazbatbam” # rest_size: 9 “‘

If the match fails:

  • Clears all [match values].

  • Returns ‘nil`.

“‘rb scanner.check_until(/nope/) # => nil match_values_cleared?(scanner) # => true “`



1076
1077
1078
1079
1080
# File 'strscan.c', line 1076

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

#clearObject

:nodoc:



392
393
394
395
396
397
# File 'strscan.c', line 392

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

#concat(str) ⇒ Object

:markup: markdown :include: strscan/link_refs.txt

call-seq:

concat(more_string) -> self
  • Appends the given ‘more_string` to the [stored string].

  • Returns ‘self`.

  • Does not affect the [positions] or [match values].

“‘rb scanner = StringScanner.new(’foo’) scanner.string # => “foo” scanner.terminate scanner.concat(‘barbaz’) # => #<StringScanner 3/9 “foo” @ “barba…”> scanner.string # => “foobarbaz” put_situation(scanner) # Situation: # pos: 3 # charpos: 3 # rest: “barbaz” # rest_size: 6 “‘



501
502
503
504
505
506
507
508
509
510
# File 'strscan.c', line 501

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

:nodoc:

Returns:

  • (Boolean)


1529
1530
1531
1532
1533
1534
# File 'strscan.c', line 1529

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

#eos?Boolean

:markup: markdown :include: strscan/link_refs.txt

call-seq:

eos? -> true or false

Returns whether the [position] is at the end of the [stored string]:

“‘rb scanner = StringScanner.new(’foobarbaz’) scanner.eos? # => false pos = 3 scanner.eos? # => false scanner.terminate scanner.eos? # => true “‘

Returns:

  • (Boolean)


1511
1512
1513
1514
1515
1516
1517
1518
# File 'strscan.c', line 1511

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

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

#exist?(re) ⇒ Boolean

:markup: markdown :include: strscan/link_refs.txt

call-seq:

exist?(pattern) -> byte_offset or nil

Attempts to [match] the given ‘pattern` anywhere (at any [position]) n the [target substring]; does not modify the [positions].

If the match succeeds:

  • Returns a byte offset: the distance in bytes between the current [position] and the end of the matched substring.

  • Sets all [match values].

“‘rb scanner = StringScanner.new(’foobarbazbatbam’) scanner.pos = 6 scanner.exist?(/bat/) # => 6 put_match_values(scanner) # Basic match values: # matched?: true # matched_size: 3 # pre_match: “foobarbaz” # matched : “bat” # post_match: “bam” # Captured match values: # size: 1 # captures: [] # named_captures: {} # values_at: [“bat”, nil] # []: # [0]: “bat” # [1]: nil put_situation(scanner) # Situation: # pos: 6 # charpos: 6 # rest: “bazbatbam” # rest_size: 9 “‘

If the match fails:

  • Returns ‘nil`.

  • Clears all [match values].

“‘rb scanner.exist?(/nope/) # => nil match_values_cleared?(scanner) # => true “`

Returns:

  • (Boolean)


1002
1003
1004
1005
1006
# File 'strscan.c', line 1002

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

#fixed_anchor?Boolean

:markup: markdown :include: strscan/link_refs.txt

call-seq:

fixed_anchor? -> true or false

Returns whether the [fixed-anchor property] is set.

Returns:

  • (Boolean)


2183
2184
2185
2186
2187
2188
2189
# File 'strscan.c', line 2183

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

#get_byteObject

:markup: markdown :include: strscan/link_refs.txt :include: strscan/methods/get_byte.md



1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
# File 'strscan.c', line 1197

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

:nodoc:



1225
1226
1227
1228
1229
1230
# File 'strscan.c', line 1225

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

#getchObject

:markup: markdown :include: strscan/link_refs.txt :include: strscan/methods/getch.md



1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
# File 'strscan.c', line 1124

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

:markup: markdown :include: strscan/link_refs.txt

call-seq:

inspect -> string

Returns a string representation of ‘self` that may show:

  1. The current [position].

  2. The size (in bytes) of the [stored string].

  3. The substring preceding the current position.

  4. The substring following the current position (which is also the [target substring]).

“‘rb scanner = StringScanner.new(“Fri Dec 12 1975 14:39”) scanner.pos = 11 scanner.inspect # => “#<StringScanner 11/21 "…c 12 " @ "1975 …">” “`

If at beginning-of-string, item 4 above (following substring) is omitted:

“‘rb scanner.reset scanner.inspect # => “#<StringScanner 0/21 @ "Fri D…">” “`

If at end-of-string, all items above are omitted:

“‘rb scanner.terminate scanner.inspect # => “#<StringScanner fin>” “`



2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
# File 'strscan.c', line 2105

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?(re) ⇒ Boolean

:markup: markdown :include: strscan/link_refs.txt

call-seq:

match?(pattern) -> updated_position or nil

Attempts to [match] the given ‘pattern` at the beginning of the [target substring]; does not modify the [positions].

If the match succeeds:

  • Sets [match values].

  • Returns the size in bytes of the matched substring.

“‘rb scanner = StringScanner.new(’foobarbaz’) scanner.pos = 3 scanner.match?(/bar/) => 3 put_match_values(scanner) # Basic match values: # matched?: true # matched_size: 3 # pre_match: “foo” # matched : “bar” # post_match: “baz” # Captured match values: # size: 1 # captures: [] # named_captures: {} # values_at: [“bar”, nil] # []: # [0]: “bar” # [1]: nil put_situation(scanner) # Situation: # pos: 3 # charpos: 3 # rest: “barbaz” # rest_size: 6 “‘

If the match fails:

  • Clears match values.

  • Returns ‘nil`.

  • Does not increment positions.

“‘rb scanner.match?(/nope/) # => nil match_values_cleared?(scanner) # => true “`

Returns:

  • (Boolean)


831
832
833
834
835
# File 'strscan.c', line 831

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

#matchedObject

:markup: markdown :include: strscan/link_refs.txt

call-seq:

matched -> matched_substring or nil

Returns the matched substring from the most recent [match] attempt if it was successful, or ‘nil` otherwise; see [Basic Matched Values]:

“‘rb scanner = StringScanner.new(’foobarbaz’) scanner.matched # => nil scanner.pos = 3 scanner.match?(/bar/) # => 3 scanner.matched # => “bar” scanner.match?(/nope/) # => nil scanner.matched # => nil “‘



1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
# File 'strscan.c', line 1613

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

:markup: markdown :include: strscan/link_refs.txt

call-seq:

matched? -> true or false

Returns ‘true` of the most recent [match attempt] was successful, `false` otherwise; see [Basic Matched Values]:

“‘rb scanner = StringScanner.new(’foobarbaz’) scanner.matched? # => false scanner.pos = 3 scanner.exist?(/baz/) # => 6 scanner.matched? # => true scanner.exist?(/nope/) # => nil scanner.matched? # => false “‘

Returns:

  • (Boolean)


1581
1582
1583
1584
1585
1586
1587
1588
# File 'strscan.c', line 1581

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

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

#matched_sizeObject

:markup: markdown :include: strscan/link_refs.txt

call-seq:

matched_size -> substring_size or nil

Returns the size (in bytes) of the matched substring from the most recent match [match attempt] if it was successful, or ‘nil` otherwise; see [Basic Matched Values]:

“‘rb scanner = StringScanner.new(’foobarbaz’) scanner.matched_size # => nil

pos = 3 scanner.exist?(/baz/) # => 9 scanner.matched_size # => 3

scanner.exist?(/nope/) # => nil scanner.matched_size # => nil “‘



1650
1651
1652
1653
1654
1655
1656
1657
1658
# File 'strscan.c', line 1650

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_capturesObject

:markup: markdown :include: strscan/link_refs.txt

call-seq:

named_captures -> hash

Returns the array of captured match values at indexes (1..) if the most recent match attempt succeeded, or nil otherwise; see [Captured Match Values]:

“‘rb scanner = StringScanner.new(’Fri Dec 12 1975 14:39’) scanner.named_captures # => {}

pattern = /(?<wday>w+) (?<month>w+) (?<day>d+) / scanner.match?(pattern) scanner.named_captures # => “month”=>“Dec”, “day”=>“12”

scanner.string = ‘nope’ scanner.match?(pattern) scanner.named_captures # => “month”=>nil, “day”=>nil

scanner.match?(/nosuch/) scanner.named_captures # => {} “‘



2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
# File 'strscan.c', line 2244

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

    return data.captures;
}

#peek(vlen) ⇒ Object

:markup: markdown :include: strscan/link_refs.txt

call-seq:

peek(length) -> substring

Returns the substring ‘string[pos, length]`; does not update [match values] or [positions]:

“‘rb scanner = StringScanner.new(’foobarbaz’) scanner.pos = 3 scanner.peek(3) # => “bar” scanner.terminate scanner.peek(3) # => “” “‘



1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
# File 'strscan.c', line 1251

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

#peek_byteObject

Peeks at the current byte and returns it as an integer.

s = StringScanner.new('ab')
s.peek_byte         # => 97


1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
# File 'strscan.c', line 1180

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

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

    return INT2FIX((unsigned char)*CURPTR(p));
}

#peep(vlen) ⇒ Object

:nodoc:



1276
1277
1278
1279
1280
1281
# File 'strscan.c', line 1276

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

#pointerObject

:markup: markdown :include: strscan/link_refs.txt :include: strscan/methods/get_pos.md



517
518
519
520
521
522
523
524
# File 'strscan.c', line 517

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

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

#pointer=(v) ⇒ Object

:markup: markdown :include: strscan/link_refs.txt :include: strscan/methods/set_pos.md



546
547
548
549
550
551
552
553
554
555
556
557
558
559
# File 'strscan.c', line 546

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

:markup: markdown :include: strscan/link_refs.txt :include: strscan/methods/get_pos.md



517
518
519
520
521
522
523
524
# File 'strscan.c', line 517

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

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

#pos=(v) ⇒ Object

:markup: markdown :include: strscan/link_refs.txt :include: strscan/methods/set_pos.md



546
547
548
549
550
551
552
553
554
555
556
557
558
559
# File 'strscan.c', line 546

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

:markup: markdown :include: strscan/link_refs.txt

call-seq:

post_match -> substring

Returns the substring that follows the matched substring from the most recent match attempt if it was successful, or ‘nil` otherwise; see [Basic Match Values]:

“‘rb scanner = StringScanner.new(’foobarbaz’) scanner.post_match # => nil

scanner.pos = 3 scanner.match?(/bar/) # => 3 scanner.post_match # => “baz”

scanner.match?(/nope/) # => nil scanner.post_match # => nil “‘



1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
# File 'strscan.c', line 1972

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

:markup: markdown :include: strscan/link_refs.txt

call-seq:

pre_match -> substring

Returns the substring that precedes the matched substring from the most recent match attempt if it was successful, or ‘nil` otherwise; see [Basic Match Values]:

“‘rb scanner = StringScanner.new(’foobarbaz’) scanner.pre_match # => nil

scanner.pos = 3 scanner.exist?(/baz/) # => 6 scanner.pre_match # => “foobar” # Substring of entire string, not just target string.

scanner.exist?(/nope/) # => nil scanner.pre_match # => nil “‘



1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
# File 'strscan.c', line 1935

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

:markup: markdown :include: strscan/link_refs.txt

call-seq:

reset -> self

Sets both [byte position] and [character position] to zero, and clears [match values]; returns self:

“‘rb scanner = StringScanner.new(’foobarbaz’) scanner.exist?(/bar/) # => 6 scanner.reset # => #<StringScanner 0/9 @ “fooba…”> put_situation(scanner) # Situation: # pos: 0 # charpos: 0 # rest: “foobarbaz” # rest_size: 9 # => nil match_values_cleared?(scanner) # => true “‘



357
358
359
360
361
362
363
364
365
366
# File 'strscan.c', line 357

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

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

#restObject

:markup: markdown :include: strscan/link_refs.txt

call-seq:

rest -> target_substring

Returns the ‘rest’ of the [stored string] (all after the current [position]), which is the [target substring]:

“‘rb scanner = StringScanner.new(’foobarbaz’) scanner.rest # => “foobarbaz” scanner.pos = 3 scanner.rest # => “barbaz” scanner.terminate scanner.rest # => “” “‘



2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
# File 'strscan.c', line 2004

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

:nodoc:

Returns:

  • (Boolean)


1550
1551
1552
1553
1554
1555
1556
1557
# File 'strscan.c', line 1550

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

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

#rest_sizeObject

:markup: markdown :include: strscan/link_refs.txt

call-seq:

rest_size -> integer

Returns the size (in bytes) of the #rest of the [stored string]:

“‘rb scanner = StringScanner.new(’foobarbaz’) scanner.rest # => “foobarbaz” scanner.rest_size # => 9 scanner.pos = 3 scanner.rest # => “barbaz” scanner.rest_size # => 6 scanner.terminate scanner.rest # => “” scanner.rest_size # => 0 “‘



2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
# File 'strscan.c', line 2038

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

:nodoc:



2061
2062
2063
2064
2065
2066
# File 'strscan.c', line 2061

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

#scan(re) ⇒ Object

:markup: markdown :include: strscan/link_refs.txt :include: strscan/methods/scan.md



769
770
771
772
773
# File 'strscan.c', line 769

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

#scan_byteObject

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



1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
# File 'strscan.c', line 1155

static VALUE
strscan_scan_byte(VALUE self)
{
    struct strscanner *p;
    VALUE byte;

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

    byte = INT2FIX((unsigned char)*CURPTR(p));
    p->prev = p->curr;
    p->curr++;
    MATCHED(p);
    adjust_registers_to_matched(p);
    return byte;
}

#scan_full(re, s, f) ⇒ Object

:nodoc:



928
929
930
931
932
# File 'strscan.c', line 928

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_integer(base: 10) ⇒ Object

call-seq:

scan_integer(base: 10)

If ‘base` isn’t provided or is ‘10`, then it is equivalent to calling `#scan` with a `[+-]?d+` pattern, and returns an Integer or nil.

If ‘base` is `16`, then it is equivalent to calling `#scan` with a `[+-]?(0x)?+` pattern, and returns an Integer or nil.

The scanned string must be encoded with an ASCII compatible encoding, otherwise Encoding::CompatibilityError will be raised.



15
16
17
18
19
20
21
22
23
24
# File 'lib/strscan/strscan.rb', line 15

def scan_integer(base: 10)
  case base
  when 10
    scan_base10_integer
  when 16
    scan_base16_integer
  else
    raise ArgumentError, "Unsupported integer base: #{base.inspect}, expected 10 or 16"
  end
end

#scan_until(re) ⇒ Object

:markup: markdown :include: strscan/link_refs.txt :include: strscan/methods/scan_until.md



939
940
941
942
943
# File 'strscan.c', line 939

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

#search_full(re, s, f) ⇒ Object

:nodoc:



1101
1102
1103
1104
1105
# File 'strscan.c', line 1101

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

:markup: markdown :include: strscan/link_refs.txt

call-seq:

size -> captures_count

Returns the count of captures if the most recent match attempt succeeded, ‘nil` otherwise; see [Captures Match Values]:

“‘rb scanner = StringScanner.new(’Fri Dec 12 1975 14:39’) scanner.size # => nil

pattern = /(?<wday>w+) (?<month>w+) (?<day>d+) / scanner.match?(pattern) scanner.values_at(*0..scanner.size) # => [“Fri Dec 12 ”, “Fri”, “Dec”, “12”, nil] scanner.size # => 4

scanner.match?(/nope/) # => nil scanner.size # => nil “‘



1807
1808
1809
1810
1811
1812
1813
1814
1815
# File 'strscan.c', line 1807

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(re) ⇒ Object

:markup: markdown :include: strscan/link_refs.txt :include: strscan/methods/skip.md



842
843
844
845
846
# File 'strscan.c', line 842

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

#skip_until(re) ⇒ Object

:markup: markdown :include: strscan/link_refs.txt :include: strscan/methods/skip_until.md



1013
1014
1015
1016
1017
# File 'strscan.c', line 1013

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

#stringObject

:markup: markdown :include: strscan/link_refs.txt

call-seq:

string -> stored_string

Returns the [stored string]:

“‘rb scanner = StringScanner.new(’foobar’) scanner.string # => “foobar” scanner.concat(‘baz’) scanner.string # => “foobarbaz” “‘



416
417
418
419
420
421
422
423
# File 'strscan.c', line 416

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

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

#string=(str) ⇒ Object

:markup: markdown :include: strscan/link_refs.txt

call-seq:

string = other_string -> other_string

Replaces the [stored string] with the given ‘other_string`:

“‘rb scanner = StringScanner.new(’foobar’) scanner.scan(/foo/) put_situation(scanner) # Situation: # pos: 3 # charpos: 3 # rest: “bar” # rest_size: 3 match_values_cleared?(scanner) # => false

scanner.string = ‘baz’ # => “baz” put_situation(scanner) # Situation: # pos: 0 # charpos: 0 # rest: “baz” # rest_size: 3 match_values_cleared?(scanner) # => true “‘



460
461
462
463
464
465
466
467
468
469
470
# File 'strscan.c', line 460

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

:markup: markdown :include: strscan/link_refs.txt :include: strscan/methods/terminate.md



373
374
375
376
377
378
379
380
381
382
# File 'strscan.c', line 373

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

:markup: markdown :include: strscan/link_refs.txt

call-seq:

unscan -> self

Sets the [position] to its value previous to the recent successful

match][17

attempt:

“‘rb scanner = StringScanner.new(’foobarbaz’) scanner.scan(/foo/) put_situation(scanner) # Situation: # pos: 3 # charpos: 3 # rest: “barbaz” # rest_size: 6 scanner.unscan # => #<StringScanner 0/9 @ “fooba…”> put_situation(scanner) # Situation: # pos: 0 # charpos: 0 # rest: “foobarbaz” # rest_size: 9 “‘

Raises an exception if match values are clear:

“‘rb scanner.scan(/nope/) # => nil match_values_cleared?(scanner) # => true scanner.unscan # Raises StringScanner::Error. “`



1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
# File 'strscan.c', line 1434

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(*args) ⇒ Object

:markup: markdown :include: strscan/link_refs.txt

call-seq:

values_at(*specifiers) -> array_of_captures or nil

Returns an array of captured substrings, or ‘nil` of none.

For each ‘specifier`, the returned substring is `[specifier]`; see #[].

“‘rb scanner = StringScanner.new(’Fri Dec 12 1975 14:39’) pattern = /(?<wday>w+) (?<month>w+) (?<day>d+) / scanner.match?(pattern) scanner.values_at(*0..3) # => [“Fri Dec 12 ”, “Fri”, “Dec”, “12”] scanner.values_at(*%i[wday month day]) # => [“Fri”, “Dec”, “12”] “‘



1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
# File 'strscan.c', line 1892

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