-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSTRINGS.PAS
323 lines (289 loc) · 7.79 KB
/
STRINGS.PAS
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
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
{
Strings Unit
Pascal and null-terminated string manipulation
2022 LRT
}
unit
strings;
interface
uses
types;
const
C_TRIM_CHARS = [' ', #10, #13, #9];
type
TCharSet = set of char;
{ returns the word value as a string, left padded with the specified char }
function padw(w: word; ch: char; count: byte): string5;
{ returns the uppercase version of the provided string }
function strUpper(s: string): string;
{ returns the lowercase version of the provided string }
function strLower(s: string): string;
{ returns a substring of the provided string }
function subString(s: string; position, count:byte): string;
{ returns true if string begins as specified }
function beginsWith(const str, key: string): boolean;
{ trims a string by removing characters from its beginning and end}
function trim(const str: string): string;
function trimChars(const str: string; chars: TCharSet): string;
{ converts a null-terminated string to a Pascal-style string }
function pCharToStr(p: PChar): string;
{ returns the length of a null-terminated string }
function strlen(p: PChar): word;
{
returns a string based on the specified format
each element in the format string must be tagged as [x] where x is
a number between 0 and 9. args must be a pointer to an array of pascal
strings. Each string must be a full pascal string, not a shortened one
like string[10].
}
function strformat(format: string; args: pstr): string;
{
a different implementation of the strformat function. This one
expects each argument to be tagged as %0, %1, %2 and so on up
until %9. Each element is added to the args string, delimited
by a null character.
requires less memory than strformat and does not require to
think in pointers.
}
function strformatn(const str, args: string): string;
{
returns true if the string contains at least one character that is
included in the provided set
}
function contains(const str: string; chars: TCharSet): boolean;
{
returns true if the string A starts exactly like the full string B
}
function startsWith(const str, prefix: string): boolean;
implementation
function padw(w: word; ch: char; count: byte): string5;
var
s: string5;
begin
str(w, s);
while length(s)<count do s := ch + s;
padw := s;
end;
function strUpper(s: string): string;
var
i, len: byte;
ch: char;
res: string;
begin
res[0] := s[0];
len := length(s);
for i := 1 to len do
begin
ch := s[i];
if (ch >= 'a') and (ch <= 'z') then ch := chr(ord(ch) - 32);
res[i] := ch;
end;
strUpper := res;
end;
function strLower(s: string): string;
var
i, len: byte;
ch: char;
res: string;
begin
res[0] := s[0];
len := length(s);
for i := 1 to len do
begin
ch := s[i];
if (ch >= 'A') and (ch <= 'Z') then ch := chr(ord(ch) + 32);
res[i] := ch;
end;
strLower := res;
end;
function subString(s: string; position, count:byte): string;
var
res: string;
i, c: byte;
begin
i := position;
c := position + count;
res := '';
while (i<=byte(s[0])) and (i<c) do
begin
res := res + s[i];
inc(i);
end;
subString := res;
end;
function extractFileName(path: string; includeExtension: boolean): string;
var
i: byte;
s: string;
begin
i := length(path);
if not includeExtension then dec(i, 4);
s := '';
while path[i] <> '\' do
begin
s := path[i] + s;
dec(i);
end;
extractFileName := s;
end;
function beginsWith(const str, key: string): boolean;
var
i: byte;
begin
beginsWith := false;
if length(str)<length(key) then exit;
i := 1;
while (i<=length(str)) and (i<=length(key)) and (str[i]=key[i]) do inc(i);
beginsWith := i>length(key);
end;
function trim(const str: string): string;
begin
trim := trimChars(str, C_TRIM_CHARS);
end;
function trimChars(const str: string; chars: TCharSet): string;
var
i, j: byte;
begin
i := 1;
while (i<=length(str)) and (str[i] in chars) do inc(i);
j := length(str);
while (j>=1) and (str[j] in chars) do dec(j);
trimChars := copy(str, i, j-i+1);
end;
function pCharToStr(p: PChar): string;
var s: string;
begin
s[0] := #0;
while (s[0] <> #$FF) and (p^ <> #0) do
begin
inc(s[0]);
s[ord(s[0])] := p^;
inc(p);
end;
pCharToStr := s;
end;
function strlen(p: PChar): word;
var c: word;
begin
c := 0;
while p^ <> #0 do
begin
inc(c);
inc(p);
end;
strlen := c;
end;
function strformat(format: string; args: pstr): string;
var
str: string;
strIndex, fsIndex, argIndex: byte;
current, next: char;
p: pstr;
begin
str := '';
strIndex := 1;
fsIndex := 1;
while fsIndex <= length(format) do
begin
current := format[fsIndex];
if (fsIndex+1) <= length(format) then next := format[fsIndex+1] else next := #0;
if (current <> '[') then
begin
str[strIndex] := current;
str[0] := chr(strIndex);
inc(strIndex);
inc(fsIndex);
end else
begin
if (next = '[') or (next = #0) or not (next in ['0'..'9']) then
begin
str[strIndex] := current;
str[0] := chr(strIndex);
inc(strIndex);
if (next = '[') then inc(fsIndex, 2) else inc(fsIndex);
end else begin
argIndex := ord(next) - ord('0');
p := args;
inc(p, argIndex);
str := str + p^;
inc(strIndex, length(p^));
inc(fsIndex, 3);
end;
end;
end;
strformat := str;
end;
function strformatn(const str, args: string): string;
var
tokens: array[0..9] of byte;
result: string;
i, index: byte;
ch: char;
begin
{ if no arguments then return str and leave }
if args = '' then
begin
strformatn := str;
exit;
end;
{ find tokens in args }
fillchar(tokens, sizeof(tokens), 0);
tokens[0] := 1;
index := 1;
i := 1;
while i<=length(args) do
begin
if args[i]=#0 then begin
tokens[index] := i+1;
inc(index);
end;
inc(i);
end;
{ replace tokens in string }
result := '';
i := 1;
while i <= length(str) do
begin
ch := str[i];
if (str[i] = '%') then
if (i+1<=length(str)) then
begin
if (str[i+1] in ['0'..'9']) then
begin
ch := #0;
{ copy the token until next null or end of line}
index := tokens[ord(str[i+1]) - ord('0')];
while (index<>0) and (index<=length(args)) and (args[index]<>#0) do
begin
result := result + args[index];
inc(index);
end;
inc(i);
end else if str[i+1]='%' then
inc(i);
end;
if ch <> #0 then result := result + ch;
inc(i);
end;
strformatn := result;
end;
function contains(const str: string; chars: TCharSet): boolean;
var
i: byte;
begin
i := 1;
while (i<=length(str)) and not (str[i] in chars) do inc(i);
contains := i <= length(str)
end;
function startsWith(const str, prefix: string): boolean;
var i: byte;
begin
startsWith := false;
if length(str) >= length(prefix) then
begin
i := 1;
while (i <= length(prefix)) and (str[i] = prefix[i]) do inc(i);
startsWith := i > length(prefix);
end;
end;
end.