Spec-Zone.ru › Ruby 3.4

класс StringScanner

Родитель:
Объект

Класс StringScanner поддерживает обработку сохранённой строки как потока; этот код создаёт новый объект StringScanner с строкой 'foobarbaz':

require 'strscan'
scanner = StringScanner.new('foobarbaz')

О примерах

Все примеры здесь предполагают, что StringScanner был запрошен:

require 'strscan'

Некоторые примеры здесь предполагают, что эти константы определены:

MULTILINE_TEXT = <<~EOT
Go placidly amid the noise and haste,
and remember what peace there may be in silence.
EOT

HIRAGANA_TEXT = 'こんにちは'

ENGLISH_TEXT = 'Hello'

Некоторые примеры здесь предполагают, что определены некоторые вспомогательные методы:

  • put_situation(scanner): Отображает значения методов сканера pos, charpos, rest и rest_size.

  • put_match_values(scanner): Отображает значения совпадений сканера.

  • match_values_cleared?(scanner): Возвращает, очищены ли значения совпадений сканера.

См. примеры [здесь].

Объект StringScanner

Этот код создаёт объект StringScanner (назовём его просто сканером) и демонстрирует некоторые его базовые свойства:

scanner = StringScanner.new('foobarbaz')
scanner.string # => "foobarbaz"
put_situation(scanner)
# Situation:
#   pos:       0
#   charpos:   0
#   rest:      "foobarbaz"
#   rest_size: 9

Сканер имеет:

  • Сохранённую строку, которая:

    • Изначально устанавливается методом StringScanner.new(string) в заданную string ('foobarbaz' в примере выше).

    • Модифицируется методами string=(new_string) и concat(more_string).

    • Возвращается методом string.

    Подробнее см. Сохранённую строку ниже.

  • Позицию; индекс с нуля в байтах сохранённой строки (не в её символах):

    • Изначально устанавливается методом StringScanner.new в 0.

    • Возвращается методом pos.

    • Модифицируется явно методами reset, terminate и pos=(new_pos).

    • Модифицируется неявно (различными методами перемещения и другими).

    Подробнее см. Позицию байта ниже.

  • Целевой подстроку, которая является подстрокой сохранённой строки; она простирается от текущей позиции до конца сохранённой строки:

    • Изначально устанавливается методом StringScanner.new(string) в заданную string ('foobarbaz' в примере выше).

    • Возвращается методом rest.

    • Модифицируется любыми изменениями либо сохранённой строки, либо позиции.

    Самое важное: методы поиска и перемещения работают с целевой подстрокой, которая может быть (и часто является) меньше всей сохранённой строки.

    Подробнее см. Целевую подстроку ниже.

Сохранённая строка

Сохранённая строка — это строка, сохранённая в объекте StringScanner.

Каждый из этих методов устанавливает, изменяет или возвращает сохранённую строку:

Method Эффект
::new(string) Создаёт новый сканер для данной строки.
string=(new_string) Заменяет существующую сохранённую строку.
concat(more_string) Добавляет строку к существующей сохранённой строке.
string Возвращает сохранённую строку.

Позиции

Объект StringScanner поддерживает нулевую байтовую позицию и нулевую символическую позицию.

Каждый из этих методов явно устанавливает позиции:

Method Эффект
reset Устанавливает обе позиции в ноль (начало сохранённой строки).
terminate Устанавливает обе позиции в конец сохранённой строки.
pos=(new_byte_position) Устанавливает байтовую позицию; корректирует позицию символа.

Байтовая позиция (Позиция)

Байтовая позиция (или просто позиция) — это нулевой индекс в байтах сохранённой строки сканера; для нового объекта StringScanner байтовая позиция равна нулю.

Когда байтовая позиция:

  • Ноль (в начале), целевая подстрока — это вся сохранённая строка.

  • Равна размеру сохранённой строки (в конце), целевая подстрока — это пустая строка ''.

Для получения или установки байтовой позиции:

  • pos: возвращает байтовую позицию.

  • pos=(new_pos): устанавливает байтовую позицию.

Многие методы используют байтовую позицию в качестве основы для поиска совпадений; многие другие устанавливают, увеличивают или уменьшают байтовую позицию:

scanner = StringScanner.new('foobar')
scanner.pos # => 0
scanner.scan(/foo/) # => "foo" # Match found.
scanner.pos         # => 3     # Byte position incremented.
scanner.scan(/foo/) # => nil   # Match not found.
scanner.pos # => 3             # Byte position not changed.

Некоторые методы неявно изменяют байтовую позицию; см.:

  • Установка целевой подстроки.

  • Перемещение по целевой подстроке.

Значения этих методов выводятся непосредственно из значений pos и string:

  • charpos: позиция символа.

  • rest: целевая подстрока.

  • rest_size: rest.size.

Позиция символа

Позиция символа — это нулевой индекс в символах сохранённой строки; для нового объекта StringScanner позиция символа равна нулю.

Метод charpos возвращает позицию символа; её значение нельзя явно сбросить.

Некоторые методы изменяют (увеличивают или сбрасывают) позицию символа; см.:

  • Установка целевой подстроки.

  • Перемещение по целевой подстроке.

Пример (строка включает многобайтовые символы):

scanner = StringScanner.new(ENGLISH_TEXT) # Five 1-byte characters.
scanner.concat(HIRAGANA_TEXT)             # Five 3-byte characters
scanner.string # => "Helloこんにちは"       # Twenty bytes in all.
put_situation(scanner)
# Situation:
#   pos:       0
#   charpos:   0
#   rest:      "Helloこんにちは"
#   rest_size: 20
scanner.scan(/Hello/) # => "Hello" # Five 1-byte characters.
put_situation(scanner)
# Situation:
#   pos:       5
#   charpos:   5
#   rest:      "こんにちは"
#   rest_size: 15
scanner.getch         # => "こ"    # One 3-byte character.
put_situation(scanner)
# Situation:
#   pos:       8
#   charpos:   6
#   rest:      "んにちは"
#   rest_size: 12

Целевая подстрока

Целевая подстрока — это часть сохранённой строки, которая простирается от текущей байтовой позиции до конца сохранённой строки; она всегда либо:

  • Вся сохранённая строка (байтовая позиция — ноль).

  • Конечная подстрока сохранённой строки (байтовая позиция положительна).

Целевая подстрока возвращается методом rest, а её размер возвращается методом rest_size.

Примеры:

scanner = StringScanner.new('foobarbaz')
put_situation(scanner)
# Situation:
#   pos:       0
#   charpos:   0
#   rest:      "foobarbaz"
#   rest_size: 9
scanner.pos = 3
put_situation(scanner)
# Situation:
#   pos:       3
#   charpos:   3
#   rest:      "barbaz"
#   rest_size: 6
scanner.pos = 9
put_situation(scanner)
# Situation:
#   pos:       9
#   charpos:   9
#   rest:      ""
#   rest_size: 0

Установка целевой подстроки

Целевая подстрока устанавливается всякий раз, когда:

  • Сохранённая строка устанавливается (позиция сбрасывается в ноль; целевая подстрока устанавливается в сохранённую строку).

  • Байтовая позиция устанавливается (целевая подстрока корректируется соответственно).

Запрос целевой подстроки

Эта таблица обобщает (подробности и примеры см. по ссылкам):

Method Возвращает
rest Целевая подстрока.
rest_size Размер (в байтах) целевой подстроки.

Поиск в целевой подстроке

Метод поиска проверяет целевую подстроку, но не перемещает позиции или (по умолчанию) не сокращает целевую подстроку.

Эта таблица обобщает (подробности и примеры см. по ссылкам):

Method Возвращает Устанавливает значения соответствия?
check(pattern) Совпавший начальный подстрока или nil. Да.
check_until(pattern) Совпавшая подстрока (в любом месте) или nil. Да.
exist?(pattern) Индекс конца совпавшей подстроки (в любом месте). Да.
match?(pattern) Размер совпавшей начальной подстроки или nil. Да.
peek(size) Начальная подстрока заданной длины (байты). Нет.
peek_byte Integer ведущий байт или nil. Нет.
rest Целевая подстрока (с позиции байта до конца). Нет.

Перемещение по целевой подстроке

Метод перемещения проверяет целевую подстроку и, если успешно:

  • Перемещает позиции.

  • Укорачивает целевую подстроку.

В этой таблице обобщены (подробности и примеры по ссылкам):

Method Возвращает Устанавливает значения соответствия?
get_byte Ведущая байт или nil. Нет.
getch Ведущая символ или nil. Нет.
scan(pattern) Совпавший начальный подстрока или nil. Да.
scan_byte Integer ведущий байт или nil. Нет.
scan_until(pattern) Совпавшая подстрока (в любом месте) или nil. Да.
skip(pattern) Размер совпавшей начальной подстроки или nil. Да.
skip_until(pattern) Разница позиций до конца совпавшей подстроки или nil. Да.
unscan self. Нет.

Запросы к сканеру

Каждый из этих методов запрашивает объект сканера без его изменения (подробности и примеры по ссылкам)

Method Возвращает
beginning_of_line? true или false.
charpos Позиция символа.
eos? true или false.
fixed_anchor? true или false.
inspect String представление self.
pos Позиция байта.
rest Целевая подстрока.
rest_size Размер целевой подстроки.
string Хранимый строка.

Сопоставление

StringScanner реализует сопоставление шаблонов через Ruby класс Regexp, и его поведение сопоставления такое же, как у Ruby, за исключением свойства фиксированного якоря.

Методы сопоставления

Каждый метод сопоставления принимает один аргумент pattern, и пытается найти совпадающую подстроку в целевой подстроке.

Method Тип шаблона Сопоставляет с целевой подстрокой Возвращаемое значение при успехе Может обновлять позиции?
check Regexp или String. В начале. Совпавшая подстрока. Нет.
check_until Regexp или String. В любом месте. Подстрока. Нет.
match? Regexp или String. В начале. Размер соответствия. Нет.
exist? Regexp или String. В любом месте. Размер подстроки. Нет.
scan Regexp или String. В начале. Совпавшая подстрока. Да.
scan_until Regexp или String. В любом месте. Подстрока. Да.
skip Regexp или String. В начале. Размер соответствия. Да.
skip_until Regexp или String. В любом месте. Размер подстроки. Да.


Выбор метода сопоставления зависит от:

  • Где вы хотите найти совпадение:

    • Только в начале целевой подстроки: check, match?, scan, skip.

    • В любом месте целевой подстроки: check_until, exist?, scan_until, skip_until.

  • Нужно ли:

    • Перемещаться, изменяя позиции: scan, scan_until, skip, skip_until.

    • Сохранить позиции неизменными: check, check_until, match?, exist?.

  • Что вы хотите получить в качестве возвращаемого значения:

    • Совпавшую подстроку: check, scan.

    • Подстроку: check_until, scan_until.

    • Размер совпадения: match?, skip.

    • Размер подстроки: exist?, skip_until.

Значения соответствия

Значения соответствия в объекте StringScanner обычно содержат результаты последнего проведенного сопоставления.

Каждое значение соответствия можно рассматривать как:

  • Пустое: Изначально или после неудачной попытки сопоставления: обычно false, nil, или {}.

  • Заполненное: После успешной попытки сопоставления: true, строка, массив или хэш.

Каждый из этих методов очищает значения соответствия:

  • ::new(string).

  • reset.

  • terminate.

Каждый из этих методов пытается сопоставить шаблон и либо устанавливает значения соответствия (если успешно), либо очищает их (если нет):

  • check(pattern)

  • check_until(pattern)

  • exist?(pattern)

  • match?(pattern)

  • scan(pattern)

  • scan_until(pattern)

  • skip(pattern)

  • skip_until(pattern)

Основные значения соответствия

Основные значения соответствия — это те, которые не связаны с захватом.

Каждый из этих методов возвращает основное значение соответствия:

Method Возвращаемое значение после совпадения Возвращаемое значение после отсутствия совпадения
matched? true. false.
matched_size Размер совпавшей подстроки. nil.
matched Совпавшая подстрока. nil.
pre_match Подстрока, предшествующая совпавшей подстроке. nil.
post_match Подстрока, следующая за совпавшей подстрокой. nil.


См. примеры ниже.

Значения захваченных совпадений

Значения захваченных совпадений относятся к группировкам.

Каждый из этих методов возвращает значение захваченного совпадения:

Method Возвращаемое значение после совпадения Возвращаемое значение после отсутствия совпадения
size Количество захваченных подстрок. nil.
[](n) n-я захваченная подстрока. nil.
captures Array всех захваченных подстрок. nil.
values_at(*n) Array указанных захваченных подстрок. nil.
named_captures Hash именованных захватов. {}.


См. примеры ниже.

Примеры значений совпадений

Успешная попытка базового совпадения (без захватов):

scanner = StringScanner.new('foobarbaz')
scanner.exist?(/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

Неуспешная попытка базового совпадения (без захватов);

scanner = StringScanner.new('foobarbaz')
scanner.exist?(/nope/)
match_values_cleared?(scanner) # => true

Успешная попытка совпадения с незаданными захватами:

scanner = StringScanner.new('foobarbazbatbam')
scanner.exist?(/(foo)bar(baz)bat(bam)/)
put_match_values(scanner)
# Basic match values:
#   matched?:       true
#   matched_size:   15
#   pre_match:      ""
#   matched  :      "foobarbazbatbam"
#   post_match:     ""
# Captured match values:
#   size:           4
#   captures:       ["foo", "baz", "bam"]
#   named_captures: {}
#   values_at:      ["foobarbazbatbam", "foo", "baz", "bam", nil]
#   []:
#     [0]:          "foobarbazbatbam"
#     [1]:          "foo"
#     [2]:          "baz"
#     [3]:          "bam"
#     [4]:          nil

Успешная попытка совпадения с именованными захватами; то же, что и выше, но с named_captures:

scanner = StringScanner.new('foobarbazbatbam')
scanner.exist?(/(?<x>foo)bar(?<y>baz)bat(?<z>bam)/)
scanner.named_captures # => {"x"=>"foo", "y"=>"baz", "z"=>"bam"}

Неуспешная попытка совпадения с незаданными захватами:

scanner = StringScanner.new('somestring')
scanner.exist?(/(foo)bar(baz)bat(bam)/)
match_values_cleared?(scanner) # => true

Неуспешная попытка совпадения с именованными захватами; то же, что и выше, но с named_captures:

scanner = StringScanner.new('somestring')
scanner.exist?(/(?<x>foo)bar(?<y>baz)bat(?<z>bam)/)
match_values_cleared?(scanner) # => false
scanner.named_captures # => {"x"=>nil, "y"=>nil, "z"=>nil}

Свойство фиксированного якоря

Сопоставление шаблонов в StringScanner такое же, как и в Ruby, за исключением свойства фиксированного якоря, которое определяет значение '\A':

  • false (по умолчанию): соответствует текущей позиции байта.

    scanner = StringScanner.new('foobar')
    scanner.scan(/\A./) # => "f"
    scanner.scan(/\A./) # => "o"
    scanner.scan(/\A./) # => "o"
    scanner.scan(/\A./) # => "b"
    
  • true: соответствует началу целевой подстроки; никогда не соответствует, если позиция байта не ноль:

    scanner = StringScanner.new('foobar', fixed_anchor: true)
    scanner.scan(/\A./) # => "f"
    scanner.scan(/\A./) # => nil
    scanner.reset
    scanner.scan(/\A./) # => "f"
    

Свойство фиксированного якоря устанавливается при создании объекта StringScanner и не может быть изменено (см. StringScanner.new); метод fixed_anchor? возвращает это значение.

Публичные методы класса

new(string, fixed_anchor: false) → string_scanner
Исходный код
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);
    p->str = str;

    return self;
}

Возвращает новый объект StringScanner, у которого сохранённая строка — заданная string; устанавливает свойство фиксированного якоря:

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

Общедоступные методы экземпляра

<<
Псевдоним для: concat
[](specifier) → подстрока или nil
Исходный код
static VALUE
strscan_aref(VALUE self, VALUE idx)
{
    const char *name;
    struct strscanner *p;
    long i;

    GET_SCANNER(self, p);
    if (! MATCHED_P(p))        return Qnil;

    switch (TYPE(idx)) {
        case T_SYMBOL:
            idx = rb_sym2str(idx);
            /* fall through */
        case T_STRING:
            if (!RTEST(p->regex)) return Qnil;
            RSTRING_GETMEM(idx, name, i);
            i = name_to_backref_number(&(p->regs), p->regex, name, name + i, rb_enc_get(idx));
            break;
        default:
            i = NUM2LONG(idx);
    }

    if (i < 0)
        i += p->regs.num_regs;
    if (i < 0)                 return Qnil;
    if (i >= p->regs.num_regs) return Qnil;
    if (p->regs.beg[i] == -1)  return Qnil;

    return extract_range(p,
                         adjust_register_position(p, p->regs.beg[i]),
                         adjust_register_position(p, p->regs.end[i]));
}

Возвращает захваченную подстроку или nil; см. Захваченные значения совпадения.

Когда есть захват:

scanner = StringScanner.new('Fri Dec 12 1975 14:39')
scanner.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)
  • specifier ноль: возвращает всю совпавшую подстроку:

    scanner[0]         # => "Fri Dec 12 "
    scanner.pre_match  # => ""
    scanner.post_match # => "1975 14:39"
    
  • specifier положительное целое число. возвращает n-й захват или nil , если он вне диапазона:

    scanner[1] # => "Fri"
    scanner[2] # => "Dec"
    scanner[3] # => "12"
    scanner[4] # => nil
    
  • specifier отрицательное целое число. считает назад от последней подгруппы:

    scanner[-1] # => "12"
    scanner[-4] # => "Fri Dec 12 "
    scanner[-5] # => nil
    
  • specifier символ или строка. возвращает именованную подгруппу или nil , если такой нет:

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

Когда нет захватов, только [0] возвращает ненулевое %%%CODE_BLOCK_243%%:

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

При неудачном сопоставлении даже [0] возвращает nil:

scanner.scan(/nope/) # => nil
scanner[0]           # => nil
scanner[1]           # => nil
beginning_of_line? → true или false
Исходный код
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;
}

Возвращает, находится ли позиция в начале строки; то есть, в начале сохранённой строки или сразу после новой строки:

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? является псевдонимом для StringScanner#beginning_of_line?.

captures → массив_подстрок или nil
Исходный код
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;
}

Возвращает массив захваченных значений совпадения по индексам (1..) , если последнее попытка сопоставления прошла успешно, или nil в противном случае:

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
charpos ()
Исходный код
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)));
}

вызов: charpos -> позиция_символа

Возвращает позицию символа (по умолчанию ноль), которая может отличаться от байтовой позиции, указанной методом pos:

scanner = StringScanner.new(HIRAGANA_TEXT)
scanner.string # => "こんにちは"
scanner.getch  # => "こ" # 3-byte character.
scanner.getch  # => "ん" # 3-byte character.
put_situation(scanner)
# Situation:
#   pos:       6
#   charpos:   2
#   rest:      "にちは"
#   rest_size: 9
check(шаблон) → совпавшая_подстрока или nil
Исходный код
static VALUE
strscan_check(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 0, 1, 1);
}

Попытка сопоставить заданный pattern в начале целевой подстроки; не изменяет позиций.

Если сопоставление успешно:

  • Возвращает совпавшую подстроку.

  • Устанавливает все значения совпадения.

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

Если сопоставление не удалось:

  • Возвращает nil.

  • Очищает все значения совпадения.

scanner.check(/nope/)          # => nil
match_values_cleared?(scanner) # => true
check_until(шаблон) → подстрока или nil
Исходный код
static VALUE
strscan_check_until(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 0, 1, 0);
}

Попытка сопоставить заданный pattern где угодно (в любой позиции) в целевой подстроке; не изменяет позиции.

Если сопоставление успешно:

  • Устанавливает все значения совпадения.

  • Возвращает совпавшую подстроку, которая простирается от текущей позиции до конца совпавшей подстроки.

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

Если сопоставление не удалось:

  • Очищает все значения совпадения.

  • Возвращает nil.

scanner.check_until(/nope/)    # => nil
match_values_cleared?(scanner) # => true
concat(другая_строка) → self
Исходный код
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;
}
  • Добавляет заданную more_string к сохранённой строке.

  • Возвращает self.

  • Не влияет на позиции или значения совпадения.

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
Также псевдоним для: <<
eos? → true или false
Исходный код
static VALUE
strscan_eos_p(VALUE self)
{
    struct strscanner *p;

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

Возвращает, находится ли позиция в конце сохранённой строки:

scanner = StringScanner.new('foobarbaz')
scanner.eos? # => false
pos = 3
scanner.eos? # => false
scanner.terminate
scanner.eos? # => true
exist?(шаблон) → смещение_байта или nil
Исходный код
static VALUE
strscan_exist_p(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 0, 0, 0);
}

Попытка сопоставить заданный pattern где угодно (в любой позиции) в целевой подстроке; не изменяет позиции.

Если сопоставление успешно:

  • Возвращает смещение байтов: расстояние в байтах между текущей позицией и концом совпавшей подстроки.

  • Устанавливает все значения совпадения.

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

Если сопоставление не удалось:

  • Возвращает nil.

  • Очищает все значения совпадения.

scanner.exist?(/nope/)         # => nil
match_values_cleared?(scanner) # => true
fixed_anchor? → true или false
Исходный код
static VALUE
strscan_fixed_anchor_p(VALUE self)
{
    struct strscanner *p;
    p = check_strscan(self);
    return p->fixed_anchor_p ? Qtrue : Qfalse;
}

Возвращает, установлено ли свойство фиксированной точки.

END_OF_DOCUMENT_MARKER ```
get_byte ()
Исходный код
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]));
}

call-seq: get_byte -> байт_как_символ или nil

Возвращает следующий байт, если он доступен:

  • Если позиция не находится в конце хранимой строки:

    • Возвращает следующий байт.

    • Увеличивает положение байта.

    • Корректирует положение символа.

    scanner = StringScanner.new(HIRAGANA_TEXT)
    # => #<StringScanner 0/15 @ "\xE3\x81\x93\xE3\x82...">
    scanner.string                                   # => "こんにちは"
    [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\xE3", 1, 1]
    [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x81", 2, 2]
    [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x93", 3, 1]
    [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\xE3", 4, 2]
    [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x82", 5, 3]
    [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x93", 6, 2]
    
  • В противном случае возвращает nil, и не изменяет позиции.

    scanner.terminate
    [scanner.get_byte, scanner.pos, scanner.charpos] # => [nil, 15, 5]
    
getch ()
Исходный код
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]));
}

call-seq: getch -> символ или nil

Возвращает следующий (возможно, многобайтный) символ, если он доступен:

  • Если позиция находится в начале символа:

    • Возвращает символ.

    • Увеличивает положение символа на 1.

    • Увеличивает положение байта на размер символа (в байтах).

    scanner = StringScanner.new(HIRAGANA_TEXT)
    scanner.string                                # => "こんにちは"
    [scanner.getch, scanner.pos, scanner.charpos] # => ["こ", 3, 1]
    [scanner.getch, scanner.pos, scanner.charpos] # => ["ん", 6, 2]
    [scanner.getch, scanner.pos, scanner.charpos] # => ["に", 9, 3]
    [scanner.getch, scanner.pos, scanner.charpos] # => ["ち", 12, 4]
    [scanner.getch, scanner.pos, scanner.charpos] # => ["は", 15, 5]
    [scanner.getch, scanner.pos, scanner.charpos] # => [nil, 15, 5]
    
  • Если позиция находится внутри многобайтного символа (то есть не в начале), ведет себя как get_byte (возвращает 1-байтовый символ):

    scanner.pos = 1
    [scanner.getch, scanner.pos, scanner.charpos] # => ["\x81", 2, 2]
    [scanner.getch, scanner.pos, scanner.charpos] # => ["\x93", 3, 1]
    [scanner.getch, scanner.pos, scanner.charpos] # => ["ん", 6, 2]
    
  • Если позиция находится в конце хранимой строки, возвращает nil и не изменяет позиции:

    scanner.terminate
    [scanner.getch, scanner.pos, scanner.charpos] # => [nil, 15, 5]
    
inspect → строка
Исходный код
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;
}

Возвращает строковое представление self, которое может отображать:

  1. Текущее положение.

  2. Размер (в байтах) хранимой строки.

  3. Подстроку, предшествующую текущему положению.

  4. Подстроку, следующую за текущим положением (которая также является целевой подстрокой).

scanner = StringScanner.new("Fri Dec 12 1975 14:39")
scanner.pos = 11
scanner.inspect # => "#<StringScanner 11/21 \"...c 12 \" @ \"1975 ...\">"

Если в начале строки, элемент 4 выше (подстрока, следующая за текущим положением) опускается:

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

Если в конце строки, все элементы выше опускаются:

scanner.terminate
scanner.inspect # => "#<StringScanner fin>"
pointer= (p1)

call-seq: pos = n -> n pointer = n -> n

Устанавливает позицию байта и позицию символа; возвращает n.

Не влияет на значения совпадения.

Для неотрицательного n, устанавливает позицию в n:

scanner = StringScanner.new(HIRAGANA_TEXT)
scanner.string  # => "こんにちは"
scanner.pos = 3 # => 3
scanner.rest    # => "んにちは"
scanner.charpos # => 1

Для отрицательного n, считает с конца сохранённой строки:

scanner.pos = -9 # => -9
scanner.pos      # => 6
scanner.rest     # => "にちは"
scanner.charpos  # => 2
Псевдоним для: pos=
pos ()
Исходный код
static VALUE
strscan_get_pos(VALUE self)
{
    struct strscanner *p;

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

call-seq: pos -> byte_position

Возвращает целое число позиции байта, которая может отличаться от позиции символа:

scanner = StringScanner.new(HIRAGANA_TEXT)
scanner.string  # => "こんにちは"
scanner.pos     # => 0
scanner.getch   # => "こ" # 3-byte character.
scanner.charpos # => 1
scanner.pos     # => 3
Также псевдоним для: pointer
pos= (p1)
Исходный код
static VALUE
strscan_set_pos(VALUE self, VALUE v)
{
    struct strscanner *p;
    long i;

    GET_SCANNER(self, p);
    i = NUM2INT(v);
    if (i < 0) i += S_LEN(p);
    if (i < 0) rb_raise(rb_eRangeError, "index out of range");
    if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range");
    p->curr = i;
    return LONG2NUM(i);
}

call-seq: pos = n -> n pointer = n -> n

Устанавливает позицию байта и позицию символа; возвращает n.

Не влияет на значения совпадения.

Для неотрицательного n, устанавливает позицию в n:

scanner = StringScanner.new(HIRAGANA_TEXT)
scanner.string  # => "こんにちは"
scanner.pos = 3 # => 3
scanner.rest    # => "んにちは"
scanner.charpos # => 1

Для отрицательного n, считает с конца сохранённой строки:

scanner.pos = -9 # => -9
scanner.pos      # => 6
scanner.rest     # => "にちは"
scanner.charpos  # => 2
Также псевдоним для: pointer=
post_match → substring
Исходный код
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));
}

Возвращает подстроку, следующую за сопоставленной подстрокой с последней попытки сопоставления, если она была успешной, или nil в противном случае; см. Основные значения сопоставления:

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
pre_match → substring
Исходный код
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]));
}

Возвращает подстроку, предшествующую сопоставленной подстроке с последней попытки сопоставления, если она была успешной, или nil в противном случае; см. Основные значения сопоставления:

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
reset → self
Исходный код
static VALUE
strscan_reset(VALUE self)
{
    struct strscanner *p;

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

Устанавливает позицию байта и позицию символа в ноль и очищает значения совпадений; возвращает 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
rest → target_substring
Исходный код
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));
}

Возвращает остальную часть сохранённой строки (всё после текущей позиции), которая является целевой подстрокой:

scanner = StringScanner.new('foobarbaz')
scanner.rest # => "foobarbaz"
scanner.pos = 3
scanner.rest # => "barbaz"
scanner.terminate
scanner.rest # => ""
rest_size → integer
Исходный код
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);
}

Возвращает размер (в байтах) rest сохранённой строки:

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
scan (p1)
Исходный код
static VALUE
strscan_scan(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 1, 1, 1);
}

call-seq: scan(pattern) -> substring or nil

Попытка сопоставить заданный pattern в начале целевой подстроки.

Если сопоставление успешно:

  • Возвращает сопоставленную подстроку.

  • Увеличивает позицию байта на substring.bytesize, и может увеличить позицию символа.

  • Устанавливает значения совпадений.

scanner = StringScanner.new(HIRAGANA_TEXT)
scanner.string     # => "こんにちは"
scanner.pos = 6
scanner.scan(/に/) # => "に"
put_match_values(scanner)
# Basic match values:
#   matched?:       true
#   matched_size:   3
#   pre_match:      "こん"
#   matched  :      "に"
#   post_match:     "ちは"
# Captured match values:
#   size:           1
#   captures:       []
#   named_captures: {}
#   values_at:      ["に", nil]
#   []:
#     [0]:          "に"
#     [1]:          nil
put_situation(scanner)
# Situation:
#   pos:       9
#   charpos:   3
#   rest:      "ちは"
#   rest_size: 6

Если сопоставление не удалось:

  • Возвращает nil.

  • Не увеличивает позицию байта и символа.

  • Очищает значения совпадений.

scanner.scan(/nope/)           # => nil
match_values_cleared?(scanner) # => true
scan_byte → integer_byte
Исходный код
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;
}

Сканирует один байт и возвращает его как целое число. Этот метод не чувствителен к многобайтовым символам. См. также: getch.

scan_until (p1)
Исходный код
static VALUE
strscan_scan_until(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 1, 1, 0);
}

call-seq: scan_until(pattern) -> substring or nil

Попытка сопоставления заданного pattern в любом месте (в любой позиции) целевой подстроки.

Если попытка сопоставления успешна:

  • Устанавливает значения совпадений.

  • Устанавливает позицию байта в конец сопоставленной подстроки; может скорректировать позицию символа.

  • Возвращает сопоставленную подстроку.

scanner = StringScanner.new(HIRAGANA_TEXT)
scanner.string           # => "こんにちは"
scanner.pos = 6
scanner.scan_until(/ち/) # => "にち"
put_match_values(scanner)
# Basic match values:
#   matched?:       true
#   matched_size:   3
#   pre_match:      "こんに"
#   matched  :      "ち"
#   post_match:     "は"
# Captured match values:
#   size:           1
#   captures:       []
#   named_captures: {}
#   values_at:      ["ち", nil]
#   []:
#     [0]:          "ち"
#     [1]:          nil
put_situation(scanner)
# Situation:
#   pos:       12
#   charpos:   4
#   rest:      "は"
#   rest_size: 3

Если попытка сопоставления не удалась:

  • Очищает данные сопоставления.

  • Возвращает nil.

  • Не обновляет позиции.

scanner.scan_until(/nope/)     # => nil
match_values_cleared?(scanner) # => true
size → captures_count
Исходный код
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);
}

Возвращает количество совпадений, если последняя попытка совпадения прошла успешно, nil в противном случае; см. Значения захваченных совпадений:

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
skip (p1)
Исходный код
static VALUE
strscan_skip(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 1, 0, 1);
}

call-seq: skip(pattern) match_size or nil

Пытается сопоставить указанный pattern в начале целевого подстроки;

Если совпадение успешно:

  • Увеличивает байтовый позицию на substring.bytesize, и может увеличить позицию символа.

  • Устанавливает значения совпадения.

  • Возвращает размер (в байтах) сопоставленной подстроки.

scanner = StringScanner.new(HIRAGANA_TEXT)
scanner.string                  # => "こんにちは"
scanner.pos = 6
scanner.skip(/に/)              # => 3
put_match_values(scanner)
# Basic match values:
#   matched?:       true
#   matched_size:   3
#   pre_match:      "こん"
#   matched  :      "に"
#   post_match:     "ちは"
# Captured match values:
#   size:           1
#   captures:       []
#   named_captures: {}
#   values_at:      ["に", nil]
#   []:
#     [0]:          "に"
#     [1]:          nil
put_situation(scanner)
# Situation:
#   pos:       9
#   charpos:   3
#   rest:      "ちは"
#   rest_size: 6

scanner.skip(/nope/)            # => nil
match_values_cleared?(scanner)  # => true
skip_until (p1)
Исходный код
static VALUE
strscan_skip_until(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 1, 0, 0);
}

call-seq: skip_until(pattern) -> matched_substring_size or nil

Пытается сопоставить указанный pattern где угодно (в любой позиции) в целевой подстроке; не изменяет позиции.

Если попытка совпадения успешна:

  • Устанавливает значения совпадения.

  • Возвращает размер сопоставленной подстроки.

scanner = StringScanner.new(HIRAGANA_TEXT)
scanner.string           # => "こんにちは"
scanner.pos = 6
scanner.skip_until(/ち/) # => 6
put_match_values(scanner)
# Basic match values:
#   matched?:       true
#   matched_size:   3
#   pre_match:      "こんに"
#   matched  :      "ち"
#   post_match:     "は"
# Captured match values:
#   size:           1
#   captures:       []
#   named_captures: {}
#   values_at:      ["ち", nil]
#   []:
#     [0]:          "ち"
#     [1]:          nil
put_situation(scanner)
# Situation:
#   pos:       12
#   charpos:   4
#   rest:      "は"
#   rest_size: 3

Если попытка совпадения не удалась:

  • Очищает значения совпадения.

  • Возвращает nil.

scanner.skip_until(/nope/)     # => nil
match_values_cleared?(scanner) # => true
string → stored_string
Исходный код
static VALUE
strscan_get_string(VALUE self)
{
    struct strscanner *p;

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

Возвращает хранимую строку:

scanner = StringScanner.new('foobar')
scanner.string # => "foobar"
scanner.concat('baz')
scanner.string # => "foobarbaz"
string = other_string → other_string
Исходный код
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;
}

Заменяет хранимую строку на заданную other_string:

  • Устанавливает обе позиции в ноль.

  • Очищает значения совпадения.

  • Возвращает 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
terminate ()
Исходный код
static VALUE
strscan_terminate(VALUE self)
{
    struct strscanner *p;

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

call-seq: terminate -> self

Устанавливает сканер на конец строки; возвращает self:

  • Устанавливает обе позиции на конец потока.

  • Очищает значения совпадения.

scanner = StringScanner.new(HIRAGANA_TEXT)
scanner.string                 # => "こんにちは"
scanner.scan_until(/に/)
put_situation(scanner)
# Situation:
#   pos:       9
#   charpos:   3
#   rest:      "ちは"
#   rest_size: 6
match_values_cleared?(scanner) # => false

scanner.terminate              # => #<StringScanner fin>
put_situation(scanner)
# Situation:
#   pos:       15
#   charpos:   5
#   rest:      ""
#   rest_size: 0
match_values_cleared?(scanner) # => true
unscan → self
Исходный код
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;
}

Устанавливает позицию на значение, предшествующее последней успешной попытке сопоставления:

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

Вызывает исключение, если значения совпадения очищены:

scanner.scan(/nope/)           # => nil
match_values_cleared?(scanner) # => true
scanner.unscan                 # Raises StringScanner::Error.
values_at(*specifiers) → array_of_captures or nil
Исходный код
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;
}

Возвращает массив захваченных подстрок или nil при отсутствии таковых.

Для каждого specifier, возвращаемая подстрока [specifier]; см. [].

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

Приватные методы экземпляра

dup → shallow_copy
Исходный код
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;
        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;
}

Возвращает поверхностную копию self; хранимая строка в копии — та же, что и в self.

scan_base10_integer ()
Исходный код
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;
    }

    MATCHED(p);
    p->prev = p->curr;

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

    return strscan_parse_integer(p, 10, len);
}
scan_base16_integer ()
Исходный код
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 + 2)) && ptr[len] == '0' && ptr[len + 1] == 'x') {
        len += 2;
    }

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

    MATCHED(p);
    p->prev = p->curr;

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

    return strscan_parse_integer(p, 16, len);
}

Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API