func ReadProperties(fname string) (map[string]string, error) { props := make(map[string]string) err := file.Filter(fname, func(_ int, line []byte) ([]byte, error) { p := pair.Parse(unsafe2.String(line), "=").Trim() if p.HasKey() { props[p.Key] = strings2.TrimAfter(p.Value, "#") } return line, nil }) return props, err }
// compile compile a url path to a clean path that replace all named variable // to _WILDCARD or _REMAINSALL and extract all variable names // if just want to match and don't need variable value, only use ':' or '*' // for ':', it will catch the single section of url path seperated by '/' // for '*', it will catch all remains url path, it should appear in the last // of pattern for variables behind it will all be ignored // // the query portion will be trimmed func compile(path string) (newPath string, vars map[string]int) { path = strings2.TrimAfter(path, "?") l := len(path) if path[0] != '/' { log.Panicln("Invalid pattern, must start with '/': " + path) } if l != 1 && path[l-1] == '/' { path = path[:l-1] } sections := strings.Split(path[1:], "/") new := make([]byte, 0, len(path)) varIndex := 0 for _, s := range sections { new = append(new, '/') last := len(s) i := last - 1 var c byte for ; i >= 0; i-- { if s[i] == _MATCH_WILDCARD { c = _WILDCARD } else if s[i] == _MATCH_REMAINSALL { c = _REMAINSALL } else { continue } if name := s[i+1:]; len(name) > 0 { if isInvalidSection(name) { log.Panicf("path %s has pre-defined characters %c or %c\n", path, _WILDCARD, _REMAINSALL) } if vars == nil { vars = make(map[string]int) } vars[name] = varIndex } varIndex++ last = i break } if last != 0 { new = append(new, []byte(s[:last])...) } if c != 0 { new = append(new, c) } } newPath = string(new) if vars == nil { vars = emptyVars } return }