// ConcatSlash concats strings and ensures ends with "/"
337702
func ConcatSlash(strs ...string) string {
	out := bytes.Buffer{}
	for _, s := range strs {
		if strings.HasSuffix(s, "/") {
			out.WriteString(s)
		} else {
			out.WriteString(s)
			out.WriteByte('/')
		}
	}

	return string(out.Bytes())
}
620845
func Abs(path string) string {
	var abs string
	cwd, _ := os.Getwd()

	if path == "" || path == "." {
		abs = cwd

	} else if path == ".." {
		abs = filepath.Join(cwd, path)

	} else if strings.HasPrefix(path, "~/") {
		abs = filepath.Join(UserDir(), path[2:])

	} else if strings.HasPrefix(path, "./") {
		abs = filepath.Join(cwd, path[2:])

	} else if strings.HasPrefix(path, "../") {
		abs = filepath.Join(cwd, "..", path[2:])

	} else {
		return path
	}
	return abs
}
347690
func parseCatSpec(s string) (*catSpec, error) {
	s = strings.TrimSpace(s)
	dbspec := strings.Index(s, "[")
	if dbspec < 0 {
		spec := &catSpec{Path: s}
		return spec, nil
	}
	if !strings.HasSuffix(s, "]") {
		return nil, fmt.Errorf("invalid db spec")
	}
	dbs := strings.Split(s[dbspec+1:len(s)-1], ":")
	spec := &catSpec{Path: s[:dbspec], DB: dbs}
	return spec, nil
}
914602
func IsCleanSlashPath(p string) bool {
	if p == "" {
		return false
	}
	if strings.ContainsRune(p, '\\') {
		return false
	}
	if p != path.Clean(p) {
		return false
	}
	if p[0] == '/' || p == ".." || strings.HasPrefix(p, "../") {
		return false
	}
	return true
}
996064
func stripLeaveSlash(prefix string, h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		p := strings.TrimPrefix(req.URL.Path, prefix)
		if len(p) >= len(req.URL.Path) {
			http.NotFound(w, req)
			return
		}
		if len(p) > 0 && p[:1] != "/" {
			p = "/" + p
		}
		req.URL.Path = p
		h.ServeHTTP(w, req)
	})
}
546490
func (c *Cons) ConsS(o interface{}) iseq.Seq {
	return &Cons{first: o, more: c}
}
482543
func (p *parser) parseEscape() (result string, err error) {
	if len(p.s) < p.i+2 || p.s[p.i] != '\\' {
		return "", errors.New("invalid escape sequence")
	}

	start := p.i + 1
	c := p.s[start]
	switch {
	case c == '\r' || c == '\n' || c == '\f':
		return "", errors.New("escaped line ending outside string")
	case hexDigit(c):
		// unicode escape (hex)
		var i int
		for i = start; i < p.i+6 && i < len(p.s) && hexDigit(p.s[i]); i++ {
			// empty
		}
		v, _ := strconv.ParseUint(p.s[start:i], 16, 21)
		if len(p.s) > i {
			switch p.s[i] {
			case '\r':
				i++
				if len(p.s) > i && p.s[i] == '\n' {
					i++
				}
			case ' ', '\t', '\n', '\f':
				i++
			}
		}
		p.i = i
		return string(rune(v)), nil
	}

	// Return the literal character after the backslash.
	result = p.s[start : start+1]
	p.i += 2
	return result, nil
}
823927
func compareSlashSeparated(a, b string) int {
	switch {
	case a == "" && b == "":
		return 0
	case a == "":
		return 1
	case b == "":
		return -1
	}

	sa := strings.SplitN(a, "/", 2)
	sb := strings.SplitN(b, "/", 2)
	if sa[0] < sb[0] {
		return -1
	}
	if sa[0] > sb[0] {
		return 1
	}

	getInt := func(suffix string) (bool, int) {
		num, err := strconv.Atoi(suffix)
		if err != nil {
			return false, 0
		}
		return true, num
	}

	naIsNumeric, na := getInt(sa[1])
	if !naIsNumeric {
		return compareStrings(sa[1], sb[1])
	}
	nbIsNumeric, nb := getInt(sb[1])
	if !nbIsNumeric {
		return compareStrings(sa[1], sb[1])
	}

	switch {
	case na < nb:
		return -1
	case na == nb:
		return 0
	}
	return 1
}
103300
func Concat(strs ...string) string {
	out := bytes.Buffer{}
	for i, s := range strs {
		if i == 0 {
			out.WriteString(s)
		} else if s != "" {
			out.WriteByte('/')
			out.WriteString(s)
		}
	}
	return string(out.Bytes())
}
1343240
func backslashEscape(s string, set []byte) string {
	var buf bytes.Buffer
	for _, b := range []byte(s) {
		if b == '\\' || bytes.IndexByte(set, b) != -1 {
			buf.WriteByte('\\')
		}
		buf.WriteByte(b)
	}
	return buf.String()
}
295439
func checkCatSyntax(ctx *cli.Context) {
	args := ctx.Args()
	if !args.Present() {
		args = []string{"-"}
	}
	for _, arg := range args {
		if strings.HasPrefix(arg, "-") && len(arg) > 1 {
			fatalIf(probe.NewError(errors.New("")), fmt.Sprintf("Unknown flag `%s` passed.", arg))
		}
	}
}
195378
func ConcatAuthKeys(a, b string) string {
	if a == "" {
		return b
	}
	if b == "" {
		return a
	}
	if a[len(a)-1] != '\n' {
		return a + "\n" + b
	}
	return a + b
}
307438
func checkIsHex(s string) error {
	switch {
	case s == "":
		return fmt.Errorf("empty hex string")
	case len(s)%2 != 0:
		return fmt.Errorf("uneven number of symbols in the hex string")
	}
	for _, c := range s {
		if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')) {
			return fmt.Errorf("bad lowercase hex string %q, wrong char %c", s, c)
		}
	}
	return nil
}
58085
func (sc *StringConstraint) RegexpString(pat string) *StringConstraint {
	return sc.Regexp(regexp.MustCompile(pat))
}
246466
func ensureNoLeadingSlash(s string) string {
	s = strings.TrimSpace(s)
	if s == "" {
		return ""
	}

	for len(s) > 0 && s[0] == '/' {
		s = s[1:]
	}
	return s
}
348052
func escapeStringBackslash(buf []byte, v string) []byte {
	pos := len(buf)
	buf = reserveBuffer(buf, len(v)*2)

	for i := 0; i < len(v); i++ {
		c := v[i]
		switch c {
		case '\x00':
			buf[pos] = '\\'
			buf[pos+1] = '0'
			pos += 2
		case '\n':
			buf[pos] = '\\'
			buf[pos+1] = 'n'
			pos += 2
		case '\r':
			buf[pos] = '\\'
			buf[pos+1] = 'r'
			pos += 2
		case '\x1a':
			buf[pos] = '\\'
			buf[pos+1] = 'Z'
			pos += 2
		case '\'':
			buf[pos] = '\\'
			buf[pos+1] = '\''
			pos += 2
		case '"':
			buf[pos] = '\\'
			buf[pos+1] = '"'
			pos += 2
		case '\\':
			buf[pos] = '\\'
			buf[pos+1] = '\\'
			pos += 2
		default:
			buf[pos] = c
			pos++
		}
	}

	return buf[:pos]
}
385561
func eqOrSlashedPrefix(s, prefix string) bool {
	if !strings.HasPrefix(s, prefix) {
		return false
	}

	prflen, pathlen := len(prefix), len(s)
	return prflen == pathlen || strings.Index(s[prflen:], "/") == 0
}