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:



332
333
334
335
336
# File 'ext/strscan/strscan.c', line 332

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



493
494
495
496
497
498
499
500
501
502
# File 'ext/strscan/strscan.c', line 493

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



1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
# File 'ext/strscan/strscan.c', line 1695

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)


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

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



1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
# File 'ext/strscan/strscan.c', line 1788

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



523
524
525
526
527
528
529
530
531
# File 'ext/strscan/strscan.c', line 523

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



896
897
898
899
900
# File 'ext/strscan/strscan.c', line 896

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



1069
1070
1071
1072
1073
# File 'ext/strscan/strscan.c', line 1069

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

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



493
494
495
496
497
498
499
500
501
502
# File 'ext/strscan/strscan.c', line 493

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

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


1476
1477
1478
1479
1480
1481
1482
1483
# File 'ext/strscan/strscan.c', line 1476

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)


995
996
997
998
999
# File 'ext/strscan/strscan.c', line 995

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)


2112
2113
2114
2115
2116
2117
2118
# File 'ext/strscan/strscan.c', line 2112

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



1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
# File 'ext/strscan/strscan.c', line 1190

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

#getchObject

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



1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
# File 'ext/strscan/strscan.c', line 1117

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



2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
# File 'ext/strscan/strscan.c', line 2034

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)


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

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



1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
# File 'ext/strscan/strscan.c', line 1561

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)


1529
1530
1531
1532
1533
1534
1535
1536
# File 'ext/strscan/strscan.c', line 1529

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



1598
1599
1600
1601
1602
1603
1604
1605
1606
# File 'ext/strscan/strscan.c', line 1598

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



2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
# File 'ext/strscan/strscan.c', line 2176

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



1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
# File 'ext/strscan/strscan.c', line 1228

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


1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
# File 'ext/strscan/strscan.c', line 1173

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

#pointerObject

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



509
510
511
512
513
514
515
516
# File 'ext/strscan/strscan.c', line 509

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



538
539
540
541
542
543
544
545
546
547
548
549
550
551
# File 'ext/strscan/strscan.c', line 538

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



509
510
511
512
513
514
515
516
# File 'ext/strscan/strscan.c', line 509

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



538
539
540
541
542
543
544
545
546
547
548
549
550
551
# File 'ext/strscan/strscan.c', line 538

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



1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
# File 'ext/strscan/strscan.c', line 1917

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



1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
# File 'ext/strscan/strscan.c', line 1880

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



364
365
366
367
368
369
370
371
372
373
# File 'ext/strscan/strscan.c', line 364

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



1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
# File 'ext/strscan/strscan.c', line 1949

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)


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

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



1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
# File 'ext/strscan/strscan.c', line 1983

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

#scan(re) ⇒ Object

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



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

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.



1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
# File 'ext/strscan/strscan.c', line 1148

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:



921
922
923
924
925
# File 'ext/strscan/strscan.c', line 921

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



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

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:



1094
1095
1096
1097
1098
# File 'ext/strscan/strscan.c', line 1094

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



1752
1753
1754
1755
1756
1757
1758
1759
1760
# File 'ext/strscan/strscan.c', line 1752

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



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

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



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

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



408
409
410
411
412
413
414
415
# File 'ext/strscan/strscan.c', line 408

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



452
453
454
455
456
457
458
459
460
461
462
# File 'ext/strscan/strscan.c', line 452

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

    StringValue(str);
    RB_OBJ_WRITE(self, &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



380
381
382
383
384
385
386
387
388
389
# File 'ext/strscan/strscan.c', line 380

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



1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
# File 'ext/strscan/strscan.c', line 1399

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



1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
# File 'ext/strscan/strscan.c', line 1837

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