match_at 1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 91f41f9404f9926d531ef6c827e0617156bb71bf
4
+ data.tar.gz: 28ec30a32bfd55544e760881dd91fcb8ed2a16b9
5
+ SHA512:
6
+ metadata.gz: a3a19f48b310d85009e46fe2ba8bc6ba517f2b42576428da4ca57c68743171b81c1160be6093abfe6635c3b44343952a3e49b41bb04da07a44c553004070bc76
7
+ data.tar.gz: 1952562c10d176e24f0de5fe980447ce8ca94f9b1d8f87e4160f8c86f0541831bc0ae9e9c9172c8ad16b888d3c5068917303392f7c5c87307ca9a1c0de383052
data/.gitignore ADDED
@@ -0,0 +1,33 @@
1
+ # Copyright (c) 2017 Urabe, Shyouhei
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be
11
+ # included in all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ .DS_Store
22
+ .bundle
23
+ .ruby-version
24
+ .yardoc
25
+ Gemfile.lock
26
+ coverage
27
+ doc
28
+ stackprof.dump
29
+ tmp
30
+ vendor
31
+ *.so
32
+ *.dll
33
+ *.bundle
data/.rubocop.yml ADDED
@@ -0,0 +1,86 @@
1
+ #! /your/favourite/path/to/rubocop
2
+ # -*- mode: yaml; coding: utf-8 -*-
3
+
4
+ # Copyright (c) 2017 Urabe, Shyouhei
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ AllCops:
25
+ DisabledByDefault: false # true
26
+ DisplayCopNames: true
27
+ Exclude:
28
+ - "vendor/**/*"
29
+ TargetRubyVersion: 2.4 # 2.5
30
+
31
+ Layout:
32
+ Enabled: false
33
+
34
+ Lint/AmbiguousBlockAssociation:
35
+ Enabled: false
36
+
37
+ Lint/LiteralInCondition:
38
+ Enabled: false
39
+
40
+ Lint/ScriptPermission:
41
+ Enabled: false
42
+
43
+ Metrics/AbcSize:
44
+ Enabled: false
45
+
46
+ Metrics/ClassLength:
47
+ Enabled: false
48
+
49
+ Metrics/CyclomaticComplexity:
50
+ Enabled: false
51
+
52
+ Metrics/BlockLength:
53
+ Enabled: false
54
+
55
+ Metrics/MethodLength:
56
+ Enabled: false
57
+
58
+ Metrics/PerceivedComplexity:
59
+ # What the f* is this thing?
60
+ Enabled: false
61
+
62
+ Rails:
63
+ Enabled: false
64
+
65
+ Security/Eval:
66
+ Enabled: false
67
+
68
+ Security/MarshalLoad:
69
+ Enabled: false
70
+
71
+ Style:
72
+ Enabled: false
73
+
74
+ Lint/AssignmentInCondition:
75
+ Enabled: false
76
+
77
+ Lint/UselessAssignment:
78
+ Exclude:
79
+ - 'test/**/*'
80
+ - '*.gemspec'
81
+
82
+ Metrics/LineLength:
83
+ AllowURI: true
84
+ Max: 80
85
+ Exclude:
86
+ - 'test/**/*'
data/.yardopts ADDED
@@ -0,0 +1,6 @@
1
+ --markup-provider=redcarpet
2
+ --markup=markdown
3
+ --charset utf-8
4
+ --readme README.md
5
+ lib/**/*.rb
6
+ ext/**/*.c
data/Gemfile ADDED
@@ -0,0 +1,27 @@
1
+ #! /your/favourite/path/to/bundler
2
+ # -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
3
+ # -*- frozen_string_literal: true -*-
4
+ # -*- warn_indent: true -*-
5
+
6
+ # Copyright (c) 2017 Urabe, Shyouhei
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ # SOFTWARE.
25
+
26
+ source 'https://rubygems.org'
27
+ gemspec require: false
data/LICENSE.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2017 Urabe, Shyouhei
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be
11
+ included in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # match_at: implementation of `String#match_at`, `Regexp#match_at`
2
+
3
+ Regular expressions are useful but current Ruby lacks one feature: to match a regular expression against particular position of a String. This functionality _is_ in fact implemented in the regular expression engine, but have not been exposed so far. This is a very tiny extension library to give you that feature.
4
+
5
+ ## What is match_at and why you need it
6
+
7
+ Your basic usage of regular expressions in ruby is like this:
8
+
9
+ ```ruby
10
+ md = /bar/.match "foobarbaz" # => #<MatchData "bar">
11
+
12
+ # 0 1 2 3 4 5 6 7 8
13
+ # f o o b a r b a z
14
+ # |---|
15
+ # match
16
+
17
+ md.pre_match # => "foo"
18
+ md.post_match # => "baz"
19
+ md.begin(0) # => 3
20
+ md.end(0) # => 5
21
+ ```
22
+
23
+ Here, the regular expression matches at the middle of the parameter string. Normal behaviour of a regular expression is to search for leftmost & longest string that fits the pattern.
24
+
25
+ But that is not always what you want. When you want to split a long string into a series of tokens, it is usually not optimal to scan again and again from the beginning.
26
+
27
+ ```
28
+ ... f o o b a r b a z ...
29
+ ---> |
30
+ suppose you have already scanned here.
31
+ you want to start from this exact position...
32
+ ```
33
+
34
+ This kind of situation has formerlly been tackled by the StringScanner standard library. That is still okay today. However strscan is not "fluent"; for instance you can't get a MatchData with it.
35
+
36
+ Luckily as I wrote above the functionality is already there. This library is to let you use it.
37
+
38
+ ```ruby
39
+ md = /bar/.match_at "foobarbaz", 3 # => #<MatchData "bar">
40
+
41
+ # 0 1 2 3 4 5 6 7 8
42
+ # f o o b a r b a z
43
+ # |---|
44
+ # match
45
+
46
+ md.pre_match # => "foo"
47
+ md.post_match # => "baz"
48
+ md.begin(0) # => 3
49
+ md.end(0) # => 5
50
+ ```
data/Rakefile ADDED
@@ -0,0 +1,71 @@
1
+ #! /your/favourite/path/to/rake
2
+ # -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
3
+ # -*- frozen_string_literal: true -*-
4
+ # -*- warn_indent: true -*-
5
+
6
+ # Copyright (c) 2017 Urabe, Shyouhei
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ # SOFTWARE.
25
+
26
+ require 'rubygems'
27
+ require 'bundler/setup'
28
+ Bundler.setup :development
29
+ require 'rake'
30
+ require 'rake/extensiontask'
31
+ require 'yard'
32
+ require 'bundler/gem_tasks'
33
+ require 'rake/testtask'
34
+ require 'rubocop/rake_task'
35
+
36
+ YARD::Rake::YardocTask.new
37
+ RuboCop::RakeTask.new
38
+
39
+ Rake::ExtensionTask.new "match_at" do |ext|
40
+ ext.lib_dir = "lib/match_at"
41
+ end
42
+
43
+ task default: :test
44
+ task spec: :test
45
+ desc "run tests"
46
+ Rake::TestTask.new do |t|
47
+ t.test_files = FileList['test/**/*.rb'] - ['test/test_helper.rb']
48
+ t.warning = true
49
+ t.verbose = true
50
+ end
51
+
52
+ desc "a la rails console"
53
+ task :console do
54
+ require 'irb'
55
+ require 'irb/completion'
56
+ ARGV.clear
57
+ IRB.start
58
+ end
59
+ task c: :console
60
+ task irb: :console
61
+
62
+ desc "pry console"
63
+ task :pry do
64
+ require 'pry'
65
+ ARGV.clear
66
+ Pry.start
67
+ end
68
+
69
+ task test: :compile
70
+ task console: :compile
71
+ task pri: :compile
@@ -0,0 +1,27 @@
1
+ #! /your/favourite/path/to/ruby
2
+ # -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
3
+ # -*- frozen_string_literal: true -*-
4
+ # -*- warn_indent: true -*-
5
+
6
+ # Copyright (c) 2017 Urabe, Shyouhei
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ # SOFTWARE.
25
+
26
+ require 'mkmf'
27
+ create_makefile 'match_at'
@@ -0,0 +1,124 @@
1
+ /* -*- mode: c; coding: utf-8; indent-tabs-mode: nil -*- */
2
+ /* Copyright (c) 2017 Urabe, Shyouhei
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to
6
+ * deal in the Software without restriction, including without limitation the
7
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8
+ * sell copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be
12
+ * included in all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20
+ * IN THE SOFTWARE.
21
+ */
22
+
23
+ #include <stdbool.h>
24
+ #include <ruby/ruby.h>
25
+ #include <ruby/re.h>
26
+ #include <ruby/encoding.h>
27
+
28
+ static VALUE match_at(VALUE RB_UNUSED_VAR(mod), VALUE str, VALUE rexp, VALUE pos);
29
+ static VALUE match_at_p(VALUE RB_UNUSED_VAR(mod), VALUE str, VALUE rexp, VALUE pos);
30
+ static bool do_match(VALUE str, VALUE rexp, VALUE pos, OnigRegion *region);
31
+
32
+ VALUE
33
+ match_at_p(VALUE mod, VALUE str, VALUE rexp, VALUE pos)
34
+ {
35
+ return do_match(str, rexp, pos, NULL) ? Qtrue : Qfalse;
36
+ }
37
+
38
+ VALUE
39
+ match_at(VALUE mod, VALUE str, VALUE rexp, VALUE pos)
40
+ {
41
+ OnigRegion region = { 0 };
42
+ VALUE ret = Qnil;
43
+
44
+ if (do_match(str, rexp, pos, &region)) {
45
+ int err;
46
+ ret = rb_funcall(rb_cMatch, rb_intern("allocate"), 0);
47
+ err = rb_reg_region_copy(RMATCH_REGS(ret), &region);
48
+ if (err) {
49
+ rb_memerror();
50
+ }
51
+ else {
52
+ RMATCH(ret)->regexp = rexp;
53
+ RMATCH(ret)->str = rb_str_new_frozen(str); /* copy */
54
+ OBJ_INFECT(ret, rexp);
55
+ OBJ_INFECT(ret, str);
56
+ /* no backref introduced, OK write barrier. */
57
+ }
58
+ }
59
+ onig_region_free(&region, 0);
60
+ return ret;
61
+ }
62
+
63
+ bool
64
+ do_match(
65
+ VALUE vstr,
66
+ VALUE vreg,
67
+ VALUE vpos,
68
+ OnigRegion *region)
69
+ {
70
+ const char *str;
71
+ const char *end;
72
+ const char *ptr;
73
+ const rb_encoding *enc;
74
+ long pos;
75
+ OnigRegex reg;
76
+ OnigPosition result;
77
+ bool tmpreg;
78
+
79
+ Check_Type(vreg, T_REGEXP);
80
+
81
+ pos = NUM2LONG(vpos);
82
+ str = rb_string_value_ptr(&vstr);
83
+ enc = rb_enc_check(vstr, vreg);
84
+ end = RSTRING_END(vstr);
85
+ ptr = rb_enc_nth(str, end, pos, enc);
86
+ reg = rb_reg_prepare_re(vreg, vstr);
87
+ tmpreg = (reg != RREGEXP_PTR(vreg));
88
+
89
+ /* This !tmpreg maneuver is required to prevent memory leaks. */
90
+ if (!tmpreg) RREGEXP(vreg)->usecnt++;
91
+ result = onig_match(reg, (OnigUChar *)str, (OnigUChar *)end,
92
+ (OnigUChar *)ptr, region, ONIG_OPTION_NONE);
93
+ if (!tmpreg) RREGEXP(vreg)->usecnt--;
94
+
95
+ if (tmpreg) {
96
+ if (RREGEXP(vreg)->usecnt) {
97
+ onig_free(reg);
98
+ }
99
+ else {
100
+ onig_free(RREGEXP_PTR(vreg));
101
+ RREGEXP_PTR(vreg) = reg;
102
+ }
103
+ }
104
+
105
+ if (result >= 0) {
106
+ return true;
107
+ }
108
+ else if (result == ONIG_MISMATCH) {
109
+ return false;
110
+ }
111
+ else {
112
+ OnigUChar err[ONIG_MAX_ERROR_MESSAGE_LEN] = { 0 };
113
+ onig_error_code_to_str(err, (int)result);
114
+ rb_raise(rb_eRegexpError, "%s: %+"PRIsVALUE, err, vreg);
115
+ }
116
+ }
117
+
118
+ void
119
+ Init_match_at(void)
120
+ {
121
+ VALUE mod = rb_define_module("MatchAt");
122
+ rb_define_module_function(mod, "match_at?", match_at_p, 3);
123
+ rb_define_module_function(mod, "match_at", match_at, 3);
124
+ }
data/lib/match_at.rb ADDED
@@ -0,0 +1,96 @@
1
+ #! /your/favourite/path/to/ruby
2
+ # -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
3
+ # -*- frozen_string_literal: true -*-
4
+ # -*- warn_indent: true -*-
5
+
6
+ # Copyright (c) 2017 Urabe, Shyouhei
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ # SOFTWARE.
25
+
26
+ # This library is a Refinements. By `use`-ing it your namespace has
27
+ # `String#match_at`.
28
+ module MatchAt
29
+ refine String do
30
+
31
+ # Match, at the exact `pos`-th character.
32
+ #
33
+ # This is much like String#index / String#rindex, but does not try to shift
34
+ # forward / backward to search for other matching points.
35
+ #
36
+ # ```ruby
37
+ # "foobar".match_at(/o/, 0) # => nil
38
+ # "foobar".match_at(/o/, 1) # => #<MatchData "o">
39
+ # "foobar".match_at(/o/, 2) # => #<MatchData "o">
40
+ # "foobar".match_at(/o/, 3) # => nil
41
+ # "foobar".match_at(/bar/, -3) # => #<MatchData "bar">
42
+ # ```
43
+ #
44
+ # @param rexp [Regexp] pattern to match.
45
+ # @param pos [Integer] character index.
46
+ # @return [MatchData] successful match
47
+ # @return [nil] failure in match
48
+ def match_at rexp, pos = 0
49
+ MatchAt.match_at self, rexp, pos
50
+ end
51
+
52
+ # Similar to #match_at, but returns true/false instead of MatchData.
53
+ #
54
+ # @param (see #match_at)
55
+ # @return [true] successful match
56
+ # @return [false] failure in match
57
+ def match_at? rexp, pos = 0
58
+ MatchAt.match_at? self, rexp, pos
59
+ end
60
+ end
61
+
62
+ refine Regexp do
63
+
64
+ # Match, at the exact `pos`-th character.
65
+ #
66
+ # This is much like Regexp#match, especially the arguments are identical.
67
+ # However the way it matches the target string is different.
68
+ #
69
+ # ```ruby
70
+ # /o/.match_at("foobar", 0) # => nil
71
+ # /o/.match_at("foobar", 1) # => #<MatchData "o">
72
+ # /o/.match_at("foobar", 2) # => #<MatchData "o">
73
+ # /o/.match_at("foobar", 3) # => nil
74
+ # /bar/.match_at("fo0bar", -3) # => #<MatchData "bar">
75
+ # ```
76
+ #
77
+ # @param str [String] target string.
78
+ # @param pos [Integer] character index.
79
+ # @return [MatchData] successful match
80
+ # @return [nil] failure in match
81
+ def match_at str, pos = 0
82
+ MatchAt.match_at str, self, pos
83
+ end
84
+
85
+ # Similar to #match_at, but returns true/false instead of MatchData.
86
+ #
87
+ # @param (see #match_at)
88
+ # @return [true] successful match
89
+ # @return [false] failure in match
90
+ def match_at? str, pos = 0
91
+ MatchAt.match_at? str, self, pos
92
+ end
93
+ end
94
+ end
95
+
96
+ require 'match_at/match_at'
@@ -0,0 +1,27 @@
1
+ #! /your/favourite/path/to/ruby
2
+ # -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
3
+ # -*- frozen_string_literal: true -*-
4
+ # -*- warn_indent: true -*-
5
+
6
+ # Copyright (c) 2017 Urabe, Shyouhei
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ # SOFTWARE.
25
+ ;
26
+
27
+ MatchAt::VERSION = 1
data/match_at.gemspec ADDED
@@ -0,0 +1,60 @@
1
+ #! /your/favourite/path/to/gem
2
+ # -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
3
+ # -*- frozen_string_literal: true -*-
4
+ # -*- warn_indent: true -*-
5
+
6
+ # Copyright (c) 2017 Urabe, Shyouhei
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ # SOFTWARE.
25
+
26
+ # :HACK: avoid namespace pollution
27
+ path = File.expand_path 'lib/match_at/version.rb', __dir__
28
+ content = File.read path
29
+ version = Module.new.module_eval <<-'end'
30
+ MatchAt = Module.new
31
+ eval content, binding, path
32
+ end
33
+
34
+ Gem::Specification.new do |spec|
35
+ spec.name = 'match_at'
36
+ spec.version = version
37
+ spec.author = 'Urabe, Shyouhei'
38
+ spec.email = 'shyouhei@ruby-lang.org'
39
+ spec.summary = 'implements String#match_at'
40
+ spec.description = 'implements String#match_at'
41
+ spec.homepage = 'https://github.com/shyouhei/match_at'
42
+ spec.license = 'MIT'
43
+ spec.extensions = %w'ext/match_at/extconf.rb'
44
+ spec.files = `git ls-files -z`.split("\x0").reject { |f|
45
+ f.match(%r'^(test|spec|features|samples)/')
46
+ }
47
+
48
+ spec.add_development_dependency 'bundler'
49
+ spec.add_development_dependency 'pry-byebug'
50
+ spec.add_development_dependency 'rake'
51
+ spec.add_development_dependency 'rake-compiler'
52
+ spec.add_development_dependency 'rdoc'
53
+ spec.add_development_dependency 'redcarpet'
54
+ spec.add_development_dependency 'rubocop'
55
+ spec.add_development_dependency 'simplecov'
56
+ spec.add_development_dependency 'stackprof'
57
+ spec.add_development_dependency 'test-unit', '>= 3'
58
+ spec.add_development_dependency 'yard'
59
+ spec.required_ruby_version = '>= 2.0.0'
60
+ end
metadata ADDED
@@ -0,0 +1,210 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: match_at
3
+ version: !ruby/object:Gem::Version
4
+ version: '1'
5
+ platform: ruby
6
+ authors:
7
+ - Urabe, Shyouhei
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-08-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry-byebug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake-compiler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rdoc
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: redcarpet
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: stackprof
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: test-unit
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '3'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '3'
153
+ - !ruby/object:Gem::Dependency
154
+ name: yard
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description: implements String#match_at
168
+ email: shyouhei@ruby-lang.org
169
+ executables: []
170
+ extensions:
171
+ - ext/match_at/extconf.rb
172
+ extra_rdoc_files: []
173
+ files:
174
+ - ".gitignore"
175
+ - ".rubocop.yml"
176
+ - ".yardopts"
177
+ - Gemfile
178
+ - LICENSE.txt
179
+ - README.md
180
+ - Rakefile
181
+ - ext/match_at/extconf.rb
182
+ - ext/match_at/match_at.c
183
+ - lib/match_at.rb
184
+ - lib/match_at/version.rb
185
+ - match_at.gemspec
186
+ homepage: https://github.com/shyouhei/match_at
187
+ licenses:
188
+ - MIT
189
+ metadata: {}
190
+ post_install_message:
191
+ rdoc_options: []
192
+ require_paths:
193
+ - lib
194
+ required_ruby_version: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - ">="
197
+ - !ruby/object:Gem::Version
198
+ version: 2.0.0
199
+ required_rubygems_version: !ruby/object:Gem::Requirement
200
+ requirements:
201
+ - - ">="
202
+ - !ruby/object:Gem::Version
203
+ version: '0'
204
+ requirements: []
205
+ rubyforge_project:
206
+ rubygems_version: 2.6.12
207
+ signing_key:
208
+ specification_version: 4
209
+ summary: implements String#match_at
210
+ test_files: []