Class: StringScanner

Inherits:
Object
  • Object
show all
Defined in:
ext/strscan/strscan.c,
lib/strscan/strscan.rb,
ext/strscan/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:



329
330
331
332
333
# File 'ext/strscan/strscan.c', line 329

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 “‘



505
506
507
508
509
510
511
512
513
514
# File 'ext/strscan/strscan.c', line 505

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 “`



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
1782
1783
1784
1785
# File 'ext/strscan/strscan.c', line 1754

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


1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
# File 'ext/strscan/strscan.c', line 1487

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 “‘



1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
# File 'ext/strscan/strscan.c', line 1847

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



535
536
537
538
539
540
541
542
543
# File 'ext/strscan/strscan.c', line 535

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 “`



908
909
910
911
912
# File 'ext/strscan/strscan.c', line 908

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 “`



1081
1082
1083
1084
1085
# File 'ext/strscan/strscan.c', line 1081

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

#clearObject

:nodoc:



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

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 “‘



505
506
507
508
509
510
511
512
513
514
# File 'ext/strscan/strscan.c', line 505

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)


1536
1537
1538
1539
1540
1541
# File 'ext/strscan/strscan.c', line 1536

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)


1518
1519
1520
1521
1522
1523
1524
1525
# File 'ext/strscan/strscan.c', line 1518

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)


1007
1008
1009
1010
1011
# File 'ext/strscan/strscan.c', line 1007

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)


2187
2188
2189
2190
2191
2192
2193
# File 'ext/strscan/strscan.c', line 2187

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



1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
# File 'ext/strscan/strscan.c', line 1202

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:



1230
1231
1232
1233
1234
1235
# File 'ext/strscan/strscan.c', line 1230

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



1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
# File 'ext/strscan/strscan.c', line 1129

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>” “`



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
2136
2137
2138
2139
# File 'ext/strscan/strscan.c', line 2109

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)


836
837
838
839
840
# File 'ext/strscan/strscan.c', line 836

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 “‘



1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
# File 'ext/strscan/strscan.c', line 1620

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)


1588
1589
1590
1591
1592
1593
1594
1595
# File 'ext/strscan/strscan.c', line 1588

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 “‘



1657
1658
1659
1660
1661
1662
1663
1664
1665
# File 'ext/strscan/strscan.c', line 1657

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 # => {} “‘



2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
# File 'ext/strscan/strscan.c', line 2251

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) # => “” “‘



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

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


1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
# File 'ext/strscan/strscan.c', line 1185

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:



1281
1282
1283
1284
1285
1286
# File 'ext/strscan/strscan.c', line 1281

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



521
522
523
524
525
526
527
528
# File 'ext/strscan/strscan.c', line 521

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

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

#pointer=(v) ⇒ Object

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



550
551
552
553
554
555
556
557
558
559
560
561
562
563
# File 'ext/strscan/strscan.c', line 550

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

    GET_SCANNER(self, p);
    i = NUM2LONG(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



521
522
523
524
525
526
527
528
# File 'ext/strscan/strscan.c', line 521

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

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

#pos=(v) ⇒ Object

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



550
551
552
553
554
555
556
557
558
559
560
561
562
563
# File 'ext/strscan/strscan.c', line 550

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

    GET_SCANNER(self, p);
    i = NUM2LONG(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 “‘



1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
# File 'ext/strscan/strscan.c', line 1976

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 “‘



1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
# File 'ext/strscan/strscan.c', line 1939

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 “‘



361
362
363
364
365
366
367
368
369
370
# File 'ext/strscan/strscan.c', line 361

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 # => “” “‘



2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
# File 'ext/strscan/strscan.c', line 2008

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)


1557
1558
1559
1560
1561
1562
1563
1564
# File 'ext/strscan/strscan.c', line 1557

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 “‘



2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
# File 'ext/strscan/strscan.c', line 2042

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:



2065
2066
2067
2068
2069
2070
# File 'ext/strscan/strscan.c', line 2065

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



774
775
776
777
778
# File 'ext/strscan/strscan.c', line 774

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.



1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
# File 'ext/strscan/strscan.c', line 1160

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:



933
934
935
936
937
# File 'ext/strscan/strscan.c', line 933

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



944
945
946
947
948
# File 'ext/strscan/strscan.c', line 944

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:



1106
1107
1108
1109
1110
# File 'ext/strscan/strscan.c', line 1106

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 “‘



1811
1812
1813
1814
1815
1816
1817
1818
1819
# File 'ext/strscan/strscan.c', line 1811

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



847
848
849
850
851
# File 'ext/strscan/strscan.c', line 847

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



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

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” “‘



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

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 “‘



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

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



377
378
379
380
381
382
383
384
385
386
# File 'ext/strscan/strscan.c', line 377

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. “`



1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
# File 'ext/strscan/strscan.c', line 1441

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”] “‘



1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
# File 'ext/strscan/strscan.c', line 1896

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