lgierth-rack-mount 0.6.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,160 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.6
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+ require 'rack/mount/utils'
10
+ require 'rack/mount/strexp/tokenizer'
11
+
12
+ module Rack
13
+ module Mount
14
+ class StrexpParser < Racc::Parser
15
+
16
+
17
+ if Regin.regexp_supports_named_captures?
18
+ REGEXP_NAMED_CAPTURE = '(?<%s>%s)'.freeze
19
+ else
20
+ REGEXP_NAMED_CAPTURE = '(?:<%s>%s)'.freeze
21
+ end
22
+
23
+ attr_accessor :anchor, :requirements
24
+ ##### State transition tables begin ###
25
+
26
+ racc_action_table = [
27
+ 1, 2, 3, 9, 4, 1, 2, 3, 12, 4,
28
+ 1, 2, 3, 11, 4, 1, 2, 3, nil, 4 ]
29
+
30
+ racc_action_check = [
31
+ 0, 0, 0, 5, 0, 3, 3, 3, 9, 3,
32
+ 8, 8, 8, 8, 8, 6, 6, 6, nil, 6 ]
33
+
34
+ racc_action_pointer = [
35
+ -2, nil, nil, 3, nil, 3, 13, nil, 8, 8,
36
+ nil, nil, nil ]
37
+
38
+ racc_action_default = [
39
+ -8, -4, -5, -8, -7, -8, -1, -3, -8, -8,
40
+ -2, -6, 13 ]
41
+
42
+ racc_goto_table = [
43
+ 6, 5, 10, 8, 10 ]
44
+
45
+ racc_goto_check = [
46
+ 2, 1, 3, 2, 3 ]
47
+
48
+ racc_goto_pointer = [
49
+ nil, 1, 0, -4 ]
50
+
51
+ racc_goto_default = [
52
+ nil, nil, nil, 7 ]
53
+
54
+ racc_reduce_table = [
55
+ 0, 0, :racc_error,
56
+ 1, 8, :_reduce_1,
57
+ 2, 9, :_reduce_2,
58
+ 1, 9, :_reduce_none,
59
+ 1, 10, :_reduce_4,
60
+ 1, 10, :_reduce_5,
61
+ 3, 10, :_reduce_6,
62
+ 1, 10, :_reduce_7 ]
63
+
64
+ racc_reduce_n = 8
65
+
66
+ racc_shift_n = 13
67
+
68
+ racc_token_table = {
69
+ false => 0,
70
+ :error => 1,
71
+ :PARAM => 2,
72
+ :GLOB => 3,
73
+ :LPAREN => 4,
74
+ :RPAREN => 5,
75
+ :CHAR => 6 }
76
+
77
+ racc_nt_base = 7
78
+
79
+ racc_use_result_var = true
80
+
81
+ Racc_arg = [
82
+ racc_action_table,
83
+ racc_action_check,
84
+ racc_action_default,
85
+ racc_action_pointer,
86
+ racc_goto_table,
87
+ racc_goto_check,
88
+ racc_goto_default,
89
+ racc_goto_pointer,
90
+ racc_nt_base,
91
+ racc_reduce_table,
92
+ racc_token_table,
93
+ racc_shift_n,
94
+ racc_reduce_n,
95
+ racc_use_result_var ]
96
+
97
+ Racc_token_to_s_table = [
98
+ "$end",
99
+ "error",
100
+ "PARAM",
101
+ "GLOB",
102
+ "LPAREN",
103
+ "RPAREN",
104
+ "CHAR",
105
+ "$start",
106
+ "target",
107
+ "expr",
108
+ "token" ]
109
+
110
+ Racc_debug_parser = false
111
+
112
+ ##### State transition tables end #####
113
+
114
+ # reduce 0 omitted
115
+
116
+ def _reduce_1(val, _values, result)
117
+ result = anchor ? "\\A#{val.join}\\Z" : "\\A#{val.join}"
118
+ result
119
+ end
120
+
121
+ def _reduce_2(val, _values, result)
122
+ result = val.join
123
+ result
124
+ end
125
+
126
+ # reduce 3 omitted
127
+
128
+ def _reduce_4(val, _values, result)
129
+ name = val[0].to_sym
130
+ requirement = requirements[name]
131
+ result = REGEXP_NAMED_CAPTURE % [name, requirement]
132
+
133
+ result
134
+ end
135
+
136
+ def _reduce_5(val, _values, result)
137
+ name = val[0].to_sym
138
+ requirement = requirements[name]
139
+ result = REGEXP_NAMED_CAPTURE % [name, '.+' || requirement]
140
+
141
+ result
142
+ end
143
+
144
+ def _reduce_6(val, _values, result)
145
+ result = "(?:#{val[1]})?"
146
+ result
147
+ end
148
+
149
+ def _reduce_7(val, _values, result)
150
+ result = Regexp.escape(val[0])
151
+ result
152
+ end
153
+
154
+ def _reduce_none(val, _values, result)
155
+ val[0]
156
+ end
157
+
158
+ end # class StrexpParser
159
+ end # module Mount
160
+ end # module Rack
@@ -0,0 +1,34 @@
1
+ class Rack::Mount::StrexpParser
2
+ rule
3
+ target: expr { result = anchor ? "\\A#{val.join}\\Z" : "\\A#{val.join}" }
4
+
5
+ expr: expr token { result = val.join }
6
+ | token
7
+
8
+ token: PARAM {
9
+ name = val[0].to_sym
10
+ requirement = requirements[name]
11
+ result = REGEXP_NAMED_CAPTURE % [name, requirement]
12
+ }
13
+ | GLOB {
14
+ name = val[0].to_sym
15
+ requirement = requirements[name]
16
+ result = REGEXP_NAMED_CAPTURE % [name, '.+' || requirement]
17
+ }
18
+ | LPAREN expr RPAREN { result = "(?:#{val[1]})?" }
19
+ | CHAR { result = Regexp.escape(val[0]) }
20
+ end
21
+
22
+ ---- header ----
23
+ require 'rack/mount/utils'
24
+ require 'rack/mount/strexp/tokenizer'
25
+
26
+ ---- inner
27
+
28
+ if Regin.regexp_supports_named_captures?
29
+ REGEXP_NAMED_CAPTURE = '(?<%s>%s)'.freeze
30
+ else
31
+ REGEXP_NAMED_CAPTURE = '(?:<%s>%s)'.freeze
32
+ end
33
+
34
+ attr_accessor :anchor, :requirements
@@ -0,0 +1,83 @@
1
+ #--
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by rex 1.0.5.beta1
4
+ # from lexical definition file "lib/rack/mount/strexp/tokenizer.rex".
5
+ #++
6
+
7
+ require 'racc/parser'
8
+ class Rack::Mount::StrexpParser < Racc::Parser
9
+ require 'strscan'
10
+
11
+ class ScanError < StandardError ; end
12
+
13
+ attr_reader :lineno
14
+ attr_reader :filename
15
+ attr_accessor :state
16
+
17
+ def scan_setup(str)
18
+ @ss = StringScanner.new(str)
19
+ @lineno = 1
20
+ @state = nil
21
+ end
22
+
23
+ def action
24
+ yield
25
+ end
26
+
27
+ def scan_str(str)
28
+ scan_setup(str)
29
+ do_parse
30
+ end
31
+ alias :scan :scan_str
32
+
33
+ def load_file( filename )
34
+ @filename = filename
35
+ open(filename, "r") do |f|
36
+ scan_setup(f.read)
37
+ end
38
+ end
39
+
40
+ def scan_file( filename )
41
+ load_file(filename)
42
+ do_parse
43
+ end
44
+
45
+
46
+ def next_token
47
+ return if @ss.eos?
48
+
49
+ text = @ss.peek(1)
50
+ @lineno += 1 if text == "\n"
51
+ token = case @state
52
+ when nil
53
+ case
54
+ when (text = @ss.scan(/\\(\(|\)|:|\*)/))
55
+ action { [:CHAR, @ss[1]] }
56
+
57
+ when (text = @ss.scan(/\:([a-zA-Z_]\w*)/))
58
+ action { [:PARAM, @ss[1]] }
59
+
60
+ when (text = @ss.scan(/\*([a-zA-Z_]\w*)/))
61
+ action { [:GLOB, @ss[1]] }
62
+
63
+ when (text = @ss.scan(/\(/))
64
+ action { [:LPAREN, text] }
65
+
66
+ when (text = @ss.scan(/\)/))
67
+ action { [:RPAREN, text] }
68
+
69
+ when (text = @ss.scan(/./))
70
+ action { [:CHAR, text] }
71
+
72
+ else
73
+ text = @ss.string[@ss.pos .. -1]
74
+ raise ScanError, "can not match: '" + text + "'"
75
+ end # if
76
+
77
+ else
78
+ raise ScanError, "undefined state: '" + state.to_s + "'"
79
+ end # case state
80
+ token
81
+ end # def next_token
82
+
83
+ end # class
@@ -0,0 +1,12 @@
1
+ class Rack::Mount::StrexpParser
2
+ macro
3
+ RESERVED \(|\)|:|\*
4
+ ALPHA_U [a-zA-Z_]
5
+ rule
6
+ \\({RESERVED}) { [:CHAR, @ss[1]] }
7
+ \:({ALPHA_U}\w*) { [:PARAM, @ss[1]] }
8
+ \*({ALPHA_U}\w*) { [:GLOB, @ss[1]] }
9
+ \( { [:LPAREN, text] }
10
+ \) { [:RPAREN, text] }
11
+ . { [:CHAR, text] }
12
+ end
@@ -0,0 +1,162 @@
1
+ begin
2
+ require 'regin'
3
+ rescue LoadError
4
+ $: << File.expand_path(File.join(File.dirname(__FILE__), 'vendor/regin'))
5
+ require 'regin'
6
+ end
7
+
8
+ require 'uri'
9
+
10
+ module Rack::Mount
11
+ # Private utility methods used throughout Rack::Mount.
12
+ #--
13
+ # This module is a trash can. Try to move these functions into
14
+ # more appropriate contexts.
15
+ #++
16
+ module Utils
17
+ def silence_debug
18
+ old_debug, $DEBUG = $DEBUG, nil
19
+ yield
20
+ ensure
21
+ $DEBUG = old_debug
22
+ end
23
+ module_function :silence_debug
24
+
25
+ def debug(msg)
26
+ warn "Rack::Mount #{msg}" if $DEBUG
27
+ end
28
+ module_function :debug
29
+
30
+ # Normalizes URI path.
31
+ #
32
+ # Strips off trailing slash and ensures there is a leading slash.
33
+ #
34
+ # normalize_path("/foo") # => "/foo"
35
+ # normalize_path("/foo/") # => "/foo"
36
+ # normalize_path("foo") # => "/foo"
37
+ # normalize_path("") # => "/"
38
+ def normalize_path(path)
39
+ path = "/#{path}"
40
+ path.squeeze!('/')
41
+ path.sub!(%r{/+\Z}, '')
42
+ path = '/' if path == ''
43
+ path
44
+ end
45
+ module_function :normalize_path
46
+
47
+ # Removes trailing nils from array.
48
+ #
49
+ # pop_trailing_blanks!([1, 2, 3]) # => [1, 2, 3]
50
+ # pop_trailing_blanks!([1, 2, 3, nil, ""]) # => [1, 2, 3]
51
+ # pop_trailing_blanks!([nil]) # => []
52
+ # pop_trailing_blanks!([""]) # => []
53
+ def pop_trailing_blanks!(ary)
54
+ while ary.length > 0 && (ary.last.nil? || ary.last == '')
55
+ ary.pop
56
+ end
57
+ ary
58
+ end
59
+ module_function :pop_trailing_blanks!
60
+
61
+ RESERVED_PCHAR = ':@&=+$,;%'
62
+ SAFE_PCHAR = "#{URI::REGEXP::PATTERN::UNRESERVED}#{RESERVED_PCHAR}"
63
+ if RUBY_VERSION >= '1.9'
64
+ UNSAFE_PCHAR = Regexp.new("[^#{SAFE_PCHAR}]", false).freeze
65
+ else
66
+ UNSAFE_PCHAR = Regexp.new("[^#{SAFE_PCHAR}]", false, 'N').freeze
67
+ end
68
+
69
+ Parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI
70
+
71
+ def escape_uri(uri)
72
+ Parser.escape(uri.to_s, UNSAFE_PCHAR)
73
+ end
74
+ module_function :escape_uri
75
+
76
+ if ''.respond_to?(:force_encoding)
77
+ def unescape_uri(uri)
78
+ Parser.unescape(uri).force_encoding('utf-8')
79
+ end
80
+ else
81
+ def unescape_uri(uri)
82
+ URI.unescape(uri)
83
+ end
84
+ end
85
+ module_function :unescape_uri
86
+
87
+ # Taken from Rack 1.1.x to build nested query strings
88
+ def build_nested_query(value, prefix = nil) #:nodoc:
89
+ case value
90
+ when Array
91
+ value.map { |v|
92
+ build_nested_query(v, "#{prefix}[]")
93
+ }.join("&")
94
+ when Hash
95
+ value.map { |k, v|
96
+ build_nested_query(v, prefix ? "#{prefix}[#{Rack::Utils.escape(k)}]" : Rack::Utils.escape(k))
97
+ }.join("&")
98
+ when String
99
+ raise ArgumentError, "value must be a Hash" if prefix.nil?
100
+ "#{prefix}=#{Rack::Utils.escape(value)}"
101
+ else
102
+ prefix
103
+ end
104
+ end
105
+ module_function :build_nested_query
106
+
107
+ # Determines whether the regexp must match the entire string.
108
+ #
109
+ # regexp_anchored?(/^foo$/) # => true
110
+ # regexp_anchored?(/foo/) # => false
111
+ # regexp_anchored?(/^foo/) # => false
112
+ # regexp_anchored?(/foo$/) # => false
113
+ def regexp_anchored?(regexp)
114
+ regexp.source =~ /\A(\\A|\^).*(\\Z|\$)\Z/m ? true : false
115
+ end
116
+ module_function :regexp_anchored?
117
+
118
+ def normalize_extended_expression(regexp)
119
+ return regexp unless regexp.options & Regexp::EXTENDED != 0
120
+ source = regexp.source
121
+ source.gsub!(/#.+$/, '')
122
+ source.gsub!(/\s+/, '')
123
+ source.gsub!(/\\\//, '/')
124
+ Regexp.compile(source)
125
+ end
126
+ module_function :normalize_extended_expression
127
+
128
+ def parse_regexp(regexp)
129
+ cache = @@_parse_regexp_cache ||= {}
130
+
131
+ if expression = cache[regexp]
132
+ return expression
133
+ end
134
+
135
+ unless regexp.is_a?(RegexpWithNamedGroups)
136
+ regexp = RegexpWithNamedGroups.new(regexp)
137
+ end
138
+
139
+ expression = Regin.parse(regexp)
140
+
141
+ unless Regin.regexp_supports_named_captures?
142
+ tag_captures = Proc.new do |group|
143
+ case group
144
+ when Regin::Group
145
+ # TODO: dup instead of mutating
146
+ group.instance_variable_set('@name', regexp.names[group.index]) if group.index
147
+ tag_captures.call(group.expression)
148
+ when Regin::Expression
149
+ group.each { |child| tag_captures.call(child) }
150
+ end
151
+ end
152
+ tag_captures.call(expression)
153
+ end
154
+
155
+ cache[regexp] = expression.freeze
156
+ expression
157
+ rescue Racc::ParseError, Regin::Parser::ScanError
158
+ []
159
+ end
160
+ module_function :parse_regexp
161
+ end
162
+ end