Permalink
Browse files

A number of fixes for Regexp found running rails3

@source must be dup'd before returning.
Made our named capture API mirror the API in 1.9.
  • Loading branch information...
Evan Phoenix
Evan Phoenix committed Nov 5, 2009
1 parent aac7c52 commit 113c3582837c19ff640e057d9f647eedd49a63e7
Showing with 28 additions and 9 deletions.
  1. +3 −1 kernel/bootstrap/regexp.rb
  2. +20 −8 kernel/common/regexp.rb
  3. +5 −0 vm/builtin/regexp.cpp
@@ -8,12 +8,14 @@ def self.allocate
##
# See Regexp.new. This may be overridden by subclasses.
- def initialize(pattern, opts, lang)
+ def compile(pattern, opts, lang)
Ruby.primitive :regexp_initialize
raise PrimitiveFailure,
"regexp_new(#{str.inspect}, #{opts}, #{lang.inspect}) primitive failed"
end
+ private :compile
+
def search_region(str, start, finish, forward) # equiv to MRI's re_search
Ruby.primitive :regexp_search_region
raise PrimitiveFailure, "Regexp#search_region primitive failed"
View
@@ -1,7 +1,4 @@
class Regexp
- attr_reader :source
- attr_reader :names
-
ValidKcode = [?n,?e,?s,?u]
KcodeValue = [16,32,48,64]
@@ -64,7 +61,7 @@ class Regexp
# You may also explicitly pass in 'n', 'N' or 'none' to disable multibyte
# support. Any other values are ignored.
- def self.new(pattern, opts = nil, lang = nil)
+ def initialize(pattern, opts=nil, lang=nil)
if pattern.is_a?(Regexp)
opts = pattern.options
pattern = pattern.source
@@ -82,9 +79,7 @@ def self.new(pattern, opts = nil, lang = nil)
opts |= KcodeValue[idx] if idx
end
- r = allocate
- r.send :initialize, pattern, opts, lang
- r
+ compile pattern, opts, lang
end
def self.escape(str)
@@ -140,6 +135,10 @@ def self.union(*patterns)
Regexp.new(patterns.join('|'))
end
+ def source
+ @source.dup
+ end
+
def ~
line = $_
if !line.is_a?(String)
@@ -466,6 +465,19 @@ def option_to_string(option)
string << 'x' if (option & EXTENDED) > 0
string
end
+
+ def name_table
+ @names
+ end
+
+ def named_captures
+ hash = {}
+ @names.each do |k,v|
+ hash[k.to_s] = [v + 1] # we only have one location currently for a key
+ end
+
+ return hash
+ end
end
class MatchData
@@ -544,7 +556,7 @@ def [](idx, len = nil)
if len
return to_a[idx, len]
elsif idx.is_a?(Symbol)
- num = @regexp.names[idx]
+ num = @regexp.name_table[idx]
raise ArgumentError, "Unknown named group '#{idx}'" unless num
return get_capture(num)
elsif !idx.is_a?(Integer) or idx < 0
View
@@ -228,6 +228,7 @@ namespace rubinius {
// 'self' is passed in automatically by the primitive glue
Regexp* Regexp::allocate(STATE, Object* self) {
Regexp* re = Regexp::create(state);
+ re->onig_data = 0;
re->klass(state, (Class*)self);
return re;
}
@@ -367,6 +368,8 @@ namespace rubinius {
Regexp* reg_o = force_as<Regexp>(obj);
regex_t* reg = reg_o->onig_data;
+ if(!reg) return;
+
ByteArray* reg_ba = ByteArray::from_body(reg);
if(ByteArray* reg_tmp = force_as<ByteArray>(mark.call(reg_ba))) {
@@ -436,6 +439,8 @@ namespace rubinius {
Regexp* reg_o = force_as<Regexp>(obj);
regex_t* reg = reg_o->onig_data;
+ if(!reg) return;
+
ByteArray* reg_ba = ByteArray::from_body(reg);
visit.call(reg_ba);

0 comments on commit 113c358

Please sign in to comment.