X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FWeb%2FSimple%2FDispatchParser.pm;h=1be1cf2092615b9a95e9d2f744e5f8301b5dd116;hb=9b9866ae3d62893fcba1b7c585a2d7358175d0c2;hp=1882c9812208a7c287b14e1d3caa7149247983e5;hpb=134d6c1fd8883248002ca24b699a11609703d5fa;p=catagits%2FWeb-Simple.git diff --git a/lib/Web/Simple/DispatchParser.pm b/lib/Web/Simple/DispatchParser.pm index 1882c98..1be1cf2 100644 --- a/lib/Web/Simple/DispatchParser.pm +++ b/lib/Web/Simple/DispatchParser.pm @@ -58,6 +58,35 @@ sub _parse_spec { } } +sub _parse_spec_combinator { + my ($self, $spec, $match) = @_; + for ($_[1]) { + + /\G\+/gc and + return $match; + + /\G\|/gc and + return do { + my @match = $match; + PARSE: { do { + push @match, $self->_parse_spec_section($_) + or $self->_blam("Unable to work out what the next section is"); + last PARSE if (pos == length); + last PARSE unless /\G\|/gc; # give up when next thing isn't | + } until (pos == length) }; # accept trailing whitespace + return sub { + foreach my $try (@match) { + if (my @ret = $try->(@_)) { + return @ret; + } + } + return; + }; + }; + } + return; +} + sub _parse_spec_section { my ($self) = @_; for ($_[1]) { @@ -92,37 +121,12 @@ sub _parse_spec_section { return; }; }; - } - return; # () will trigger the blam in our caller -} -sub _parse_spec_combinator { - my ($self, $spec, $match) = @_; - for ($_[1]) { - - /\G\+/gc and - return $match; - - /\G\|/gc and - return do { - my @match = $match; - PARSE: { do { - push @match, $self->_parse_spec_section($_) - or $self->_blam("Unable to work out what the next section is"); - last PARSE if (pos == length); - last PARSE unless /\G\|/gc; # give up when next thing isn't | - } until (pos == length) }; # accept trailing whitespace - return sub { - foreach my $try (@match) { - if (my @ret = $try->(@_)) { - return @ret; - } - } - return; - }; - }; + # ? + /\G\?/gc and + return $self->_parse_param_handler($_, 'query'); } - return; + return; # () will trigger the blam in our caller } sub _http_method_match { @@ -204,4 +208,76 @@ sub _url_extension_match { } } +sub _parse_param_handler { + my ($self, $spec, $type) = @_; + + require Web::Simple::ParamParser; + my $unpacker = Web::Simple::ParamParser->can("get_unpacked_${type}_from"); + + for ($_[1]) { + my (@required, @single, %multi, $star, $multistar) = @_; + PARAM: { do { + + # per param flag + + my $multi = 0; + + # ?@foo or ?@* + + /\G\@/gc and $multi = 1; + + # @* or * + + if (/\G\*/) { + + $multi ? ($multistar = 1) : ($star = 1); + } else { + + # @foo= or foo= or @foo~ or foo~ + + /\G(\w+)/gc or $self->_blam('Expected parameter name'); + + my $name = $1; + + # check for = or ~ on the end + + /\G\=/gc + ? push(@required, $name) + : (/\G\~/gc or $self->_blam('Expected = or ~ after parameter name')); + + # record the key in the right category depending on the multi (@) flag + + $multi ? (push @single, $name) : ($multi{$name} = 1); + } + } while (/\G\&/gc) } + + return sub { + my $raw = $unpacker->($_[0]); + foreach my $name (@required) { + return unless exists $raw->{$name}; + } + my %p; + foreach my $name ( + @single, + ($star + ? (grep { !exists $multi{$_} } keys %$raw) + : () + ) + ) { + $p{$name} = $raw->{$name}->[-1] if exists $raw->{$name}; + } + foreach my $name ( + keys %multi, + ($multistar + ? (grep { !exists $p{$_} } keys %$raw) + : () + ) + ) { + $p{$name} = $raw->{$name}||[]; + } + return ({}, \%p); + }; + } +} + 1;