]> Cypherpunks repositories - gostls13.git/commitdiff
path/filepath: avoid allocation in Clean of cleaned path even on windows (fix build)
authorAlex Brainman <alex.brainman@gmail.com>
Sat, 30 Jun 2012 12:08:53 +0000 (22:08 +1000)
committerAlex Brainman <alex.brainman@gmail.com>
Sat, 30 Jun 2012 12:08:53 +0000 (22:08 +1000)
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6344049

src/pkg/path/filepath/path.go
src/pkg/path/filepath/path_plan9.go
src/pkg/path/filepath/path_unix.go
src/pkg/path/filepath/path_windows.go

index 7b6a9bd5d286b6e55f11855fdc15fd7e1e751939..bb27f1c851a820e7ba38ad93a5041b64a89bbf79 100644 (file)
@@ -18,26 +18,28 @@ import (
 // and retrieving the final string. It does not allocate a buffer
 // to hold the output until that output diverges from s.
 type lazybuf struct {
-       s   string
-       buf []byte
-       w   int
+       path       string
+       buf        []byte
+       w          int
+       volAndPath string
+       volLen     int
 }
 
 func (b *lazybuf) index(i int) byte {
        if b.buf != nil {
                return b.buf[i]
        }
-       return b.s[i]
+       return b.path[i]
 }
 
 func (b *lazybuf) append(c byte) {
        if b.buf == nil {
-               if b.w < len(b.s) && b.s[b.w] == c {
+               if b.w < len(b.path) && b.path[b.w] == c {
                        b.w++
                        return
                }
-               b.buf = make([]byte, len(b.s))
-               copy(b.buf, b.s[:b.w])
+               b.buf = make([]byte, len(b.path))
+               copy(b.buf, b.path[:b.w])
        }
        b.buf[b.w] = c
        b.w++
@@ -45,9 +47,9 @@ func (b *lazybuf) append(c byte) {
 
 func (b *lazybuf) string() string {
        if b.buf == nil {
-               return b.s[:b.w]
+               return b.volAndPath[:b.volLen+b.w]
        }
-       return string(b.buf[:b.w])
+       return b.volAndPath[:b.volLen] + string(b.buf[:b.w])
 }
 
 const (
@@ -77,14 +79,15 @@ const (
 // Getting Dot-Dot Right,''
 // http://plan9.bell-labs.com/sys/doc/lexnames.html
 func Clean(path string) string {
-       vol := VolumeName(path)
-       path = path[len(vol):]
+       originalPath := path
+       volLen := volumeNameLen(path)
+       path = path[volLen:]
        if path == "" {
-               if len(vol) > 1 && vol[1] != ':' {
+               if volLen > 1 && originalPath[1] != ':' {
                        // should be UNC
-                       return FromSlash(vol)
+                       return FromSlash(originalPath)
                }
-               return vol + "."
+               return originalPath + "."
        }
        rooted := os.IsPathSeparator(path[0])
 
@@ -94,7 +97,7 @@ func Clean(path string) string {
        //      dotdot is index in buf where .. must stop, either because
        //              it is the leading slash or it is a leading ../../.. prefix.
        n := len(path)
-       out := lazybuf{s: path}
+       out := lazybuf{path: path, volAndPath: originalPath, volLen: volLen}
        r, dotdot := 0, 0
        if rooted {
                out.append(Separator)
@@ -146,7 +149,7 @@ func Clean(path string) string {
                out.append('.')
        }
 
-       return FromSlash(vol + out.string())
+       return FromSlash(out.string())
 }
 
 // ToSlash returns the result of replacing each separator character
@@ -448,3 +451,11 @@ func Dir(path string) string {
        }
        return vol + dir
 }
+
+// VolumeName returns leading volume name.  
+// Given "C:\foo\bar" it returns "C:" under windows.
+// Given "\\host\share\foo" it returns "\\host\share".
+// On other platforms it returns "".
+func VolumeName(path string) (v string) {
+       return path[:volumeNameLen(path)]
+}
index 59a5812dd0bad1c7acec33e2e0304b28e491a353..0c938d89da191fd4b66086aaac588a15848b5b59 100644 (file)
@@ -11,10 +11,10 @@ func IsAbs(path string) bool {
        return strings.HasPrefix(path, "/") || strings.HasPrefix(path, "#")
 }
 
-// VolumeName returns the leading volume name on Windows.
-// It returns "" elsewhere.
-func VolumeName(path string) string {
-       return ""
+// volumeNameLen returns length of the leading volume name on Windows.
+// It returns 0 elsewhere.
+func volumeNameLen(path string) int {
+       return 0
 }
 
 // HasPrefix exists for historical compatibility and should not be used.
index 305e307272f8b7a831f6291b0370d96d31a1c964..3b48d14e0831a936577e567a8600caa0502bca46 100644 (file)
@@ -13,10 +13,10 @@ func IsAbs(path string) bool {
        return strings.HasPrefix(path, "/")
 }
 
-// VolumeName returns the leading volume name on Windows.
-// It returns "" elsewhere.
-func VolumeName(path string) string {
-       return ""
+// volumeNameLen returns length of the leading volume name on Windows.
+// It returns 0 elsewhere.
+func volumeNameLen(path string) int {
+       return 0
 }
 
 // HasPrefix exists for historical compatibility and should not be used.
index 3dcd0302195d6bd58ba1c2a08d6b878dfa21d76e..db2b57ec00a53b4378a02699ede96740e490651e 100644 (file)
@@ -14,29 +14,27 @@ func isSlash(c uint8) bool {
 
 // IsAbs returns true if the path is absolute.
 func IsAbs(path string) (b bool) {
-       v := VolumeName(path)
-       if v == "" {
+       l := volumeNameLen(path)
+       if l == 0 {
                return false
        }
-       path = path[len(v):]
+       path = path[l:]
        if path == "" {
                return false
        }
        return isSlash(path[0])
 }
 
-// VolumeName returns leading volume name.  
-// Given "C:\foo\bar" it returns "C:" under windows.
-// Given "\\host\share\foo" it returns "\\host\share".
-// On other platforms it returns "".
-func VolumeName(path string) (v string) {
+// volumeNameLen returns length of the leading volume name on Windows.
+// It returns 0 elsewhere.
+func volumeNameLen(path string) int {
        if len(path) < 2 {
-               return ""
+               return 0
        }
        // with drive letter
        c := path[0]
        if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
-               return path[:2]
+               return 2
        }
        // is it UNC
        if l := len(path); l >= 5 && isSlash(path[0]) && isSlash(path[1]) &&
@@ -56,13 +54,13 @@ func VolumeName(path string) (v string) {
                                                        break
                                                }
                                        }
-                                       return path[:n]
+                                       return n
                                }
                                break
                        }
                }
        }
-       return ""
+       return 0
 }
 
 // HasPrefix exists for historical compatibility and should not be used.