Subversion Repositories oidplus

Rev

Rev 748 | Rev 750 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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