-
Notifications
You must be signed in to change notification settings - Fork 3
/
Pathname.bas
273 lines (223 loc) · 9.36 KB
/
Pathname.bas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
'-----------------------------------------------------------------------------------------------------------------------
' Pathname utility library
' Copyright (c) 2024 Samuel Gomes
'-----------------------------------------------------------------------------------------------------------------------
$INCLUDEONCE
'$INCLUDE:'Pathname.bi'
'-----------------------------------------------------------------------------------------------------------------------
' Test code for debugging the library
'-----------------------------------------------------------------------------------------------------------------------
'_DEFINE A-Z AS LONG
'OPTION _EXPLICIT
'PRINT Pathname_IsAbsolute("C:/Windows")
'PRINT Pathname_IsAbsolute("/Windows")
'PRINT Pathname_IsAbsolute("Windows")
'PRINT Pathname_IsAbsolute("")
'PRINT Pathname_FixDirectoryName("Windows")
'PRINT Pathname_FixDirectoryName("Windows/")
'PRINT Pathname_FixDirectoryName("")
'PRINT Pathname_FixDirectorySeparators("C:/Windows\")
'PRINT Pathname_FixDirectorySeparators("Windows")
'PRINT Pathname_FixDirectorySeparators("")
'PRINT Pathname_GetFileName("C:\foo/bar.ext")
'PRINT Pathname_GetFileName("bar.ext")
'PRINT Pathname_GetFileName("")
'PRINT Pathname_GetPath("C:\foo/bar.ext")
'PRINT Pathname_GetPath("\bar.ext")
'PRINT Pathname_GetPath("")
'PRINT Pathname_HasFileExtension("C:\foo/bar.ext")
'PRINT Pathname_HasFileExtension("bar.ext/")
'PRINT Pathname_HasFileExtension("")
'PRINT Pathname_GetFileExtension("C:\foo/bar.ext")
'PRINT Pathname_GetFileExtension("bar.ext/")
'PRINT Pathname_GetFileExtension("")
'PRINT Pathname_RemoveFileExtension("C:\foo/bar.ext")
'PRINT Pathname_RemoveFileExtension("bar.ext/")
'PRINT Pathname_RemoveFileExtension("")
'PRINT Pathname_GetDriveOrScheme("https://www.github.com/")
'PRINT Pathname_GetDriveOrScheme("C:\Windows\")
'PRINT Pathname_GetDriveOrScheme("")
'PRINT Pathname_MakeLegalFileName("<abracadabra.txt/>")
'PRINT Pathname_MakeLegalFileName("")
'END
'-----------------------------------------------------------------------------------------------------------------------
' Return true if path name is an absolute path (i.e. starts from the root)
FUNCTION Pathname_IsAbsolute%% (pathName AS STRING)
$IF WINDOWS THEN
' Either \ or / or x:\ or x:/
IF LEN(pathName) > 2 THEN
Pathname_IsAbsolute = (ASC(pathName, 1) = PATHNAME_DIR_SEPARATOR_CODE_WIN OR ASC(pathName, 1) = PATHNAME_DIR_SEPARATOR_CODE_NIX OR ASC(pathName, 3) = PATHNAME_DIR_SEPARATOR_CODE_WIN OR ASC(pathName, 3) = PATHNAME_DIR_SEPARATOR_CODE_NIX)
ELSEIF LEN(pathName) > 0 THEN
Pathname_IsAbsolute = (ASC(pathName, 1) = PATHNAME_DIR_SEPARATOR_CODE_WIN OR ASC(pathName, 1) = PATHNAME_DIR_SEPARATOR_CODE_NIX)
END IF
$ELSE
' /
IF LEN(pathName) > 0 THEN
Pathname_IsAbsolute = (PATHNAME_DIR_SEPARATOR_CODE = ASC(pathName, 1))
END IF
$END IF
END FUNCTION
' Adds a trailing directory separator to a directory name if needed
FUNCTION Pathname_FixDirectoryName$ (pathName AS STRING)
$IF WINDOWS THEN
IF LEN(pathName) > 0 THEN
IF ASC(pathName, LEN(pathName)) <> PATHNAME_DIR_SEPARATOR_CODE_WIN AND ASC(pathName, LEN(pathName)) <> PATHNAME_DIR_SEPARATOR_CODE_NIX THEN
Pathname_FixDirectoryName = pathName + PATHNAME_DIR_SEPARATOR
EXIT FUNCTION
END IF
END IF
$ELSE
IF LEN(pathName) > 0 THEN
IF ASC(pathName, LEN(pathName)) <> PATHNAME_DIR_SEPARATOR_CODE THEN
Pathname_FixDirectoryName = pathName + PATHNAME_DIR_SEPARATOR
EXIT FUNCTION
END IF
END IF
$END IF
Pathname_FixDirectoryName = pathName
END FUNCTION
' Fixes the provided filename and path to use the correct path separator
FUNCTION Pathname_FixDirectorySeparators$ (pathName AS STRING)
DIM i AS _UNSIGNED LONG, buffer AS STRING: buffer = pathName
$IF WINDOWS THEN
FOR i = 1 TO LEN(buffer)
IF ASC(buffer, i) = PATHNAME_DIR_SEPARATOR_CODE_NIX THEN ASC(buffer, i) = PATHNAME_DIR_SEPARATOR_CODE_WIN
NEXT
$ELSE
FOR i = 1 TO LEN(buffer)
IF ASC(buffer, i) = PATHNAME_DIR_SEPARATOR_CODE_WIN THEN ASC(buffer, i) = PATHNAME_DIR_SEPARATOR_CODE_NIX
NEXT
$END IF
Pathname_FixDirectorySeparators = buffer
END FUNCTION
' Gets the filename portion from a file path or URL
' If no part seperator is found it assumes the whole string is a filename
FUNCTION Pathname_GetFileName$ (pathOrURL AS STRING)
DIM AS _UNSIGNED LONG i, j: j = LEN(pathOrURL)
$IF WINDOWS THEN
' Retrieve the position of the first / or \ in the parameter from the
FOR i = j TO 1 STEP -1
SELECT CASE ASC(pathOrURL, i)
CASE PATHNAME_DIR_SEPARATOR_CODE_WIN, PATHNAME_DIR_SEPARATOR_CODE_NIX
EXIT FOR
END SELECT
NEXT
$ELSE
i = _INSTRREV(pathOrURL, PATHNAME_DIR_SEPARATOR)
$END IF
' Return the full string if pathsep was not found
IF i = 0 THEN
Pathname_GetFileName = pathOrURL
ELSE
Pathname_GetFileName = RIGHT$(pathOrURL, j - i)
END IF
END FUNCTION
' Returns the pathname portion from a file path or URL
' If no path seperator is found it return an empty string
FUNCTION Pathname_GetPath$ (pathOrURL AS STRING)
DIM i AS _UNSIGNED LONG
$IF WINDOWS THEN
FOR i = LEN(pathOrURL) TO 1 STEP -1
SELECT CASE ASC(pathOrURL, i)
CASE PATHNAME_DIR_SEPARATOR_CODE_WIN, PATHNAME_DIR_SEPARATOR_CODE_NIX
EXIT FOR
END SELECT
NEXT
$ELSE
i = _INSTRREV(pathOrURL, PATHNAME_DIR_SEPARATOR)
$END IF
IF i <> 0 THEN Pathname_GetPath = LEFT$(pathOrURL, i)
END FUNCTION
' Returns True if pathOrURL has a file extension
FUNCTION Pathname_HasFileExtension%% (pathOrURL AS STRING)
DIM i AS _UNSIGNED LONG
FOR i = LEN(pathOrURL) TO 1 STEP -1
$IF WINDOWS THEN
SELECT CASE ASC(pathOrURL, i)
CASE PATHNAME_DIR_SEPARATOR_CODE_WIN, PATHNAME_DIR_SEPARATOR_CODE_NIX
EXIT FOR
CASE PATHNAME_EXT_SEPARATOR_CODE
Pathname_HasFileExtension = TRUE
EXIT FOR
END SELECT
$ELSE
SELECT CASE ASC(pathOrURL, i)
CASE PATHNAME_DIR_SEPARATOR_CODE
EXIT FOR
CASE PATHNAME_EXT_SEPARATOR_CODE
Pathname_HasFileExtension = TRUE
EXIT FOR
END SELECT
$END IF
NEXT
END FUNCTION
' Get the file extension from a path name (ex. .doc, .so etc.)
' Note this will return anything after a dot if the URL/path is just a directory name
FUNCTION Pathname_GetFileExtension$ (pathOrURL AS STRING)
DIM i AS _UNSIGNED LONG
FOR i = LEN(pathOrURL) TO 1 STEP -1
$IF WINDOWS THEN
SELECT CASE ASC(pathOrURL, i)
CASE PATHNAME_DIR_SEPARATOR_CODE_WIN, PATHNAME_DIR_SEPARATOR_CODE_NIX
EXIT FOR
CASE PATHNAME_EXT_SEPARATOR_CODE
Pathname_GetFileExtension = RIGHT$(pathOrURL, LEN(pathOrURL) - i + 1)
EXIT FOR
END SELECT
$ELSE
SELECT CASE ASC(pathOrURL, i)
CASE PATHNAME_DIR_SEPARATOR_CODE
EXIT FOR
CASE PATHNAME_EXT_SEPARATOR_CODE
Pathname_GetFileExtension = RIGHT$(pathOrURL, LEN(pathOrURL) - i + 1)
EXIT FOR
END SELECT
$END IF
NEXT
END FUNCTION
' Returns pathOrURL without extension
FUNCTION Pathname_RemoveFileExtension$ (pathOrURL AS STRING)
DIM i AS _UNSIGNED LONG
FOR i = LEN(pathOrURL) TO 1 STEP -1
$IF WINDOWS THEN
SELECT CASE ASC(pathOrURL, i)
CASE PATHNAME_DIR_SEPARATOR_CODE_WIN, PATHNAME_DIR_SEPARATOR_CODE_NIX
EXIT FOR
CASE PATHNAME_EXT_SEPARATOR_CODE
Pathname_RemoveFileExtension = LEFT$(pathOrURL, i - 1)
EXIT FUNCTION
END SELECT
$ELSE
SELECT CASE ASC(pathOrURL, i)
CASE PATHNAME_DIR_SEPARATOR_CODE
EXIT FOR
CASE PATHNAME_EXT_SEPARATOR_CODE
Pathname_RemoveFileExtension = LEFT$(pathOrURL, i - 1)
EXIT FUNCTION
END SELECT
$END IF
NEXT
Pathname_RemoveFileExtension = pathOrURL
END FUNCTION
' Gets the drive or scheme from a path name (ex. C:, HTTPS: etc.)
FUNCTION Pathname_GetDriveOrScheme$ (pathOrURL AS STRING)
DIM i AS _UNSIGNED LONG: i = INSTR(pathOrURL, PATHNAME_SCHEME_TERMINATOR)
IF i <> 0 THEN Pathname_GetDriveOrScheme = LEFT$(pathOrURL, i)
END FUNCTION
' Generates a filename without illegal filesystem characters
' Actually this is a lot more strict on *nix to ensure Windows & *nix interop.
FUNCTION Pathname_MakeLegalFileName$ (fileName AS STRING)
DIM s AS STRING, c AS _UNSIGNED _BYTE
' Clean any unwanted characters
DIM i AS _UNSIGNED LONG
FOR i = 1 TO LEN(fileName)
c = ASC(fileName, i)
SELECT CASE c
CASE IS < 32, PATHNAME_DIR_SEPARATOR_CODE_WIN, PATHNAME_DIR_SEPARATOR_CODE_NIX, PATHNAME_SCHEME_TERMINATOR_CODE, 34, 42, 60, 62, 63, 124
s = s + "_"
CASE ELSE
s = s + CHR$(c)
END SELECT
NEXT
Pathname_MakeLegalFileName = s
END FUNCTION