123456789_123456789_123456789_123456789_123456789_

Class: StringScanner

Relationships & Source Files
Namespace Children
Exceptions:
Inherits: Object
Defined in: ext/strscan/strscan.c,
ext/strscan/strscan.c,
ext/strscan/lib/strscan/strscan.rb

Overview

:markup: markdown

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(string, fixed_anchor: false) ⇒ string_scanner (private)

:markup: markdown

Returns a new StringScanner object whose [stored string][1] is the given #string; sets the [fixed-anchor property][10]:

scanner = {StringScanner.new}('foobarbaz')
scanner.string        # => "foobarbaz"
scanner.fixed_anchor? # => false
put_situation(scanner)
==== Situation:
====   pos:       0
====   charpos:   0
====   rest:      "foobarbaz"
====   rest_size: 9
[ GitHub ]

  
# File 'ext/strscan/strscan.c', line 251

static VALUE
strscan_initialize(int argc, VALUE *argv, VALUE self)
{
    struct strscanner *p;
    VALUE str, options;

    p = check_strscan(self);
    rb_scan_args(argc, argv, "11", &str, &options);
    options = rb_check_hash_type(options);
    if (!NIL_P(options)) {
        VALUE fixed_anchor;
        ID keyword_ids[1];
        keyword_ids[0] = rb_intern("fixed_anchor");
        rb_get_kwargs(options, keyword_ids, 0, 1, &fixed_anchor);
        if (fixed_anchor == Qundef) {
            p->fixed_anchor_p = false;
        }
        else {
            p->fixed_anchor_p = RTEST(fixed_anchor);
        }
    }
    else {
        p->fixed_anchor_p = false;
    }
    StringValue(str);
    RB_OBJ_WRITE(self, &p->str, str);

    return self;
}

Class Method Details

.must_C_version

This method is for internal use only.
[ GitHub ]

  
# File 'ext/strscan/strscan.c', line 329

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

Instance Attribute Details

#beginning_of_line?Boolean (readonly)

:markup: markdown

Returns whether the [position][2] is at the beginning of a line; that is, at the beginning of the [stored string][1] 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 beginning_of_line?.

[ GitHub ]

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

#empty?Boolean (readonly)

This method is for internal use only.
[ GitHub ]

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

:markup: markdown

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

scanner = {StringScanner.new}('foobarbaz')
scanner.eos? # => false
pos = 3
scanner.eos? # => false
scanner.terminate
scanner.eos? # => true
[ GitHub ]

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

#fixed_anchor?Boolean (readonly)

:markup: markdown

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

[ GitHub ]

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

#matchedmatched_substring? (readonly)

:markup: markdown

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

scanner = {StringScanner.new}('foobarbaz')
scanner.matched        # => nil
scanner.pos = 3
scanner.match?(/bar/)  # => 3
scanner.matched        # => "bar"
scanner.match?(/nope/) # => nil
scanner.matched        # => nil
[ GitHub ]

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

:markup: markdown

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

scanner = {StringScanner.new}('foobarbaz')
scanner.matched?       # => false
scanner.pos = 3
scanner.exist?(/baz/)  # => 6
scanner.matched?       # => true
scanner.exist?(/nope/) # => nil
scanner.matched?       # => false
[ GitHub ]

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

#pointer (rw)

Alias for #pos.

#pos (rw) Also known as: #pointer

:markup: markdown

[ GitHub ]

  
# 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) (rw) Also known as: #pointer=

:markup: markdown

[ GitHub ]

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

#resttarget_substring (readonly)

:markup: markdown

Returns the 'rest' of the [stored string]1, which is the [target substring][3]:

scanner = {StringScanner.new}('foobarbaz')
scanner.rest # => "foobarbaz"
scanner.pos = 3
scanner.rest # => "barbaz"
scanner.terminate
scanner.rest # => ""
[ GitHub ]

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

This method is for internal use only.
[ GitHub ]

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

#stringstored_string (rw)

:markup: markdown

Returns the [stored string][1]:

scanner = {StringScanner.new}('foobar')
scanner.string # => "foobar"
scanner.concat('baz')
scanner.string # => "foobarbaz"
[ GitHub ]

  
# 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=(other_string) ⇒ other_string (rw)

:markup: markdown

Replaces the [stored string][1] with the given other_string:

  • Sets both [positions][11] to zero.
  • Clears [match values][9].
  • Returns other_string.
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
[ GitHub ]

  
# File 'ext/strscan/strscan.c', line 464

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

Instance Method Details

#<<(more_string) ⇒ self Also known as: #concat

:markup: markdown

  • Appends the given more_string to the [stored string][1].
  • Returns self.
  • Does not affect the [positions][11] or [match values][9].
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
[ GitHub ]

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

#[](specifier) ⇒ substring?

:markup: markdown

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

When there are captures:

scanner = {StringScanner.new}('Fri Dec 12 1975 14:39')
scanner.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)
  • specifier zero: returns the entire matched substring:

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

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

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

    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:

scanner = {StringScanner.new}('foobarbaz')
scanner.exist?(/bar/)
scanner[0] # => "bar"
scanner[1] # => nil

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

scanner.scan(/nope/) # => nil
scanner[0]           # => nil
scanner[1]           # => nil
[ GitHub ]

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

#capturessubstring_array?

:markup: markdown

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

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
[ GitHub ]

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

#charpos

:markup: markdown

[ GitHub ]

  
# 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(pattern) ⇒ matched_substring?

:markup: markdown

Attempts to [match][17] the given pattern at the beginning of the [target substring][3]; does not modify the [positions][11].

If the match succeeds:

  • Returns the matched substring.
  • Sets all [match values][9].
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][9].
scanner.check(/nope/)          # => nil
match_values_cleared?(scanner) # => true
[ GitHub ]

  
# 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(pattern) ⇒ substring?

:markup: markdown

Attempts to [match][17] the given pattern anywhere (at any [position][2]) in the [target substring][3]; does not modify the [positions][11].

If the match succeeds:

  • Sets all [match values][9].
  • Returns the matched substring, which extends from the current [position][2] to the end of the matched substring.
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][9].
  • Returns nil.
scanner.check_until(/nope/)    # => nil
match_values_cleared?(scanner) # => true
[ GitHub ]

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

#clear

This method is for internal use only.
[ GitHub ]

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

#<<(more_string) ⇒ self #concat(more_string) ⇒ self

Alias for #<<.

#exist?(pattern) ⇒ byte_offset?

:markup: markdown

Attempts to [match][17] the given pattern anywhere (at any [position][2]) n the [target substring][3]; does not modify the [positions][11].

If the match succeeds:

  • Returns a byte offset: the distance in bytes between the current [position][2] and the end of the matched substring.
  • Sets all [match values][9].
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][9].
scanner.exist?(/nope/)         # => nil
match_values_cleared?(scanner) # => true
[ GitHub ]

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

#get_byte

:markup: markdown

[ GitHub ]

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

#getbyte

This method is for internal use only.
[ GitHub ]

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

#getch

:markup: markdown

[ GitHub ]

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

#dupshallow_copy (private)

:markup: markdown

Returns a shallow copy of self; the [stored string][1] in the copy is the same string as in self.

[ GitHub ]

  
# File 'ext/strscan/strscan.c', line 297

static VALUE
strscan_init_copy(VALUE vself, VALUE vorig)
{
    struct strscanner *self, *orig;

    self = check_strscan(vself);
    orig = check_strscan(vorig);
    if (self != orig) {
	self->flags = orig->flags;
	RB_OBJ_WRITE(vself, &self->str, orig->str);
	self->prev = orig->prev;
	self->curr = orig->curr;
	if (rb_reg_region_copy(&self->regs, &orig->regs))
	    rb_memerror();
	RB_GC_GUARD(vorig);
    }

    return vself;
}

#inspectString

:markup: markdown

Returns a string representation of self that may show:

  1. The current [position][2].
  2. The size (in bytes) of the [stored string][1].
  3. The substring preceding the current position.
  4. The substring following the current position (which is also the [target substring][3]).
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:

scanner.reset
scanner.inspect # => "#<StringScanner 0/21 @ \"Fri D...\">"

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

scanner.terminate
scanner.inspect # => "#<StringScanner fin>"
[ GitHub ]

  
# 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?(pattern) ⇒ updated_position?

:markup: markdown

Attempts to [match][17] the given pattern at the beginning of the [target substring][3]; does not modify the [positions][11].

If the match succeeds:

  • Sets [match values][9].
  • Returns the size in bytes of the matched substring.
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.
scanner.match?(/nope/)         # => nil
match_values_cleared?(scanner) # => true
[ GitHub ]

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

#matched_sizesubstring_size?

:markup: markdown

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

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
[ GitHub ]

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

:markup: markdown

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

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 # => {"wday"=>"Fri", "month"=>"Dec", "day"=>"12"}

scanner.string = 'nope'
scanner.match?(pattern)
scanner.named_captures # => {"wday"=>nil, "month"=>nil, "day"=>nil}

scanner.match?(/nosuch/)
scanner.named_captures # => {}
[ GitHub ]

  
# 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(length) ⇒ substring

:markup: markdown

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

scanner = {StringScanner.new}('foobarbaz')
scanner.pos = 3
scanner.peek(3)   # => "bar"
scanner.terminate
scanner.peek(3)   # => ""
[ GitHub ]

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

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

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

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

This method is for internal use only.
[ GitHub ]

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

#post_matchsubstring

:markup: markdown

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][18]:

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
[ GitHub ]

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

:markup: markdown

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][18]:

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
[ GitHub ]

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

#resetself

:markup: markdown

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

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
[ GitHub ]

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

#rest_sizeInteger

:markup: markdown

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

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
[ GitHub ]

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

#restsize

This method is for internal use only.
[ GitHub ]

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

:markup: markdown

[ GitHub ]

  
# 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_base10_integer (private)

[ GitHub ]

  
# File 'ext/strscan/strscan.c', line 1325

static VALUE
strscan_scan_base10_integer(VALUE self)
{
    char *ptr;
    long len = 0;
    struct strscanner *p;

    GET_SCANNER(self, p);
    CLEAR_MATCH_STATUS(p);

    strscan_must_ascii_compat(p->str);

    ptr = CURPTR(p);

    long remaining_len = S_RESTLEN(p);

    if (remaining_len <= 0) {
        return Qnil;
    }

    if (ptr[len] == '-' || ptr[len] == '+') {
        len++;
    }

    if (!rb_isdigit(ptr[len])) {
        return Qnil;
    }

    p->prev = p->curr;

    while (len < remaining_len && rb_isdigit(ptr[len])) {
        len++;
    }

    return strscan_parse_integer(p, 10, len);
}

#scan_base16_integer (private)

[ GitHub ]

  
# File 'ext/strscan/strscan.c', line 1362

static VALUE
strscan_scan_base16_integer(VALUE self)
{
    char *ptr;
    long len = 0;
    struct strscanner *p;

    GET_SCANNER(self, p);
    CLEAR_MATCH_STATUS(p);

    strscan_must_ascii_compat(p->str);

    ptr = CURPTR(p);

    long remaining_len = S_RESTLEN(p);

    if (remaining_len <= 0) {
        return Qnil;
    }

    if (ptr[len] == '-' || ptr[len] == '+') {
        len++;
    }

    if ((remaining_len >= (len + 3)) && ptr[len] == '0' && ptr[len + 1] == 'x' && rb_isxdigit(ptr[len + 2])) {
        len += 2;
    }

    if (len >= remaining_len || !rb_isxdigit(ptr[len])) {
        return Qnil;
    }

    p->prev = p->curr;

    while (len < remaining_len && rb_isxdigit(ptr[len])) {
        len++;
    }

    return strscan_parse_integer(p, 16, len);
}

#scan_byteinteger_byte

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

[ GitHub ]

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

This method is for internal use only.
[ GitHub ]

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

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)?[0-9a-fA-F]+ pattern, and returns an Integer or nil.

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

[ GitHub ]

  
# File 'ext/strscan/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)

:markup: markdown

[ GitHub ]

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

This method is for internal use only.
[ GitHub ]

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

#sizecaptures_count

:markup: markdown

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

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
[ GitHub ]

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

:markup: markdown

[ GitHub ]

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

:markup: markdown

[ GitHub ]

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

#terminate

:markup: markdown

[ GitHub ]

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

#unscanself

:markup: markdown

Sets the [position][2] to its value previous to the recent successful [match][17] attempt:

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:

scanner.scan(/nope/)           # => nil
match_values_cleared?(scanner) # => true
scanner.unscan                 # Raises {StringScanner::Error}.
[ GitHub ]

  
# 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(*specifiers) ⇒ array_of_captures?

:markup: markdown

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

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

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"]
[ GitHub ]

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