Spec-Zone.ru › Ruby 3.4

класс StringScanner

Родительский класс:
Object

Класс 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.

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

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

Позиции

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

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

Метод Действие
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

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

Целевая подстрока задаётся каждый раз, когда:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Метод Возвращаемое значение Задаёт значения совпадения?
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. Нет.

Получение сведений о сканере

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

Метод Возвращаемое значение
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 и пытается найти совпадающую подстроку в целевой подстроке.

Метод Тип образца Сопоставление с целевой подстрокой Возвращаемое значение при успехе Может ли изменять позиции?
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)

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

Основные значения совпадения не связаны с захватами.

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

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


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

Значения совпадения с захватами

Значения совпадения с захватами связаны с захватами.

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

Метод Возвращаемое значение при совпадении Возвращаемое значение при отсутствии совпадения
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) → substring or 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] возвращает значение, отличное от nil:

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 or 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 → substring_array or 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 -> character_position

Возвращает позицию символа (изначально равную нулю), которая может отличаться от позиции байта, возвращаемой методом 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(pattern) → matched_substring or 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(pattern) → substring or 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(more_string) → 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 or 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?(pattern) → byte_offset or 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 or false Показать исходный код
static VALUE
strscan_fixed_anchor_p(VALUE self)
{
    struct strscanner *p;
    p = check_strscan(self);
    return p->fixed_anchor_p ? Qtrue : Qfalse;
}

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

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

сигнатура вызова: get_byte -> byte_as_character or 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]));
}

сигнатура вызова: getch -> character or 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 (возвращает однобайтный символ):

    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 → string Показать исходный код
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>"
match?(pattern) → updated_position or nil Показать исходный код
static VALUE
strscan_match_p(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 0, 0, 1);
}

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

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

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

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

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

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

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

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

  • Не увеличивает позиции.

scanner.match?(/nope/)         # => nil
match_values_cleared?(scanner) # => true
matched → matched_substring or nil Показать исходный код
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]));
}

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

scanner = StringScanner.new('foobarbaz')
scanner.matched        # => nil
scanner.pos = 3
scanner.match?(/bar/)  # => 3
scanner.matched        # => "bar"
scanner.match?(/nope/) # => nil
scanner.matched        # => nil
matched? → true or false Показать исходный код
static VALUE
strscan_matched_p(VALUE self)
{
    struct strscanner *p;

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

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

scanner = StringScanner.new('foobarbaz')
scanner.matched?       # => false
scanner.pos = 3
scanner.exist?(/baz/)  # => 6
scanner.matched?       # => true
scanner.exist?(/nope/) # => nil
scanner.matched?       # => false
matched_size → substring_size or nil Показать исходный код
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]);
}

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

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
named_captures → hash Показать исходный код
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;
}

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

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 # => {}
peek(length) → substring Показать исходный код
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);
}

Возвращает подстроку string[pos, length]; не обновляет значения совпадения или позиции:

scanner = StringScanner.new('foobarbaz')
scanner.pos = 3
scanner.peek(3)   # => "bar"
scanner.terminate
scanner.peek(3)   # => ""
peek_byte () Показать исходный код
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));
}

Просматривает текущий байт и возвращает его в виде целого числа.

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

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
Псевдоним для: pos
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);
}

последовательность вызова: 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);
}

последовательность вызова: 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);
}

последовательность вызова: 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;
}

последовательность вызова: 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–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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