Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
16a4b46
feat: add test for named captures
ericgpks Jul 7, 2022
a3a7de3
fix: change test to be
ericgpks Jul 7, 2022
aecf835
feat: add empty method
ericgpks Jul 12, 2022
f9e9510
Update ext/strscan/strscan.c
ericgpks Jul 14, 2022
cd5c2c5
feat: change to use onig_foreach_name
ericgpks Aug 31, 2022
d8178c0
Merge branch 'master' into fix-support-named-captures
ericgpks Sep 13, 2022
1e1bf0f
fix: prepare another method to use main and change main logic
ericgpks Sep 13, 2022
666f22b
Merge branch 'fix-support-named-captures' of https://github.com/ericg…
ericgpks Sep 13, 2022
7380bda
feat: add document
ericgpks Sep 13, 2022
83d1655
Update ext/strscan/strscan.c
ericgpks Sep 14, 2022
617c3f9
Update test/strscan/test_stringscanner.rb
ericgpks Sep 14, 2022
83f042e
Update ext/strscan/strscan.c
ericgpks Sep 14, 2022
aecf844
Update test/strscan/test_stringscanner.rb
ericgpks Sep 14, 2022
30fb1b4
fix regex format in test
ericgpks Sep 14, 2022
f63639c
fix: change to use assert to check boolean
ericgpks Sep 14, 2022
aa60ea8
Update test/strscan/test_stringscanner.rb
ericgpks Sep 14, 2022
a139d4d
fix: change test to check length of a string
ericgpks Sep 16, 2022
4ed10e4
Merge branch 'fix-support-named-captures' of https://github.com/ericg…
ericgpks Sep 16, 2022
171a940
fix: change order to test expected and actual
ericgpks Sep 17, 2022
af71c09
fix: change expected value to use literal
ericgpks Sep 17, 2022
5b11f73
Fix style
kou Sep 18, 2022
5def9c2
Simplify
kou Sep 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions ext/strscan/strscan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Comment thread
ericgpks marked this conversation as resolved.

/* =======================================================================
Ruby Interface
======================================================================= */
Expand Down Expand Up @@ -1652,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);
}
8 changes: 8 additions & 0 deletions test/strscan/test_stringscanner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,14 @@ def test_scan_aref_repeatedly
assert_equal "t", s[1]
assert_equal "ring", s[2]
end

def test_named_captures
Comment thread
ericgpks marked this conversation as resolved.
omit("not implemented on JRuby and TruffleRuby") if ["jruby", "truffleruby"].include?(RUBY_ENGINE)
scan = StringScanner.new("foobarbaz")
re = /(?<f>foo)(?<r>bar)(?<z>baz)/
assert_equal(9 ,scan.match?(re))
Comment thread
kou marked this conversation as resolved.
Outdated
assert_equal({"f" => "foo", "r" => "bar", "z" => "baz"}, scan.named_captures)
end
end

class TestStringScannerFixedAnchor < TestStringScanner
Expand Down