1
2
3
4
5 package filepath
6
7 import (
8 "strings"
9 "syscall"
10 )
11
12 func isSlash(c uint8) bool {
13 return c == '\\' || c == '/'
14 }
15
16
17
18
19 var reservedNames = []string{
20 "CON", "PRN", "AUX", "NUL",
21 "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
22 "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
23 }
24
25
26
27 func isReservedName(path string) bool {
28 if len(path) == 0 {
29 return false
30 }
31 for _, reserved := range reservedNames {
32 if strings.EqualFold(path, reserved) {
33 return true
34 }
35 }
36 return false
37 }
38
39
40 func IsAbs(path string) (b bool) {
41 if isReservedName(path) {
42 return true
43 }
44 l := volumeNameLen(path)
45 if l == 0 {
46 return false
47 }
48
49 if isSlash(path[0]) && isSlash(path[1]) {
50 return true
51 }
52 path = path[l:]
53 if path == "" {
54 return false
55 }
56 return isSlash(path[0])
57 }
58
59
60
61 func volumeNameLen(path string) int {
62 if len(path) < 2 {
63 return 0
64 }
65
66 c := path[0]
67 if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
68 return 2
69 }
70
71 if l := len(path); l >= 5 && isSlash(path[0]) && isSlash(path[1]) &&
72 !isSlash(path[2]) && path[2] != '.' {
73
74 for n := 3; n < l-1; n++ {
75
76 if isSlash(path[n]) {
77 n++
78
79 if !isSlash(path[n]) {
80 if path[n] == '.' {
81 break
82 }
83 for ; n < l; n++ {
84 if isSlash(path[n]) {
85 break
86 }
87 }
88 return n
89 }
90 break
91 }
92 }
93 }
94 return 0
95 }
96
97
98
99
100
101 func HasPrefix(p, prefix string) bool {
102 if strings.HasPrefix(p, prefix) {
103 return true
104 }
105 return strings.HasPrefix(strings.ToLower(p), strings.ToLower(prefix))
106 }
107
108 func splitList(path string) []string {
109
110
111
112 if path == "" {
113 return []string{}
114 }
115
116
117 list := []string{}
118 start := 0
119 quo := false
120 for i := 0; i < len(path); i++ {
121 switch c := path[i]; {
122 case c == '"':
123 quo = !quo
124 case c == ListSeparator && !quo:
125 list = append(list, path[start:i])
126 start = i + 1
127 }
128 }
129 list = append(list, path[start:])
130
131
132 for i, s := range list {
133 list[i] = strings.ReplaceAll(s, `"`, ``)
134 }
135
136 return list
137 }
138
139 func abs(path string) (string, error) {
140 if path == "" {
141
142
143
144 path = "."
145 }
146 fullPath, err := syscall.FullPath(path)
147 if err != nil {
148 return "", err
149 }
150 return Clean(fullPath), nil
151 }
152
153 func join(elem []string) string {
154 for i, e := range elem {
155 if e != "" {
156 return joinNonEmpty(elem[i:])
157 }
158 }
159 return ""
160 }
161
162
163 func joinNonEmpty(elem []string) string {
164 if len(elem[0]) == 2 && elem[0][1] == ':' {
165
166
167
168 i := 1
169 for ; i < len(elem); i++ {
170 if elem[i] != "" {
171 break
172 }
173 }
174 return Clean(elem[0] + strings.Join(elem[i:], string(Separator)))
175 }
176
177
178
179 p := Clean(strings.Join(elem, string(Separator)))
180 if !isUNC(p) {
181 return p
182 }
183
184 head := Clean(elem[0])
185 if isUNC(head) {
186 return p
187 }
188
189
190 tail := Clean(strings.Join(elem[1:], string(Separator)))
191 if head[len(head)-1] == Separator {
192 return head + tail
193 }
194 return head + string(Separator) + tail
195 }
196
197
198 func isUNC(path string) bool {
199 return volumeNameLen(path) > 2
200 }
201
202 func sameWord(a, b string) bool {
203 return strings.EqualFold(a, b)
204 }
205
View as plain text