lgierth-rack-mount 0.6.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +36 -0
  3. data/lib/rack/mount.rb +32 -0
  4. data/lib/rack/mount/analysis/frequency.rb +60 -0
  5. data/lib/rack/mount/analysis/histogram.rb +74 -0
  6. data/lib/rack/mount/analysis/splitting.rb +159 -0
  7. data/lib/rack/mount/code_generation.rb +117 -0
  8. data/lib/rack/mount/generatable_regexp.rb +210 -0
  9. data/lib/rack/mount/multimap.rb +53 -0
  10. data/lib/rack/mount/prefix.rb +36 -0
  11. data/lib/rack/mount/regexp_with_named_groups.rb +69 -0
  12. data/lib/rack/mount/route.rb +130 -0
  13. data/lib/rack/mount/route_set.rb +420 -0
  14. data/lib/rack/mount/strexp.rb +68 -0
  15. data/lib/rack/mount/strexp/parser.rb +160 -0
  16. data/lib/rack/mount/strexp/parser.y +34 -0
  17. data/lib/rack/mount/strexp/tokenizer.rb +83 -0
  18. data/lib/rack/mount/strexp/tokenizer.rex +12 -0
  19. data/lib/rack/mount/utils.rb +162 -0
  20. data/lib/rack/mount/vendor/multimap/multimap.rb +569 -0
  21. data/lib/rack/mount/vendor/multimap/multiset.rb +185 -0
  22. data/lib/rack/mount/vendor/multimap/nested_multimap.rb +158 -0
  23. data/lib/rack/mount/vendor/regin/regin.rb +75 -0
  24. data/lib/rack/mount/vendor/regin/regin/alternation.rb +40 -0
  25. data/lib/rack/mount/vendor/regin/regin/anchor.rb +4 -0
  26. data/lib/rack/mount/vendor/regin/regin/atom.rb +54 -0
  27. data/lib/rack/mount/vendor/regin/regin/character.rb +51 -0
  28. data/lib/rack/mount/vendor/regin/regin/character_class.rb +50 -0
  29. data/lib/rack/mount/vendor/regin/regin/collection.rb +77 -0
  30. data/lib/rack/mount/vendor/regin/regin/expression.rb +126 -0
  31. data/lib/rack/mount/vendor/regin/regin/group.rb +85 -0
  32. data/lib/rack/mount/vendor/regin/regin/options.rb +55 -0
  33. data/lib/rack/mount/vendor/regin/regin/parser.rb +520 -0
  34. data/lib/rack/mount/vendor/regin/regin/tokenizer.rb +246 -0
  35. data/lib/rack/mount/vendor/regin/regin/version.rb +3 -0
  36. data/lib/rack/mount/version.rb +3 -0
  37. metadata +140 -0
@@ -0,0 +1,4 @@
1
+ module Regin
2
+ class Anchor < Atom
3
+ end
4
+ end
@@ -0,0 +1,54 @@
1
+ module Regin
2
+ class Atom
3
+ attr_reader :value, :ignorecase
4
+
5
+ def initialize(value, options = {})
6
+ @value = value
7
+ @ignorecase = options[:ignorecase]
8
+ end
9
+
10
+ def option_names
11
+ %w( ignorecase )
12
+ end
13
+
14
+ # Returns true if expression could be treated as a literal string.
15
+ def literal?
16
+ false
17
+ end
18
+
19
+ def casefold?
20
+ ignorecase ? true : false
21
+ end
22
+
23
+ def dup(options = {})
24
+ original_options = option_names.inject({}) do |h, m|
25
+ h[m.to_sym] = send(m)
26
+ h
27
+ end
28
+ self.class.new(value, original_options.merge(options))
29
+ end
30
+
31
+ def to_s(parent = false)
32
+ "#{value}"
33
+ end
34
+
35
+ def inspect #:nodoc:
36
+ "#<#{self.class.to_s.sub('Regin::', '')} #{to_s.inspect}>"
37
+ end
38
+
39
+ def ==(other) #:nodoc:
40
+ case other
41
+ when String
42
+ other == to_s
43
+ else
44
+ eql?(other)
45
+ end
46
+ end
47
+
48
+ def eql?(other) #:nodoc:
49
+ other.instance_of?(self.class) &&
50
+ self.value.eql?(other.value) &&
51
+ (!!self.ignorecase).eql?(!!other.ignorecase)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,51 @@
1
+ module Regin
2
+ class Character < Atom
3
+ attr_reader :quantifier
4
+
5
+ def initialize(value, options = {})
6
+ @quantifier = options[:quantifier]
7
+ super
8
+ end
9
+
10
+ def option_names
11
+ %w( quantifier ) + super
12
+ end
13
+
14
+ # Returns true if expression could be treated as a literal string.
15
+ #
16
+ # A Character is literal is there is no quantifier attached to it.
17
+ def literal?
18
+ quantifier.nil? && !ignorecase
19
+ end
20
+
21
+ def to_s(parent = false)
22
+ if !parent && ignorecase
23
+ "(?i-mx:#{value})#{quantifier}"
24
+ else
25
+ "#{value}#{quantifier}"
26
+ end
27
+ end
28
+
29
+ def to_regexp(anchored = false)
30
+ re = to_s(true)
31
+ re = "\\A#{re}\\Z" if anchored
32
+ Regexp.compile(re, ignorecase)
33
+ end
34
+
35
+ def match(char)
36
+ to_regexp(true).match(char)
37
+ end
38
+
39
+ def include?(char)
40
+ if ignorecase
41
+ value.downcase == char.downcase
42
+ else
43
+ value == char
44
+ end
45
+ end
46
+
47
+ def eql?(other) #:nodoc:
48
+ super && quantifier.eql?(other.quantifier)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,50 @@
1
+ module Regin
2
+ class CharacterClass < Character
3
+ def initialize(value, options = {})
4
+ @negate = options[:negate]
5
+ super
6
+ end
7
+
8
+ def option_names
9
+ %w( negate ) + super
10
+ end
11
+
12
+ attr_reader :negate
13
+
14
+ def negated?
15
+ negate ? true : false
16
+ end
17
+
18
+ # Returns true if expression could be treated as a literal string.
19
+ #
20
+ # A CharacterClass is never literal.
21
+ def literal?
22
+ false
23
+ end
24
+
25
+ def bracketed?
26
+ value != '.' && value !~ /^\\[dDsSwW]$/
27
+ end
28
+
29
+ def to_s(parent = false)
30
+ if bracketed?
31
+ if !parent && ignorecase
32
+ "(?i-mx:[#{negate && '^'}#{value}])#{quantifier}"
33
+ else
34
+ "[#{negate && '^'}#{value}]#{quantifier}"
35
+ end
36
+ else
37
+ super
38
+ end
39
+ end
40
+
41
+ def include?(char)
42
+ re = quantifier ? to_s.sub(/#{Regexp.escape(quantifier)}$/, '') : to_s
43
+ Regexp.compile("\\A#{re}\\Z").match(char)
44
+ end
45
+
46
+ def eql?(other) #:nodoc:
47
+ super && negate == other.negate
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,77 @@
1
+ module Regin
2
+ class Collection
3
+ include Enumerable
4
+
5
+ def initialize(*args)
6
+ @array = Array.new(*args)
7
+ end
8
+
9
+ def each
10
+ @array.each{ |item| yield item }
11
+ end
12
+
13
+ def [](i)
14
+ @array[i]
15
+ end
16
+
17
+ def length
18
+ @array.length
19
+ end
20
+ alias_method :size, :length
21
+
22
+ def first
23
+ @array.first
24
+ end
25
+
26
+ def last
27
+ @array.last
28
+ end
29
+
30
+ def +(other)
31
+ ary = other.is_a?(self.class) ? other.internal_array : other
32
+ self.class.new(@array + ary)
33
+ end
34
+
35
+ def to_regexp(anchored = false)
36
+ re = to_s(true)
37
+ re = "\\A#{re}\\Z" if anchored
38
+ Regexp.compile(re, flags)
39
+ end
40
+
41
+ def match(char)
42
+ to_regexp.match(char)
43
+ end
44
+
45
+ def include?(char)
46
+ any? { |e| e.include?(char) }
47
+ end
48
+
49
+ def ==(other) #:nodoc:
50
+ case other
51
+ when String
52
+ other == to_s
53
+ when Array
54
+ other == @array
55
+ else
56
+ eql?(other)
57
+ end
58
+ end
59
+
60
+ def eql?(other) #:nodoc:
61
+ other.instance_of?(self.class) && @array.eql?(other.internal_array)
62
+ end
63
+
64
+ protected
65
+ def internal_array #:nodoc:
66
+ @array
67
+ end
68
+
69
+ def extract_options(args)
70
+ if args.last.is_a?(Hash)
71
+ return args[0..-2], args.last
72
+ else
73
+ return args, {}
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,126 @@
1
+ module Regin
2
+ class Expression < Collection
3
+ attr_reader :ignorecase, :multiline, :extended
4
+
5
+ def initialize(*args)
6
+ args, options = extract_options(args)
7
+
8
+ @multiline = @ignorecase = @extended = nil
9
+
10
+ if args.length == 1 && args.first.instance_of?(Array)
11
+ super(args.first)
12
+ else
13
+ args = args.map { |e| e.instance_of?(String) ? Character.new(e) : e }
14
+ super(args)
15
+ end
16
+
17
+ self.multiline = options[:multiline] if options.key?(:multiline)
18
+ self.ignorecase = options[:ignorecase] if options.key?(:ignorecase)
19
+ self.extended = options[:extended] if options.key?(:extended)
20
+ end
21
+
22
+ # Returns true if expression could be treated as a literal string.
23
+ #
24
+ # A Expression is literal if all its elements are literal.
25
+ def literal?
26
+ !ignorecase && all? { |e| e.literal? }
27
+ end
28
+
29
+ def anchored?
30
+ anchored_to_start? && anchored_to_end?
31
+ end
32
+
33
+ def anchored_to_start?
34
+ first.is_a?(Anchor) && first == '\A'
35
+ end
36
+
37
+ def anchored_to_end?
38
+ last.is_a?(Anchor) && last == '\Z'
39
+ end
40
+
41
+ def anchored_to_line?
42
+ anchored_to_start_of_line? && anchored_to_end_of_line?
43
+ end
44
+
45
+ def anchored_to_start_of_line?
46
+ anchored_to_start? || (first.is_a?(Anchor) && first == '^')
47
+ end
48
+
49
+ def anchored_to_end_of_line?
50
+ anchored_to_end? || (last.is_a?(Anchor) && last == '$')
51
+ end
52
+
53
+ def options?
54
+ options.any?(true)
55
+ end
56
+
57
+ def flags
58
+ options.to_i
59
+ end
60
+
61
+ def +(other)
62
+ ary = other.is_a?(self.class) ? other.internal_array : other
63
+ ary = @array + ary + [options.to_h(true)]
64
+ self.class.new(*ary)
65
+ end
66
+
67
+ def dup(options = {})
68
+ expression = super()
69
+ expression.multiline = options[:multiline] if options.key?(:multiline)
70
+ expression.ignorecase = options[:ignorecase] if options.key?(:ignorecase)
71
+ expression.extended = options[:extended] if options.key?(:extended)
72
+ expression
73
+ end
74
+
75
+ def to_s(parent = false)
76
+ if parent || !options?
77
+ map { |e| e.to_s(parent) }.join
78
+ else
79
+ with, without = [], []
80
+ multiline ? (with << 'm') : (without << 'm')
81
+ ignorecase ? (with << 'i') : (without << 'i')
82
+ extended ? (with << 'x') : (without << 'x')
83
+
84
+ with = with.join
85
+ without = without.any? ? "-#{without.join}" : ''
86
+
87
+ "(?#{with}#{without}:#{map { |e| e.to_s(true) }.join})"
88
+ end
89
+ end
90
+
91
+ def inspect #:nodoc:
92
+ "#<Expression #{to_s.inspect}>"
93
+ end
94
+
95
+ def casefold?
96
+ ignorecase
97
+ end
98
+
99
+ def eql?(other) #:nodoc:
100
+ super &&
101
+ !!self.multiline == !!other.multiline &&
102
+ !!self.ignorecase == !!other.ignorecase &&
103
+ !!self.extended == !!other.extended
104
+ end
105
+
106
+ protected
107
+ def options
108
+ Options.new(multiline, ignorecase, extended)
109
+ end
110
+
111
+ def multiline=(multiline)
112
+ @multiline = multiline
113
+ end
114
+
115
+ def ignorecase=(ignorecase)
116
+ if @ignorecase.nil?
117
+ @array.map! { |e| e.dup(:ignorecase => ignorecase) }
118
+ @ignorecase = ignorecase
119
+ end
120
+ end
121
+
122
+ def extended=(extended)
123
+ @extended = extended
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,85 @@
1
+ module Regin
2
+ class Group
3
+ attr_reader :expression, :quantifier, :capture, :index, :name
4
+
5
+ def initialize(expression, options = {})
6
+ @quantifier = @index = @name = nil
7
+ @capture = true
8
+ @expression = expression.dup(options)
9
+
10
+ @quantifier = options[:quantifier] if options.key?(:quantifier)
11
+ @capture = options[:capture] if options.key?(:capture)
12
+ @index = options[:index] if options.key?(:index)
13
+ @name = options[:name] if options.key?(:name)
14
+ end
15
+
16
+ def option_names
17
+ %w( quantifier capture index name )
18
+ end
19
+
20
+ # Returns true if expression could be treated as a literal string.
21
+ #
22
+ # A Group is literal if its expression is literal and it has no quantifier.
23
+ def literal?
24
+ quantifier.nil? && expression.literal?
25
+ end
26
+
27
+ def to_s(parent = false)
28
+ if !expression.options?
29
+ "(#{capture ? '' : '?:'}#{expression.to_s(parent)})#{quantifier}"
30
+ elsif capture == false
31
+ "#{expression.to_s}#{quantifier}"
32
+ else
33
+ "(#{expression.to_s})#{quantifier}"
34
+ end
35
+ end
36
+
37
+ def to_regexp(anchored = false)
38
+ re = to_s
39
+ re = "\\A#{re}\\Z" if anchored
40
+ Regexp.compile(re)
41
+ end
42
+
43
+ def dup(options = {})
44
+ original_options = option_names.inject({}) do |h, m|
45
+ h[m.to_sym] = send(m)
46
+ h
47
+ end
48
+ self.class.new(expression, original_options.merge(options))
49
+ end
50
+
51
+ def inspect #:nodoc:
52
+ to_s.inspect
53
+ end
54
+
55
+ def match(char)
56
+ to_regexp.match(char)
57
+ end
58
+
59
+ def include?(char)
60
+ expression.include?(char)
61
+ end
62
+
63
+ def capture?
64
+ capture
65
+ end
66
+
67
+ def ==(other) #:nodoc:
68
+ case other
69
+ when String
70
+ other == to_s
71
+ else
72
+ eql?(other)
73
+ end
74
+ end
75
+
76
+ def eql?(other) #:nodoc:
77
+ other.is_a?(self.class) &&
78
+ self.expression == other.expression &&
79
+ self.quantifier == other.quantifier &&
80
+ self.capture == other.capture &&
81
+ self.index == other.index &&
82
+ self.name == other.name
83
+ end
84
+ end
85
+ end