package filepath
import "os"
const (
Separator = os.PathSeparator
ListSeparator = os.PathListSeparator
)
type lazybuf struct {
path string
buf []byte
w int
}
func (b *lazybuf) index(i int) byte {
if b.buf != nil {
return b.buf[i]
}
return b.path[i]
}
func (b *lazybuf) append(c byte) {
if b.buf == nil {
if b.w < len(b.path) && b.path[b.w] == c {
b.w++
return
}
b.buf = make([]byte, len(b.path))
copy(b.buf, b.path[:b.w])
}
b.buf[b.w] = c
b.w++
}
func (b *lazybuf) string() string {
if b.buf == nil {
return b.path[:b.w]
}
return string(b.buf[:b.w])
}
func Clean(path string) string {
if path == "" {
return "."
}
rooted := os.IsPathSeparator(path[0])
pathLen := len(path)
out := lazybuf{path: path}
r, dotdot := 0, 0
if rooted {
out.append(Separator)
r, dotdot = 1, 1
}
for r < pathLen {
switch {
case os.IsPathSeparator(path[r]):
r++
case path[r] == '.' && (r+1 == pathLen || os.IsPathSeparator(path[r+1])):
r++
case path[r] == '.' && path[r+1] == '.' && (r+2 == pathLen || os.IsPathSeparator(path[r+2])):
r = r + 2
switch {
case out.w > dotdot:
out.w--
for out.w > dotdot && !os.IsPathSeparator(out.index(out.w)) {
out.w--
}
case !rooted:
if out.w > 0 {
out.append(Separator)
}
out.append('.')
out.append('.')
dotdot = out.w
}
default:
if rooted && out.w != 1 || !rooted && out.w != 0 {
out.append(Separator)
}
for ; r < pathLen && !os.IsPathSeparator(path[r]); r++ {
out.append(path[r])
}
}
}
if out.w == 0 {
out.append('.')
}
return out.string()
}
样例源码:github.com/morganxf/ex…