2018-04-26 11:03:44 +00:00
|
|
|
package parser
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Build builds an URI scheme from a pattern string
|
2018-09-29 12:39:12 +00:00
|
|
|
func Build(s string) (*Scheme, error) {
|
2018-04-26 11:03:44 +00:00
|
|
|
|
2021-05-14 15:19:02 +00:00
|
|
|
// 1. Manage '/' at the start
|
2018-04-26 11:03:44 +00:00
|
|
|
if len(s) < 1 || s[0] != '/' {
|
|
|
|
return nil, fmt.Errorf("URI must begin with '/'")
|
|
|
|
}
|
|
|
|
|
2021-05-14 15:19:02 +00:00
|
|
|
// 2. Split by '/'
|
2018-04-26 11:03:44 +00:00
|
|
|
parts := strings.Split(s, "/")
|
|
|
|
|
2021-05-14 15:19:02 +00:00
|
|
|
// 3. Max exceeded
|
2018-04-26 11:03:44 +00:00
|
|
|
if len(parts)-2 > maxMatch {
|
|
|
|
for i, p := range parts {
|
2018-09-29 12:39:12 +00:00
|
|
|
fmt.Printf("%d: '%s'\n", i, p)
|
2018-04-26 11:03:44 +00:00
|
|
|
}
|
|
|
|
return nil, fmt.Errorf("URI must not exceed %d slash-separated components, got %d", maxMatch, len(parts))
|
|
|
|
}
|
|
|
|
|
2021-05-14 15:19:02 +00:00
|
|
|
// 4. Build for each part
|
2018-04-26 11:03:44 +00:00
|
|
|
sch, err := buildScheme(parts)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-05-14 15:19:02 +00:00
|
|
|
// 5. Optimise structure
|
2018-04-26 11:03:44 +00:00
|
|
|
opti, err := sch.optimise()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &opti, nil
|
|
|
|
|
2018-04-26 13:01:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Match returns if the given URI is matched by the scheme
|
|
|
|
func (s Scheme) Match(str string) bool {
|
|
|
|
|
2021-05-14 15:19:02 +00:00
|
|
|
// 1. Nothing -> match all
|
2018-09-29 12:39:12 +00:00
|
|
|
if len(s) == 0 {
|
|
|
|
return true
|
|
|
|
}
|
2018-04-26 13:01:18 +00:00
|
|
|
|
2021-05-14 15:19:02 +00:00
|
|
|
// 2. Check for string match
|
2018-04-26 20:15:09 +00:00
|
|
|
clearURI, match := s.matchString(str)
|
|
|
|
if !match {
|
2018-04-26 13:01:18 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2021-05-14 15:19:02 +00:00
|
|
|
// 3. Check for non-string match (wildcards)
|
2018-04-26 20:15:09 +00:00
|
|
|
match = s.matchWildcards(clearURI)
|
|
|
|
if !match {
|
|
|
|
return false
|
2018-04-26 13:01:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetMatch returns the indexed match (excluding string matchers)
|
|
|
|
func (s Scheme) GetMatch(n uint8) ([]string, error) {
|
|
|
|
|
2021-05-14 15:19:02 +00:00
|
|
|
// 1. Index out of range
|
2018-04-26 13:01:18 +00:00
|
|
|
if n > uint8(len(s)) {
|
|
|
|
return nil, fmt.Errorf("Index out of range")
|
|
|
|
}
|
|
|
|
|
2021-05-14 15:19:02 +00:00
|
|
|
// 2. Iterate to find index (exclude strings)
|
2018-04-26 13:01:18 +00:00
|
|
|
ni := -1
|
2018-04-26 21:39:10 +00:00
|
|
|
for _, m := range s {
|
2018-04-26 13:01:18 +00:00
|
|
|
|
|
|
|
// ignore strings
|
2018-09-29 12:39:12 +00:00
|
|
|
if len(m.pat) > 0 {
|
|
|
|
continue
|
|
|
|
}
|
2018-04-26 13:01:18 +00:00
|
|
|
|
|
|
|
// increment match counter : ni
|
|
|
|
ni++
|
|
|
|
|
|
|
|
// if expected index -> return matches
|
|
|
|
if uint8(ni) == n {
|
2018-04-26 21:39:10 +00:00
|
|
|
return m.buf, nil
|
2018-04-26 13:01:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-05-14 15:19:02 +00:00
|
|
|
// 3. If nothing found -> return empty set
|
2018-04-26 13:01:18 +00:00
|
|
|
return nil, fmt.Errorf("Index out of range (max: %d)", ni)
|
|
|
|
|
2018-04-26 21:39:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetAllMatch returns all the indexed match (excluding string matchers)
|
|
|
|
func (s Scheme) GetAllMatch() [][]string {
|
|
|
|
|
|
|
|
match := make([][]string, 0, len(s))
|
|
|
|
|
|
|
|
for _, m := range s {
|
|
|
|
|
|
|
|
// ignore strings
|
2018-09-29 12:39:12 +00:00
|
|
|
if len(m.pat) > 0 {
|
|
|
|
continue
|
|
|
|
}
|
2018-04-26 21:39:10 +00:00
|
|
|
|
|
|
|
match = append(match, m.buf)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return match
|
|
|
|
|
2018-09-29 12:39:12 +00:00
|
|
|
}
|