diff options
author | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2022-12-09 13:03:33 +0900 |
---|---|---|
committer | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2022-12-09 16:36:22 +0900 |
commit | 4e31fea77d360c6535e33ff2525d80fba38d15d8 (patch) | |
tree | 92bdeec2cadb323f10197d1013c699589feb83d0 /ext/strscan/strscan.c | |
parent | bcf01b18cfe9b21bfde32e28edd4745703bf190c (diff) |
Merge strscan-3.0.5
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/6890
Diffstat (limited to 'ext/strscan/strscan.c')
-rw-r--r-- | ext/strscan/strscan.c | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c index e1426380b4..9b646ab678 100644 --- a/ext/strscan/strscan.c +++ b/ext/strscan/strscan.c @@ -22,7 +22,7 @@ extern size_t onig_region_memsize(const struct re_registers *regs); #include <stdbool.h> -#define STRSCAN_VERSION "3.0.1" +#define STRSCAN_VERSION "3.0.5" /* ======================================================================= Data Type Definitions @@ -435,11 +435,11 @@ strscan_get_pos(VALUE self) * * In short, it's a 0-based index into the string. * - * s = StringScanner.new("abcädeföghi") - * s.charpos # -> 0 - * s.scan_until(/ä/) # -> "abcä" - * s.pos # -> 5 - * s.charpos # -> 4 + * s = StringScanner.new("abc\u00e4def\u00f6ghi") + * s.charpos # -> 0 + * s.scan_until(/\u00e4/) # -> "abc\u00E4" + * s.pos # -> 5 + * s.charpos # -> 4 */ static VALUE strscan_get_charpos(VALUE self) @@ -1458,6 +1458,54 @@ strscan_fixed_anchor_p(VALUE self) return p->fixed_anchor_p ? Qtrue : Qfalse; } +typedef struct { + VALUE self; + VALUE captures; +} named_captures_data; + +static int +named_captures_iter(const OnigUChar *name, + const OnigUChar *name_end, + int back_num, + int *back_refs, + OnigRegex regex, + void *arg) +{ + named_captures_data *data = arg; + + VALUE key = rb_str_new((const char *)name, name_end - name); + VALUE value = RUBY_Qnil; + int i; + for (i = 0; i < back_num; i++) { + value = strscan_aref(data->self, INT2NUM(back_refs[i])); + } + rb_hash_aset(data->captures, key, value); + return 0; +} + +/* + * call-seq: + * scanner.named_captures -> hash + * + * Returns a hash of string variables matching the regular expression. + * + * scan = StringScanner.new('foobarbaz') + * scan.match?(/(?<f>foo)(?<r>bar)(?<z>baz)/) + * scan.named_captures # -> {"f"=>"foo", "r"=>"bar", "z"=>"baz"} + */ +static VALUE +strscan_named_captures(VALUE self) +{ + struct strscanner *p; + GET_SCANNER(self, p); + named_captures_data data; + data.self = self; + data.captures = rb_hash_new(); + onig_foreach_name(RREGEXP_PTR(p->regex), named_captures_iter, &data); + + return data.captures; +} + /* ======================================================================= Ruby Interface ======================================================================= */ @@ -1468,6 +1516,8 @@ strscan_fixed_anchor_p(VALUE self) * StringScanner provides for lexical scanning operations on a String. Here is * an example of its usage: * + * require 'strscan' + * * s = StringScanner.new('This is an example string') * s.eos? # -> false * @@ -1650,4 +1700,6 @@ Init_strscan(void) rb_define_method(StringScanner, "inspect", strscan_inspect, 0); rb_define_method(StringScanner, "fixed_anchor?", strscan_fixed_anchor_p, 0); + + rb_define_method(StringScanner, "named_captures", strscan_named_captures, 0); } |