class MatchData def begin(idx) if idx == 0 start = @full.at(0) else start = @region.at(idx - 1).at(0) return nil if start == -1 end m = Rubinius::Mirror.reflect @source m.byte_to_character_index start end def end(idx) if idx == 0 fin = @full.at(1) else fin = @region.at(idx - 1).at(1) return nil if fin == -1 end m = Rubinius::Mirror.reflect @source m.byte_to_character_index fin end def offset(idx) out = [] out << self.begin(idx) out << self.end(idx) return out end def [](idx, len = nil) return to_a[idx, len] if len case idx when Fixnum if idx <= 0 return matched_area() if idx == 0 return to_a[idx] elsif idx <= @region.size tup = @region[idx - 1] x = tup.at(0) return nil if x == -1 y = tup.at(1) return @source.byteslice(x, y-x) end when String if @regexp.name_table return self[idx.to_sym] end raise IndexError, "Unknown named group '#{idx}'" when Symbol if @regexp.name_table if nums = @regexp.name_table[idx] nums.reverse_each do |num| val = self[num] return val if val end return nil end end raise IndexError, "Unknown named group '#{idx}'" end return to_a[idx] end attr_reader :regexp def ==(other) other.kind_of?(MatchData) && string == other.string && regexp == other.regexp && captures == other.captures end alias_method :eql?, :== def string @source.dup.freeze end def source @source end def full @full end def length @region.fields + 1 end def captures out = Array.new(@region.fields) idx = 0 @region.each do |tup| x = tup.at(0) if x == -1 val = nil else y = tup.at(1) val = @source.byteslice(x, y-x) end out[idx] = val idx += 1 end return out end def names @regexp.names end def pre_match return @source.byteslice(0, 0) if @full.at(0) == 0 nd = @full.at(0) - 1 @source.byteslice(0, nd+1) end def pre_match_from(idx) return @source.byteslice(0, 0) if @full.at(0) == 0 nd = @full.at(0) - 1 @source.byteslice(idx, nd-idx+1) end def collapsing? @full[0] == @full[1] end def post_match nd = @source.bytesize - 1 st = @full.at(1) @source.byteslice(st, nd-st+1) end def inspect capts = captures if capts.empty? "#" else idx = 0 capts.map! { |capture| "#{idx += 1}:#{capture.inspect}" } "#" end end def select unless block_given? raise LocalJumpError, "no block given" end out = [] ma = matched_area() out << ma if yield ma each_capture do |str| if yield(str) out << str end end return out end alias_method :size, :length def to_a ary = captures() ary.unshift matched_area() return ary end def values_at(*indexes) indexes.map { |i| self[i] }.flatten(1) end def matched_area x = @full.at(0) y = @full.at(1) @source.byteslice(x, y-x) end alias_method :to_s, :matched_area private :matched_area def get_capture(num) x, y = @region[num] return nil if !y or x == -1 return @source.byteslice(x, y-x) end private :get_capture def each_capture @region.each do |tup| x, y = *tup yield @source.byteslice(x, y-x) end end private :each_capture end