Rev 747 | Rev 749 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 747 | Rev 748 | ||
---|---|---|---|
1 | unit VTSFUNCS; |
1 | unit VTSFUNCS; |
2 | 2 | ||
3 | (************************************************) |
3 | (************************************************) |
4 | (* VTSFUNCS.PAS *) |
4 | (* VTSFUNCS.PAS *) |
5 | (* Author: Daniel Marschall *) |
5 | (* Author: Daniel Marschall *) |
6 | (* Revision: 2022-02-16 *) |
6 | (* Revision: 2022-02-19 *) |
7 | (* License: Apache 2.0 *) |
7 | (* License: Apache 2.0 *) |
8 | (* This file contains: *) |
8 | (* This file contains: *) |
9 | (* - Various functions *) |
9 | (* - Various functions *) |
10 | (************************************************) |
10 | (************************************************) |
11 | 11 | ||
12 | interface |
12 | interface |
13 | 13 | ||
14 | function Max(a, b: integer): integer; |
14 | function Max(a, b: integer): integer; |
15 | function Min(a, b: integer): integer; |
15 | function Min(a, b: integer): integer; |
16 | 16 | ||
17 | function CompareEqualLengthString(a, b: string): integer; |
17 | function CompareEqualLengthString(a, b: string): integer; |
18 | function CompareNumericString(a, b: string): integer; |
18 | function CompareNumericString(a, b: string): integer; |
19 | 19 | ||
20 | procedure Beep; |
20 | procedure Beep; |
21 | 21 | ||
22 | function Trim(s: string): string; |
22 | function Trim(s: string): string; |
23 | function TrimLineToWidth(s: string; width: integer): string; |
23 | function TrimLineToWidth(s: string; width: integer): string; |
24 | function ZeroPad(i: LongInt; n: integer): string; |
24 | function ZeroPad(i: LongInt; n: integer): string; |
25 | function LeftPadStr(s: string; n: integer; ch: char): string; |
25 | function LeftPadStr(s: string; n: integer; ch: char): string; |
26 | function RightPadStr(s: string; n: integer; ch: char): string; |
26 | function RightPadStr(s: string; n: integer; ch: char): string; |
27 | function RepeatStr(ch: char; n: integer): string; |
27 | function RepeatStr(ch: char; n: integer): string; |
28 | 28 | ||
29 | function DeleteFile(filename: string): boolean; |
29 | function DeleteFile(filename: string): boolean; |
30 | function FileExists(filename: string): boolean; |
30 | function FileExists(filename: string): boolean; |
31 | 31 | ||
32 | function IsPositiveIntegerOrZero(s: string): boolean; |
32 | function IsPositiveIntegerOrZero(s: string): boolean; |
33 | function StrToInt(s: string): Integer; |
33 | function StrToInt(s: string): Integer; |
34 | function IntToStr(Value: Integer): string; |
34 | function IntToStr(Value: Integer): string; |
35 | 35 | ||
36 | function StringReplace(s, search, replace: string): string; |
36 | function StringReplace(s, search, replace: string): string; |
37 | 37 | ||
- | 38 | function LastCharPos(const S: string; const Chr: char): integer; |
|
- | 39 | function LowerCase(s: string): string; |
|
- | 40 | function base_convert_bigint(numstring: string; frombase, tobase: integer): string; |
|
- | 41 | ||
38 | implementation |
42 | implementation |
39 | 43 | ||
40 | uses |
44 | uses |
41 | Crt; |
45 | Crt; |
42 | 46 | ||
43 | function Max(a, b: integer): integer; |
47 | function Max(a, b: integer): integer; |
44 | begin |
48 | begin |
45 | if a > b then |
49 | if a > b then |
46 | Max := a |
50 | Max := a |
47 | else |
51 | else |
48 | Max := b; |
52 | Max := b; |
49 | end; |
53 | end; |
50 | 54 | ||
51 | function Min(a, b: integer): integer; |
55 | function Min(a, b: integer): integer; |
52 | begin |
56 | begin |
53 | if a < b then |
57 | if a < b then |
54 | Min := a |
58 | Min := a |
55 | else |
59 | else |
56 | Min := b; |
60 | Min := b; |
57 | end; |
61 | end; |
58 | 62 | ||
59 | function CompareEqualLengthString(a, b: string): integer; |
63 | function CompareEqualLengthString(a, b: string): integer; |
60 | var |
64 | var |
61 | ao, bo, i: integer; |
65 | ao, bo, i: integer; |
62 | begin |
66 | begin |
63 | CompareEqualLengthString := 0; |
67 | CompareEqualLengthString := 0; |
64 | for i := 1 to Length(a) do |
68 | for i := 1 to Length(a) do |
65 | begin |
69 | begin |
66 | ao := Ord(a[i]); |
70 | ao := Ord(a[i]); |
67 | bo := Ord(b[i]); |
71 | bo := Ord(b[i]); |
68 | if ao > bo then |
72 | if ao > bo then |
69 | begin |
73 | begin |
70 | CompareEqualLengthString := 1; |
74 | CompareEqualLengthString := 1; |
71 | break; |
75 | break; |
72 | end; |
76 | end; |
73 | if ao < bo then |
77 | if ao < bo then |
74 | begin |
78 | begin |
75 | CompareEqualLengthString := -1; |
79 | CompareEqualLengthString := -1; |
76 | break; |
80 | break; |
77 | end; |
81 | end; |
78 | end; |
82 | end; |
79 | end; |
83 | end; |
80 | 84 | ||
81 | function CompareNumericString(a, b: string): integer; |
85 | function CompareNumericString(a, b: string): integer; |
82 | var |
86 | var |
83 | EqualLength: integer; |
87 | EqualLength: integer; |
84 | begin |
88 | begin |
85 | EqualLength := Max(Length(a), Length(b)); |
89 | EqualLength := Max(Length(a), Length(b)); |
86 | a := LeftPadStr(a, EqualLength, '0'); |
90 | a := LeftPadStr(a, EqualLength, '0'); |
87 | b := LeftPadStr(b, EqualLength, '0'); |
91 | b := LeftPadStr(b, EqualLength, '0'); |
88 | CompareNumericString := CompareEqualLengthString(a, b); |
92 | CompareNumericString := CompareEqualLengthString(a, b); |
89 | end; |
93 | end; |
90 | 94 | ||
91 | procedure Beep; |
95 | procedure Beep; |
92 | begin |
96 | begin |
93 | Sound(220); (*220Hz*) |
97 | Sound(220); (*220Hz*) |
94 | Delay(200); (*200ms*) |
98 | Delay(200); (*200ms*) |
95 | NoSound; |
99 | NoSound; |
96 | end; |
100 | end; |
97 | 101 | ||
98 | function Trim(s: string): string; |
102 | function Trim(s: string): string; |
99 | begin |
103 | begin |
100 | while Length(s) > 0 do |
104 | while Length(s) > 0 do |
101 | begin |
105 | begin |
102 | if s[1] in [#9,#10,#13,' '] then |
106 | if s[1] in [#9,#10,#13,' '] then |
103 | Delete(s,1,1) |
107 | Delete(s,1,1) |
104 | else |
108 | else |
105 | break; |
109 | break; |
106 | end; |
110 | end; |
107 | while Length(s) > 0 do |
111 | while Length(s) > 0 do |
108 | begin |
112 | begin |
109 | if s[Length(s)] in [#9,#10,#13,' '] then |
113 | if s[Length(s)] in [#9,#10,#13,' '] then |
110 | Delete(s,Length(s),1) |
114 | Delete(s,Length(s),1) |
111 | else |
115 | else |
112 | break; |
116 | break; |
113 | end; |
117 | end; |
114 | Trim := s; |
118 | Trim := s; |
115 | end; |
119 | end; |
116 | 120 | ||
117 | function TrimLineToWidth(s: string; width: integer): string; |
121 | function TrimLineToWidth(s: string; width: integer): string; |
118 | begin |
122 | begin |
119 | if Length(s) > width then |
123 | if Length(s) > width then |
120 | begin |
124 | begin |
121 | s := Copy(s, 1, width-3) + '...'; |
125 | s := Copy(s, 1, width-3) + '...'; |
122 | end; |
126 | end; |
123 | TrimLineToWidth := s; |
127 | TrimLineToWidth := s; |
124 | end; |
128 | end; |
125 | 129 | ||
126 | function ZeroPad(i: LongInt; n: integer): string; |
130 | function ZeroPad(i: LongInt; n: integer): string; |
127 | var |
131 | var |
128 | s: string; |
132 | s: string; |
129 | begin |
133 | begin |
130 | s := IntToStr(i); |
134 | s := IntToStr(i); |
131 | ZeroPad := LeftPadStr(s, n, '0'); |
135 | ZeroPad := LeftPadStr(s, n, '0'); |
132 | end; |
136 | end; |
133 | 137 | ||
134 | function LeftPadStr(s: string; n: integer; ch: char): string; |
138 | function LeftPadStr(s: string; n: integer; ch: char): string; |
135 | begin |
139 | begin |
136 | while Length(s) < n do |
140 | while Length(s) < n do |
137 | begin |
141 | begin |
138 | s := ch + s; |
142 | s := ch + s; |
139 | end; |
143 | end; |
140 | LeftPadStr := s; |
144 | LeftPadStr := s; |
141 | end; |
145 | end; |
142 | 146 | ||
143 | function RightPadStr(s: string; n: integer; ch: char): string; |
147 | function RightPadStr(s: string; n: integer; ch: char): string; |
144 | begin |
148 | begin |
145 | while Length(s) < n do |
149 | while Length(s) < n do |
146 | begin |
150 | begin |
147 | s := s + ch; |
151 | s := s + ch; |
148 | end; |
152 | end; |
149 | RightPadStr := s; |
153 | RightPadStr := s; |
150 | end; |
154 | end; |
151 | 155 | ||
152 | function RepeatStr(ch: char; n: integer): string; |
156 | function RepeatStr(ch: char; n: integer): string; |
153 | var |
157 | var |
154 | i: integer; |
158 | i: integer; |
155 | res: string; |
159 | res: string; |
156 | begin |
160 | begin |
157 | res := ''; |
161 | res := ''; |
158 | for i := 1 to n do |
162 | for i := 1 to n do |
159 | begin |
163 | begin |
160 | res := res + ch; |
164 | res := res + ch; |
161 | end; |
165 | end; |
162 | RepeatStr := res; |
166 | RepeatStr := res; |
163 | end; |
167 | end; |
164 | 168 | ||
165 | function DeleteFile(filename: string): boolean; |
169 | function DeleteFile(filename: string): boolean; |
166 | var |
170 | var |
167 | F: file; |
171 | F: file; |
168 | Ch: Char; |
172 | Ch: Char; |
169 | begin |
173 | begin |
170 | Assign(F, filename); |
174 | Assign(F, filename); |
171 | {$I-} |
175 | {$I-} |
172 | Reset(F); |
176 | Reset(F); |
173 | {$I+} |
177 | {$I+} |
174 | if IOResult <> 0 then |
178 | if IOResult <> 0 then |
175 | begin |
179 | begin |
176 | DeleteFile := false; (* cannot find file *) |
180 | DeleteFile := false; (* cannot find file *) |
177 | end |
181 | end |
178 | else |
182 | else |
179 | begin |
183 | begin |
180 | Close(F); |
184 | Close(F); |
181 | {$I-} |
185 | {$I-} |
182 | Erase(F); |
186 | Erase(F); |
183 | {$I+} |
187 | {$I+} |
184 | DeleteFile := IOResult = 0; |
188 | DeleteFile := IOResult = 0; |
185 | end; |
189 | end; |
186 | end; |
190 | end; |
187 | 191 | ||
188 | function FileExists(filename: string): boolean; |
192 | function FileExists(filename: string): boolean; |
189 | var |
193 | var |
190 | F: Text; |
194 | F: Text; |
191 | begin |
195 | begin |
192 | Assign(F, filename); |
196 | Assign(F, filename); |
193 | {$I-} |
197 | {$I-} |
194 | Reset(F); |
198 | Reset(F); |
195 | {$I+} |
199 | {$I+} |
196 | if IoResult = 0 then |
200 | if IoResult = 0 then |
197 | begin |
201 | begin |
198 | Close(F); |
202 | Close(F); |
199 | FileExists := true; |
203 | FileExists := true; |
200 | end |
204 | end |
201 | else |
205 | else |
202 | begin |
206 | begin |
203 | FileExists := false; |
207 | FileExists := false; |
204 | end; |
208 | end; |
205 | end; |
209 | end; |
206 | 210 | ||
207 | function IsPositiveIntegerOrZero(s: string): boolean; |
211 | function IsPositiveIntegerOrZero(s: string): boolean; |
208 | var |
212 | var |
209 | i: integer; |
213 | i: integer; |
210 | begin |
214 | begin |
211 | IsPositiveIntegerOrZero := false; |
215 | IsPositiveIntegerOrZero := false; |
212 | 216 | ||
213 | if Length(s) = 0 then exit; |
217 | if Length(s) = 0 then exit; |
214 | if (s[1] = '0') and (s <> '0') then exit; |
218 | if (s[1] = '0') and (s <> '0') then exit; |
215 | for i := 1 to Length(s) do |
219 | for i := 1 to Length(s) do |
216 | begin |
220 | begin |
217 | if not (s[i] in ['0'..'9']) then exit; |
221 | if not (s[i] in ['0'..'9']) then exit; |
218 | end; |
222 | end; |
219 | 223 | ||
220 | IsPositiveIntegerOrZero := true; |
224 | IsPositiveIntegerOrZero := true; |
221 | end; |
225 | end; |
222 | 226 | ||
223 | function StrToInt(s: string): Integer; |
227 | function StrToInt(s: string): Integer; |
224 | var |
228 | var |
225 | i, Error: Integer; |
229 | i, Error: Integer; |
226 | begin |
230 | begin |
227 | Val(s, i, Error); |
231 | Val(s, i, Error); |
228 | StrToInt := i; |
232 | StrToInt := i; |
229 | end; |
233 | end; |
230 | 234 | ||
231 | function IntToStr(Value: Integer): string; |
235 | function IntToStr(Value: Integer): string; |
232 | var |
236 | var |
233 | s: string; |
237 | s: string; |
234 | begin |
238 | begin |
235 | Str(Value, s); |
239 | Str(Value, s); |
236 | IntToStr := s; |
240 | IntToStr := s; |
237 | end; |
241 | end; |
238 | 242 | ||
239 | function StringReplace(s, search, replace: string): string; |
243 | function StringReplace(s, search, replace: string): string; |
240 | var |
244 | var |
241 | i: integer; |
245 | i: integer; |
242 | output: string; |
246 | output: string; |
243 | begin |
247 | begin |
244 | if s = '' then exit; |
248 | if s = '' then |
- | 249 | begin |
|
- | 250 | StringReplace := ''; |
|
- | 251 | Exit; |
|
- | 252 | end; |
|
- | 253 | if search = '' then |
|
- | 254 | begin |
|
- | 255 | StringReplace := s; |
|
245 | if search = '' then exit; (* invalid arg *) |
256 | exit; (* invalid arg *) |
- | 257 | end; |
|
246 | 258 | ||
247 | output := ''; |
259 | output := ''; |
248 | while s <> '' do |
260 | while s <> '' do |
249 | begin |
261 | begin |
250 | if Copy(s, 1, Length(search)) = search then |
262 | if Copy(s, 1, Length(search)) = search then |
251 | begin |
263 | begin |
252 | output := output + replace; |
264 | output := output + replace; |
253 | Delete(s, 1, Length(search)); |
265 | Delete(s, 1, Length(search)); |
254 | end |
266 | end |
255 | else |
267 | else |
256 | begin |
268 | begin |
257 | output := output + Copy(s, 1, 1); |
269 | output := output + Copy(s, 1, 1); |
258 | Delete(s, 1, 1); |
270 | Delete(s, 1, 1); |
259 | end; |
271 | end; |
260 | end; |
272 | end; |
261 | 273 | ||
262 | StringReplace := output; |
274 | StringReplace := output; |
263 | end; |
275 | end; |
- | 276 | ||
- | 277 | function LastCharPos(const S: string; const Chr: char): integer; |
|
- | 278 | var |
|
- | 279 | i: Integer; |
|
- | 280 | begin |
|
- | 281 | for i := length(S) downto 1 do |
|
- | 282 | begin |
|
- | 283 | if S[i] = Chr then |
|
- | 284 | begin |
|
- | 285 | LastCharPos := i; |
|
- | 286 | Exit; |
|
- | 287 | end; |
|
- | 288 | end; |
|
- | 289 | LastCharPos := 0; |
|
- | 290 | Exit; |
|
- | 291 | end; |
|
- | 292 | ||
- | 293 | function LowerCase(s: string): string; |
|
- | 294 | var |
|
- | 295 | res: string; |
|
- | 296 | i: integer; |
|
- | 297 | begin |
|
- | 298 | res := ''; |
|
- | 299 | for i := 1 to Length(s) do |
|
- | 300 | begin |
|
- | 301 | if s[i] in ['A'..'Z'] then |
|
- | 302 | begin |
|
- | 303 | res := res + Chr(Ord('a')+(Ord(s[i])-Ord('A'))); |
|
- | 304 | end |
|
- | 305 | else |
|
- | 306 | begin |
|
- | 307 | res := res + s[i]; |
|
- | 308 | end; |
|
- | 309 | end; |
|
- | 310 | LowerCase := res; |
|
- | 311 | end; |
|
- | 312 | ||
- | 313 | function base_convert_bigint(numstring: string; frombase, tobase: integer): string; |
|
- | 314 | var |
|
- | 315 | i: Integer; |
|
- | 316 | frombase_str: string; |
|
- | 317 | tobase_str: string; |
|
- | 318 | len: Integer; |
|
- | 319 | number: string; |
|
- | 320 | divide: Integer; |
|
- | 321 | newlen: Integer; |
|
- | 322 | res: string; |
|
- | 323 | begin |
|
- | 324 | frombase_str := ''; |
|
- | 325 | for i := 0 to frombase-1 do |
|
- | 326 | begin |
|
- | 327 | if i < 10 then |
|
- | 328 | frombase_str := frombase_str + IntToStr(i) |
|
- | 329 | else |
|
- | 330 | frombase_str := frombase_str + Chr(Ord('A') + (i-10)); |
|
- | 331 | end; |
|
- | 332 | ||
- | 333 | tobase_str := ''; |
|
- | 334 | for i := 0 to tobase-1 do |
|
- | 335 | begin |
|
- | 336 | if i < 10 then |
|
- | 337 | tobase_str := tobase_str + IntToStr(i) |
|
- | 338 | else |
|
- | 339 | tobase_str := tobase_str + Chr(Ord('A') + (i-10)); |
|
- | 340 | end; |
|
- | 341 | ||
- | 342 | len := Length(numstring); |
|
- | 343 | base_convert_bigint := ''; |
|
- | 344 | number := numstring; (* this is a fake "Int8" array (implemented with chars) *) |
|
- | 345 | for i := 0 to len-1 do |
|
- | 346 | begin |
|
- | 347 | number[i+1] := Chr(Pos(UpCase(numstring[i+1]), frombase_str)-1); |
|
- | 348 | end; |
|
- | 349 | res := ''; |
|
- | 350 | repeat (* Loop until whole number is converted *) |
|
- | 351 | divide := 0; |
|
- | 352 | newlen := 0; |
|
- | 353 | for i := 0 to len-1 do (* Perform division manually (which is why this works with big numbers) *) |
|
- | 354 | begin |
|
- | 355 | divide := divide * frombase + Ord(number[i+1]); |
|
- | 356 | if (divide >= tobase) then |
|
- | 357 | begin |
|
- | 358 | number[newlen+1] := Chr(divide div tobase); |
|
- | 359 | Inc(newlen); |
|
- | 360 | divide := divide mod tobase; |
|
- | 361 | end |
|
- | 362 | else if newlen > 0 then |
|
- | 363 | begin |
|
- | 364 | number[newlen+1] := #0; |
|
- | 365 | Inc(newlen); |
|
- | 366 | end; |
|
- | 367 | end; |
|
- | 368 | len := newlen; |
|
- | 369 | res := tobase_str[divide+1] + res; (* Divide is basically $numstring % $tobase (i.e. the new character) *) |
|
- | 370 | until newlen = 0; |
|
- | 371 | base_convert_bigint := res; |
|
- | 372 | end; |
|
264 | 373 | ||
265 | end. |
374 | end. |
266 | 375 |