@@ -19,13 +19,18 @@ package httprouter
19
19
//
20
20
// If the result of this process is an empty string, "/" is returned
21
21
func CleanPath (p string ) string {
22
+ const stackBufSize = 128
23
+
22
24
// Turn empty string into "/"
23
25
if p == "" {
24
26
return "/"
25
27
}
26
28
29
+ // Reasonably sized buffer on stack to avoid allocations in the common case.
30
+ // If a larger buffer is required, it gets allocated dynamically.
31
+ buf := make ([]byte , 0 , stackBufSize )
32
+
27
33
n := len (p )
28
- var buf []byte
29
34
30
35
// Invariants:
31
36
// reading from path; r is index of next byte to process.
@@ -37,7 +42,12 @@ func CleanPath(p string) string {
37
42
38
43
if p [0 ] != '/' {
39
44
r = 0
40
- buf = make ([]byte , n + 1 )
45
+
46
+ if n + 1 > stackBufSize {
47
+ buf = make ([]byte , n + 1 )
48
+ } else {
49
+ buf = buf [:n + 1 ]
50
+ }
41
51
buf [0 ] = '/'
42
52
}
43
53
@@ -69,7 +79,7 @@ func CleanPath(p string) string {
69
79
// can backtrack
70
80
w --
71
81
72
- if buf == nil {
82
+ if len ( buf ) == 0 {
73
83
for w > 1 && p [w ] != '/' {
74
84
w --
75
85
}
@@ -103,20 +113,25 @@ func CleanPath(p string) string {
103
113
w ++
104
114
}
105
115
106
- if buf == nil {
116
+ if len ( buf ) == 0 {
107
117
return p [:w ]
108
118
}
109
119
return string (buf [:w ])
110
120
}
111
121
112
122
// internal helper to lazily create a buffer if necessary
113
123
func bufApp (buf * []byte , s string , w int , c byte ) {
114
- if * buf == nil {
124
+ if len ( * buf ) == 0 {
115
125
if s [w ] == c {
116
126
return
117
127
}
118
128
119
- * buf = make ([]byte , len (s ))
129
+ if l := len (s ); l > cap (* buf ) {
130
+ * buf = make ([]byte , len (s ))
131
+ } else {
132
+ * buf = (* buf )[:l ]
133
+ }
134
+
120
135
copy (* buf , s [:w ])
121
136
}
122
137
(* buf )[w ] = c
0 commit comments