Skip to content

Commit

Permalink
A number of fixes for Regexp found running rails3
Browse files Browse the repository at this point in the history
@source must be dup'd before returning.
Made our named capture API mirror the API in 1.9.
  • Loading branch information
Evan Phoenix committed Nov 5, 2009
1 parent aac7c52 commit 113c358
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 9 deletions.
4 changes: 3 additions & 1 deletion kernel/bootstrap/regexp.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ def self.allocate
## ##
# See Regexp.new. This may be overridden by subclasses. # See Regexp.new. This may be overridden by subclasses.


def initialize(pattern, opts, lang) def compile(pattern, opts, lang)
Ruby.primitive :regexp_initialize Ruby.primitive :regexp_initialize
raise PrimitiveFailure, raise PrimitiveFailure,
"regexp_new(#{str.inspect}, #{opts}, #{lang.inspect}) primitive failed" "regexp_new(#{str.inspect}, #{opts}, #{lang.inspect}) primitive failed"
end end


private :compile

def search_region(str, start, finish, forward) # equiv to MRI's re_search def search_region(str, start, finish, forward) # equiv to MRI's re_search
Ruby.primitive :regexp_search_region Ruby.primitive :regexp_search_region
raise PrimitiveFailure, "Regexp#search_region primitive failed" raise PrimitiveFailure, "Regexp#search_region primitive failed"
Expand Down
28 changes: 20 additions & 8 deletions kernel/common/regexp.rb
Original file line number Original file line Diff line number Diff line change
@@ -1,7 +1,4 @@
class Regexp class Regexp
attr_reader :source
attr_reader :names

ValidKcode = [?n,?e,?s,?u] ValidKcode = [?n,?e,?s,?u]
KcodeValue = [16,32,48,64] KcodeValue = [16,32,48,64]


Expand Down Expand Up @@ -64,7 +61,7 @@ class Regexp
# You may also explicitly pass in 'n', 'N' or 'none' to disable multibyte # You may also explicitly pass in 'n', 'N' or 'none' to disable multibyte
# support. Any other values are ignored. # 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) if pattern.is_a?(Regexp)
opts = pattern.options opts = pattern.options
pattern = pattern.source pattern = pattern.source
Expand All @@ -82,9 +79,7 @@ def self.new(pattern, opts = nil, lang = nil)
opts |= KcodeValue[idx] if idx opts |= KcodeValue[idx] if idx
end end


r = allocate compile pattern, opts, lang
r.send :initialize, pattern, opts, lang
r
end end


def self.escape(str) def self.escape(str)
Expand Down Expand Up @@ -140,6 +135,10 @@ def self.union(*patterns)
Regexp.new(patterns.join('|')) Regexp.new(patterns.join('|'))
end end


def source
@source.dup
end

def ~ def ~
line = $_ line = $_
if !line.is_a?(String) if !line.is_a?(String)
Expand Down Expand Up @@ -466,6 +465,19 @@ def option_to_string(option)
string << 'x' if (option & EXTENDED) > 0 string << 'x' if (option & EXTENDED) > 0
string string
end 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 end


class MatchData class MatchData
Expand Down Expand Up @@ -544,7 +556,7 @@ def [](idx, len = nil)
if len if len
return to_a[idx, len] return to_a[idx, len]
elsif idx.is_a?(Symbol) elsif idx.is_a?(Symbol)
num = @regexp.names[idx] num = @regexp.name_table[idx]
raise ArgumentError, "Unknown named group '#{idx}'" unless num raise ArgumentError, "Unknown named group '#{idx}'" unless num
return get_capture(num) return get_capture(num)
elsif !idx.is_a?(Integer) or idx < 0 elsif !idx.is_a?(Integer) or idx < 0
Expand Down
5 changes: 5 additions & 0 deletions vm/builtin/regexp.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ namespace rubinius {
// 'self' is passed in automatically by the primitive glue // 'self' is passed in automatically by the primitive glue
Regexp* Regexp::allocate(STATE, Object* self) { Regexp* Regexp::allocate(STATE, Object* self) {
Regexp* re = Regexp::create(state); Regexp* re = Regexp::create(state);
re->onig_data = 0;
re->klass(state, (Class*)self); re->klass(state, (Class*)self);
return re; return re;
} }
Expand Down Expand Up @@ -367,6 +368,8 @@ namespace rubinius {
Regexp* reg_o = force_as<Regexp>(obj); Regexp* reg_o = force_as<Regexp>(obj);
regex_t* reg = reg_o->onig_data; regex_t* reg = reg_o->onig_data;


if(!reg) return;

ByteArray* reg_ba = ByteArray::from_body(reg); ByteArray* reg_ba = ByteArray::from_body(reg);


if(ByteArray* reg_tmp = force_as<ByteArray>(mark.call(reg_ba))) { if(ByteArray* reg_tmp = force_as<ByteArray>(mark.call(reg_ba))) {
Expand Down Expand Up @@ -436,6 +439,8 @@ namespace rubinius {
Regexp* reg_o = force_as<Regexp>(obj); Regexp* reg_o = force_as<Regexp>(obj);
regex_t* reg = reg_o->onig_data; regex_t* reg = reg_o->onig_data;


if(!reg) return;

ByteArray* reg_ba = ByteArray::from_body(reg); ByteArray* reg_ba = ByteArray::from_body(reg);
visit.call(reg_ba); visit.call(reg_ba);


Expand Down

0 comments on commit 113c358

Please sign in to comment.