Match() uses 'matchString()' and 'matchWildcards()' and now works as expected
This commit is contained in:
parent
d6a9411bb1
commit
c6112c9c74
|
@ -1,6 +1,7 @@
|
||||||
package parser
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -100,4 +101,115 @@ func (s Scheme) optimise() (Scheme, error) {
|
||||||
|
|
||||||
return rshift, nil
|
return rshift, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// matchString checks the STRING matchers from an URI
|
||||||
|
// it returns a boolean : false when not matching, true eitherway
|
||||||
|
// it returns a cleared uri, without STRING data
|
||||||
|
func (s Scheme) matchString(uri string) (string, bool) {
|
||||||
|
|
||||||
|
/* (1) Initialise variables */
|
||||||
|
clr := uri // contains cleared input string
|
||||||
|
minOff := 0 // minimum offset
|
||||||
|
|
||||||
|
/* (2) Iterate over strings */
|
||||||
|
for _, m := range s {
|
||||||
|
|
||||||
|
|
||||||
|
ls := len(m.pat)
|
||||||
|
|
||||||
|
// {1} If not STRING matcher -> ignore //
|
||||||
|
if ls == 0 { continue }
|
||||||
|
|
||||||
|
// {2} Get offset in URI (else -1) //
|
||||||
|
off := strings.Index(clr, m.pat)
|
||||||
|
if off < 0 { return "", false }
|
||||||
|
|
||||||
|
// {3} Fail on invalid offset range //
|
||||||
|
if off < minOff { return "", false }
|
||||||
|
|
||||||
|
// {4} Check for trailing '/' //
|
||||||
|
hasSlash := 0
|
||||||
|
if off+ls < len(clr) && clr[off+ls] == '/' {
|
||||||
|
hasSlash = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// {5} Remove the current string (+trailing slash) from the URI //
|
||||||
|
beg, end := clr[:off], clr[off+ls+hasSlash:]
|
||||||
|
clr = fmt.Sprintf("%s\a/%s", beg, end) // separate matches by '\a' character
|
||||||
|
|
||||||
|
// {6} Update offset range //
|
||||||
|
minOff = len(beg) + 2 - 1 // +2 slash separators
|
||||||
|
// -1 because strings begin with 1 slash already
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (3) If exists, remove trailing '/' */
|
||||||
|
if clr[len(clr)-1] == '/' {
|
||||||
|
clr = clr[:len(clr)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (4) If exists, remove trailing '\a' */
|
||||||
|
if clr[len(clr)-1] == '\a' {
|
||||||
|
clr = clr[:len(clr)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return clr, true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// matchWildcards check the WILCARDS (non-string) matchers from
|
||||||
|
// a cleared URI. it returns if the string matches
|
||||||
|
// + it sets the matchers buffers for later extraction
|
||||||
|
func (s Scheme) matchWildcards(clear string) bool {
|
||||||
|
|
||||||
|
/* (1) Extract wildcards (ref) */
|
||||||
|
wildcards := make(Scheme, 0, maxMatch)
|
||||||
|
|
||||||
|
for _, m := range s {
|
||||||
|
if len(m.pat) == 0 {
|
||||||
|
m.buf = nil // flush buffers
|
||||||
|
wildcards = append(wildcards, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (2) If no wildcards -> match */
|
||||||
|
if len(wildcards) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (3) Break uri by '\a' characters */
|
||||||
|
matches := strings.Split(clear, "\a")[1:]
|
||||||
|
|
||||||
|
/* (4) Iterate over matches */
|
||||||
|
for n, match := range matches {
|
||||||
|
|
||||||
|
// {1} If no more matcher //
|
||||||
|
if n >= len(wildcards) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// {2} Split by '/' //
|
||||||
|
data := strings.Split(match, "/")[1:] // from index 1 because it begins with '/'
|
||||||
|
|
||||||
|
// {3} If required and missing //
|
||||||
|
if wildcards[n].req && len(data) < 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// {4} If not multi but got multi //
|
||||||
|
if !wildcards[n].mul && len(data) > 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// {5} Store data into matcher //
|
||||||
|
wildcards[n].buf = data
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (5) Match */
|
||||||
|
return true
|
||||||
|
|
||||||
}
|
}
|
|
@ -47,94 +47,18 @@ func (s Scheme) Match(str string) bool {
|
||||||
/* (1) Nothing -> match all */
|
/* (1) Nothing -> match all */
|
||||||
if len(s) == 0 { return true }
|
if len(s) == 0 { return true }
|
||||||
|
|
||||||
/* (2) Init variables */
|
/* (2) Check for string match */
|
||||||
wc := make(Scheme, 0, maxMatch) // conrains wildcards
|
clearURI, match := s.matchString(str)
|
||||||
clr := str // contains cleared input string
|
if !match {
|
||||||
minOff := 0 // minimum offset
|
|
||||||
|
|
||||||
/* (3) Iterate over strings */
|
|
||||||
for _, m := range s {
|
|
||||||
|
|
||||||
ls := len(m.pat)
|
|
||||||
|
|
||||||
// if not string -> ignore
|
|
||||||
if ls == 0 {
|
|
||||||
wc = append(wc, m)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// get offset if contained, else -1
|
|
||||||
off := strings.Index(clr, m.pat)
|
|
||||||
if off < 0 { return false }
|
|
||||||
|
|
||||||
// if invalid offset range -> fail
|
|
||||||
if off < minOff { return false }
|
|
||||||
|
|
||||||
// check if trailing '/'
|
|
||||||
slash := 0
|
|
||||||
if off+ls < len(clr) && clr[off+ls] == '/' {
|
|
||||||
slash = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// exclude this string (+trailing slash if set)
|
|
||||||
// fmt.Printf("remove: '%s'\n", clr[off:off+ls+slash])
|
|
||||||
beg, end := clr[:off], clr[off+ls+slash:]
|
|
||||||
clr = fmt.Sprintf("%s//%s", beg, end)
|
|
||||||
// fmt.Printf("clr: '%s'\n", clr)
|
|
||||||
|
|
||||||
// update offset range
|
|
||||||
minOff = len(beg) + 2 - 1 // +2 slash separators
|
|
||||||
// -1 because strings begin with 1 slash already
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (4) If no wildcard -> match */
|
|
||||||
if len(wc) == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// flush wildcard buffers
|
|
||||||
for _, w := range wc { w.buf = nil }
|
|
||||||
|
|
||||||
/* (5) Break the clear string apart */
|
|
||||||
matches := strings.Split(clr, "//")[1:]
|
|
||||||
|
|
||||||
// fail if missing matches
|
|
||||||
if len(matches) < len(wc) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
nwc := 0
|
/* (3) Check for non-string match (wildcards) */
|
||||||
for _, m := range matches {
|
match = s.matchWildcards(clearURI)
|
||||||
|
if !match {
|
||||||
// ignore empty
|
return false
|
||||||
if len(m) == 0 { continue }
|
|
||||||
|
|
||||||
// no matcher for this match
|
|
||||||
if nwc >= len(wc){ return false }
|
|
||||||
|
|
||||||
// split by '/'
|
|
||||||
parts := strings.Split(m, "/")
|
|
||||||
|
|
||||||
// if required and missing -> does not match
|
|
||||||
if wc[nwc].req && len(parts) < 1 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// if not multi but multi -> does not match
|
|
||||||
if !wc[nwc].mul && len(parts) > 1 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// store into wilcard matcher
|
|
||||||
wc[nwc].buf = parts
|
|
||||||
|
|
||||||
// increment wildcard count
|
|
||||||
nwc++
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue