Subversion Repositories oidplus

Rev

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

  1. unit VTSFUNCS;
  2.  
  3. (************************************************)
  4. (* VTSFUNCS.PAS                                 *)
  5. (* Author:   Daniel Marschall                   *)
  6. (* Revision: 2022-02-20                         *)
  7. (* License:  Apache 2.0                         *)
  8. (* This file contains:                          *)
  9. (* - Various functions                          *)
  10. (************************************************)
  11.  
  12. interface
  13.  
  14. function Max(a, b: integer): integer;
  15. function Min(a, b: integer): integer;
  16.  
  17. function CompareEqualLengthString(a, b: string): integer;
  18. function CompareNumericString(a, b: string): integer;
  19.  
  20. procedure Beep;
  21.  
  22. function Trim(s: string): string;
  23. function TrimLineToWidth(s: string; width: integer): string;
  24. function ZeroPad(i: LongInt; n: integer): string;
  25. function LeftPadStr(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;
  28.  
  29. function DeleteFile(filename: string): boolean;
  30. function FileExists(filename: string): boolean;
  31.  
  32. function StripLeadingZeros(s: string): string;
  33. function IsPositiveIntegerOrZero(s: string): boolean;
  34. function IsBase36String(s: string): boolean;
  35. function StrToInt(s: string): Integer;
  36. function IntToStr(Value: Integer): string;
  37.  
  38. function StringReplace(s, search, replace: string): string;
  39.  
  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.  
  44. implementation
  45.  
  46. uses
  47.   Crt;
  48.  
  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.  
  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
  89.   EqualLength: integer;
  90. begin
  91.   EqualLength := Max(Length(a), Length(b));
  92.   a := LeftPadStr(a, EqualLength, '0');
  93.   b := LeftPadStr(b, EqualLength, '0');
  94.   CompareNumericString := CompareEqualLengthString(a, b);
  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.  
  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.  
  132. function ZeroPad(i: LongInt; n: integer): string;
  133. var
  134.   s: string;
  135. begin
  136.   s := IntToStr(i);
  137.   ZeroPad := LeftPadStr(s, n, '0');
  138. end;
  139.  
  140. function LeftPadStr(s: string; n: integer; ch: char): string;
  141. begin
  142.   while Length(s) < n do
  143.   begin
  144.     s := ch + s;
  145.   end;
  146.   LeftPadStr := s;
  147. end;
  148.  
  149. function RightPadStr(s: string; n: integer; ch: char): string;
  150. begin
  151.   while Length(s) < n do
  152.   begin
  153.     s := s + ch;
  154.   end;
  155.   RightPadStr := s;
  156. end;
  157.  
  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.  
  171. function DeleteFile(filename: string): boolean;
  172. var
  173.   F:  file;
  174.   Ch: Char;
  175. begin
  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;
  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+}
  202.   if IoResult = 0 then
  203.   begin
  204.     Close(F);
  205.     FileExists := true;
  206.   end
  207.   else
  208.   begin
  209.     FileExists := false;
  210.   end;
  211. end;
  212.  
  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.  
  221. function IsPositiveIntegerOrZero(s: string): boolean;
  222. var
  223.   i: integer;
  224. begin
  225.   IsPositiveIntegerOrZero := false;
  226.  
  227.   if Length(s) = 0 then exit;
  228.   (*if (s[1] = '0') and (s <> '0') then exit;*)
  229.   for i := 1 to Length(s) do
  230.   begin
  231.     if not (s[i] in ['0'..'9']) then exit;
  232.   end;
  233.  
  234.   IsPositiveIntegerOrZero := true;
  235. end;
  236.  
  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.  
  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.  
  269. function StringReplace(s, search, replace: string): string;
  270. var
  271.   i: integer;
  272.   output: string;
  273. begin
  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;
  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.  
  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;
  395.     res := tobase_str[divide+1] + res; (* Divide is basically "numstring mod tobase" (i.e. the new character) *)
  396.   until newlen = 0;
  397.   base_convert_bigint := res;
  398. end;
  399.  
  400. end.
  401.