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