From d6a9411bb1df756920e23e29f27af0a6cf34181b Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Thu, 26 Apr 2018 15:01:18 +0200 Subject: [PATCH] Match() partially works (have to check for optional parameters) + GetMatch() works as well --- internal/uri/parser/public.go | 131 +++++++++++++++++++++++++++++++++- internal/uri/parser/types.go | 3 +- 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/internal/uri/parser/public.go b/internal/uri/parser/public.go index f857591..c16a352 100644 --- a/internal/uri/parser/public.go +++ b/internal/uri/parser/public.go @@ -30,7 +30,7 @@ func Build(s string) (*Scheme, error){ return nil, err } - /* (5) Optimise */ + /* (5) Optimise structure */ opti, err := sch.optimise() if err != nil { return nil, err @@ -38,4 +38,133 @@ func Build(s string) (*Scheme, error){ return &opti, nil +} + + +// Match returns if the given URI is matched by the scheme +func (s Scheme) Match(str string) bool { + + /* (1) Nothing -> match all */ + if len(s) == 0 { return true } + + /* (2) Init variables */ + wc := make(Scheme, 0, maxMatch) // conrains wildcards + clr := str // contains cleared input string + 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 + } + + nwc := 0 + for _, m := range matches { + + // ignore empty + 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 +} + + +// GetMatch returns the indexed match (excluding string matchers) +func (s Scheme) GetMatch(n uint8) ([]string, error) { + + /* (1) Index out of range */ + if n > uint8(len(s)) { + return nil, fmt.Errorf("Index out of range") + } + + /* (2) Iterate to find index (exclude strings) */ + ni := -1 + for i, l := 0, len(s) ; i < l ; i++ { + + // ignore strings + if len(s[i].pat) > 0 { continue } + + // increment match counter : ni + ni++ + + // if expected index -> return matches + if uint8(ni) == n { + return s[i].buf, nil + } + + } + + /* (3) If nothing found -> return empty set */ + return nil, fmt.Errorf("Index out of range (max: %d)", ni) + } \ No newline at end of file diff --git a/internal/uri/parser/types.go b/internal/uri/parser/types.go index 6b1c35c..987ba48 100644 --- a/internal/uri/parser/types.go +++ b/internal/uri/parser/types.go @@ -27,7 +27,8 @@ type matcher struct { pat string // pattern to match (empty if wildcard) req bool // whether it is required mul bool // whether multiple matches are allowed - buf []string // matched content + + buf []string // matched content (when matching) }