lib/usher/splitter.rb in usher-0.4.8 vs lib/usher/splitter.rb in usher-0.5.1

- old
+ new

@@ -1,158 +1,21 @@ require 'strscan' class Usher class Splitter - def self.for_delimiters(delimiters, valid_regex) - delimiters_regex = delimiters.collect{|d| Regexp.quote(d)} * '|' - SplitterInstance.new( - delimiters, - Regexp.new('((:|\*)?' + valid_regex + '|' + delimiters_regex + '|\(|\)|\||\{)'), - Regexp.new("[#{delimiters.collect{|d| Regexp.quote(d)}}]|[^#{delimiters.collect{|d| Regexp.quote(d)}}]+") - ) + def self.for_delimiters(router, valid_regex) + SplitterInstance.new(Regexp.new("[#{router.delimiters.collect{|d| Regexp.quote(d)}.join}]|[^#{router.delimiters.collect{|d| Regexp.quote(d)}.join}]+")) end - - attr_reader :paths class SplitterInstance - - attr_reader :delimiter_chars - - def initialize(delimiters, split_regex, url_split_regex) - @delimiters = delimiters - @delimiter_chars = delimiters.collect{|d| d[0]} - @split_regex = split_regex + + def initialize(url_split_regex) @url_split_regex = url_split_regex end def url_split(path) path.scan(@url_split_regex) - end - - def split(path, requirements = nil, default_values = nil) - parts = Group.new(:all, nil) - ss = StringScanner.new(path) - current_group = parts - while !ss.eos? - part = ss.scan(@split_regex) - case part[0] - when ?*, ?: - type = part.slice!(0).chr.to_sym - current_group << Usher::Route::Variable.new(type, part, requirements && requirements[part.to_sym]) - when ?{ - pattern = '' - count = 1 - variable = ss.scan(/[:\*]([^,]+),/) - until count.zero? - regex_part = ss.scan(/\{|\}|[^\{\}]+/) - case regex_part[0] - when ?{ - count += 1 - when ?} - count -= 1 - end - pattern << regex_part - end - pattern.slice!(pattern.length - 1) - regex = Regexp.new(pattern) - if variable - variable_type = variable.slice!(0).chr.to_sym - variable_name = variable[0, variable.size - 1].to_sym - current_group << Usher::Route::Variable.new(variable_type, variable_name, requirements && requirements[variable_name], regex) - else - current_group << regex - end - when ?( - new_group = Group.new(:any, current_group) - current_group << new_group - current_group = new_group - when ?) - current_group = current_group.parent.type == :one ? current_group.parent.parent : current_group.parent - when ?| - unless current_group.parent.type == :one - detached_group = current_group.parent.pop - new_group = Group.new(:one, detached_group.parent) - detached_group.parent = new_group - detached_group.type = :all - new_group << detached_group - new_group.parent << new_group - end - current_group.parent << Group.new(:all, current_group.parent) - current_group = current_group.parent.last - else - current_group << part - end - end unless !path || path.empty? - paths = calc_paths(parts) - paths.each do |path| - path.each_with_index do |part, index| - if part.is_a?(Usher::Route::Variable) - part.default_value = default_values[part.name] if default_values - - case part.type - when :* - part.look_ahead = path[index + 1, path.size].find{|p| !p.is_a?(Usher::Route::Variable) && !@delimiter_chars.include?(p[0])} || nil - when :':' - part.look_ahead = path[index + 1, path.size].find{|p| @delimiter_chars.include?(p[0])} || @delimiters.first - end - end - end - end - paths - end - - private - - def cartesian_product!(lval, rval) - product = [] - (lval.size * rval.size).times do |index| - val = [] - val.push(*lval[index % lval.size]) - val.push(*rval[index % rval.size]) - product << val - end - lval.replace(product) - end - - def calc_paths(parts) - if parts.is_a?(Group) - paths = [[]] - case parts.type - when :all - parts.each do |p| - cartesian_product!(paths, calc_paths(p)) - end - when :any - parts.each do |p| - cartesian_product!(paths, calc_paths(p)) - end - paths.unshift([]) - when :one - cartesian_product!(paths, parts.collect do |p| - calc_paths(p) - end) - end - paths.each{|p| p.compact!; p.flatten! } - paths - else - [[parts]] - end - - end - end - - class Group < Array - attr_accessor :type - attr_accessor :parent - - def inspect - "#{type}->#{super}" - end - - def initialize(type, parent) - @type = type - @parent = parent end end end end \ No newline at end of file