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