home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 March / Chip_2002-03_cd1.bin / zkuste / delphi / kompon / d5 / cak / CAKDIR.ZIP / Utility.pas < prev    next >
Pascal/Delphi Source File  |  2000-06-28  |  17KB  |  708 lines

  1. {++
  2.  
  3. u t i l i t y . p a s
  4. Copyright (c) 1995-1997 by Alexander Staubo, all rights reserved.
  5.  
  6. Abstract:
  7.  
  8.   Utility functions.
  9.  
  10.   Additional notes:
  11.  
  12.   - The string functions are not optimized.
  13.  
  14.   - StreamReadLn is quite slow unless used on a buffered stream.
  15.  
  16. --}
  17.  
  18. {$WEAKPACKAGEUNIT ON}
  19. {$I+}
  20. {$IFNDEF Win32}
  21.   !!  // 32-bit compilation only.
  22. {$ENDIF}
  23.  
  24. unit Utility;
  25.  
  26. interface
  27.  
  28. uses
  29.     SysUtils, Classes;
  30.  
  31. { Types }
  32.  
  33. type
  34.   TCharSet = set of Char;
  35.  
  36. { Exception classes }
  37.  
  38.   EApiError =
  39.     class(Exception)
  40.     protected
  41.       FErrorCode : Longint;
  42.     public
  43.       constructor Create (ErrorCode : Longint); 
  44.       constructor CreateMsg (ErrorCode : Longint; const Message : string);
  45.       property ErrorCode : Longint read FErrorCode write FErrorCode;
  46.     end;
  47.  
  48. { System functions }
  49.  
  50. procedure ApiCheck (Result : Boolean);
  51.   { If Error is True, this function raises an EApiError with the last error
  52.     code and message }
  53.  
  54. procedure ApiError (ErrorCode : Longint);
  55.   { Raises an EApiError with the specified system error code }
  56.  
  57. { File utility functions }
  58.  
  59. function AddFileExt (const S, Ext : string) : string;
  60.     { Add extension to file name if the file name does not already contain an
  61.     extension. Ext must not contain period character }
  62.  
  63. function ForceFileExt (const S, Ext : string) : string;
  64.     { Add extension to file name, deleting old extension. Equivalent to the
  65.     ChangeFileExt procedure in SysUtils, except Ext must not contain period }
  66.  
  67. function AssurePath (const Path : string) : Boolean;
  68.   { Assure that all directories in path exist. Equivalent to the
  69.     ForceDirectories function in the Borland FileCtrl unit }
  70.  
  71. { File string functions }
  72.  
  73. function AddBkSlash (const S : string) : string;
  74.     { Returns S with backslash added}
  75.  
  76. function RemBkSlash (const S : string) : string;
  77.     { Returns S with backslash removed}
  78.  
  79. { Stream utilities }
  80.  
  81. procedure StreamWriteString (Stream : TStream; const Str : string);
  82.   { Write string Str to stream }
  83.  
  84. function StreamReadString (Stream : TStream) : string;
  85.   { Read string from stream }
  86.  
  87. function StreamReadLn (Stream : TStream) : string;
  88.   { Read crlf-terminated line from stream }
  89.  
  90. procedure StreamWriteLn (Stream : TStream; Str : string);
  91.   { Write crlf-terminated line to stream }
  92.  
  93. procedure StreamWrite (Stream : TStream; Str : string);
  94.   { Write string to stream }
  95.  
  96. procedure StreamReadStrings (Stream : TStream; Strings : TStrings);
  97.   { Read list of strings written with StreamWriteStrings from stream }
  98.  
  99. procedure StreamWriteStrings (Stream : TStream; Strings : TStrings);
  100.   { Write list of strings to stream }
  101.  
  102. { System functions }
  103.  
  104. function GetEnvironmentVarStr (const VarName : string) : string;
  105.   { Read variable from environment block of the calling process }
  106.   
  107. function ExpandEnvironmentStr (const Str : string) : string;
  108.   { Expands variables in Str to their equivalent environment variable values }
  109.  
  110. function GetUserNameStr : string;
  111.   { Retrieve the user name of the current thread. This is the name of the user
  112.     currently logged onto the system.  }
  113.  
  114. function GetComputerNameStr : string;
  115.   { Retrieve the computer name of the current system. This name is established
  116.     at system startup, when it is initialized from the registry }
  117.  
  118. function GetTempFileNameStr (const Path, Prefix : string;
  119.   Unique : Longint) : string;
  120.   { Generate a unique temporary file name. If successful, the file is also
  121.     created with zero length. The resulting file name is the concatenation of
  122.     specified path and prefix strings, a hexadecimal string formed from a
  123.     specified integer, and the .TMP extension. If Unique is zero, a random
  124.     number is used for the integer value; otherwise this value is used }
  125.  
  126. function GetTempPathStr : string;
  127.   { Retrieve the path of the directory designated for temporary files }
  128.  
  129. function GetSystemDirectoryStr : string;
  130.   { Retrieve system directory }
  131.  
  132. { Miscellaneous low-level functions }
  133.  
  134. function LongSub (A, B : Longint) : Longint;
  135.   { Evaluates the unsigned integer expression A-B, returning the result }
  136.  
  137. { Timing functions. The tick routines avoid problems with 32-bit integers in
  138.   Delphi, providing a separate type for storing the tick value }
  139.  
  140. type
  141.   TTicks =
  142.     record
  143.       L, H : Word;
  144.     end;
  145.  
  146. function NullTicks : TTicks;
  147.   { Returns an empty tick value }
  148.  
  149. function GetTicks : TTicks; stdcall;
  150.   { Get current tick count. Maps to GetTickCount }
  151.  
  152. function TicksSub (A, B : TTicks) : TTicks;
  153.   { Subtract B ticks from A }
  154.  
  155. function TicksToInt (Ticks : TTicks) : Integer;
  156.   { Convert ticks to integer }
  157.  
  158. function TicksToSec (Ticks : TTicks) : Integer;
  159.   { Convert ticks to seconds }
  160.  
  161. { String utilities }
  162.  
  163. type
  164.   TWordOptions = set of
  165.     (
  166.       woNoSkipQuotes,
  167.       woNoConsecutiveDelims
  168.     );
  169.  
  170. function StrGetWord (const S : string; N : Integer;
  171.   const Delims : TCharSet; const Options : TWordOptions) : string;
  172.   { Extracts word number N from string S. Delims specify the characters used to
  173.     delimit words }
  174.  
  175. function StrWordCount (const S : string; const Delims : TCharSet;
  176.   const Options : TWordOptions) : Integer;
  177.   { Returns number of words in S }
  178.  
  179. function StrWordPos (const S : string; N : Integer;
  180.   const Delims : TCharSet; const Options : TWordOptions) : Integer;
  181.   { Returns the character position of a word in S }
  182.  
  183. function UnquoteStr (const Str : string) : string;
  184.   { Removes double quotes ("") from string Str }
  185.  
  186. function StrCompareWildCards (const A, B : string) : Boolean;
  187.   { Compares two strings using Unix-like wild cards. Both A and B may contain
  188.     the wild cards * and ? }
  189.  
  190. function ReplaceString (const Str, SubStr, NewStr : string) : string;
  191.   { Replace occurences of SubStr in Str with NewStr }
  192.  
  193. implementation
  194.  
  195. uses
  196.     Windows;
  197.  
  198. { Resource strings }
  199.  
  200. {$I strconst.inc}
  201.  
  202. { EApiError }
  203.  
  204. constructor EApiError.Create (ErrorCode : Longint);
  205. begin
  206.   inherited CreateFmt(strApiError, [ErrorCode, SysErrorMessage(ErrorCode)]);
  207. end;
  208.  
  209. constructor EApiError.CreateMsg (ErrorCode : Longint; const Message : string);
  210. begin
  211.   inherited CreateFmt(Message, [ErrorCode]);
  212. end;
  213.  
  214. { Functions }
  215.  
  216. procedure ApiCheck (Result : Boolean);
  217. begin
  218.   if not Result then
  219.     ApiError(GetLastError);
  220. end;
  221.  
  222. procedure ApiError (ErrorCode : Longint);
  223. begin
  224.   raise EApiError.Create(ErrorCode);
  225. end;
  226.  
  227. function AddFileExt (const S, Ext : string) : string;
  228. begin
  229.     if Pos('.', S) > 0 then
  230.         Result:=S
  231.     else
  232.         Result:=S + '.' + Ext;
  233. end;
  234.  
  235. function ForceFileExt (const S, Ext : string) : string;
  236. begin
  237.   if S <> '' then
  238.     Result:=ChangeFileExt(S, '') + '.' + Ext
  239.   else
  240.     Result:='';
  241. end;
  242.  
  243. function AssurePath (const Path : string) : Boolean;
  244. begin
  245.     if (Path = '') or ((Length(Path) = 2) and (Path[2] = ':') and
  246.     (UpCase(Path[1]) in ['A'..'Z'])) then
  247.         Result:=True
  248.     else
  249.     begin
  250.       Result:=False;
  251.       if AssurePath(RemBkSlash(ExtractFilePath(RemBkSlash(Path)))) then
  252.         begin
  253.           try
  254.             MkDir(RemBkSlash(Path));
  255.           except
  256.             on E : EInOutError do
  257.               if (E.ErrorCode <> 0) and
  258.                  (E.ErrorCode <> ERROR_ACCESS_DENIED) and
  259.                  (E.ErrorCode <> ERROR_ALREADY_EXISTS) then
  260.                 Exit;
  261.             end;
  262.           Result:=True;
  263.         end
  264.     end;
  265. end;
  266.  
  267. function AddBkSlash (const S : string) : string;
  268. begin
  269.     if (S = '') or (S[Length(S)] = '\') then
  270.       Result:=S
  271.   else
  272.       Result:=S + '\';
  273. end;
  274.  
  275. function RemBkSlash (const S : string) : string;
  276. begin
  277.     if (S <> '') and (S[Length(S)] = '\') then
  278.       Result:=Copy(S, 1, Length(S) - 1)
  279.   else
  280.       Result:=S;
  281. end;
  282.  
  283. procedure StreamWriteString (Stream : TStream; const Str : string);
  284. var
  285.     Len : Longint;
  286. begin
  287.     Len:=Length(Str);
  288.     Stream.Write(Len, SizeOf(Len));
  289.     Stream.Write(Str[1], Len);
  290. end;
  291.  
  292. function StreamReadString (Stream : TStream) : string;
  293. var
  294.     Len : Longint;
  295. begin
  296.     Stream.Read(Len, SizeOf(Len));
  297.     SetLength(Result, Len);
  298.     Stream.Read(Result[1], Len);
  299. end;
  300.  
  301. function StreamReadLn (Stream : TStream) : string;
  302. var
  303.     C : Char;
  304. begin
  305.     Result:='';
  306.     while True do
  307.         begin
  308.             if Stream.Read(C, SizeOf(C)) = 0 then
  309.                 Break;
  310.  
  311.             if C <> #13 then
  312.                 if C = #10 then
  313.                     Break
  314.                 else
  315.                     Result:=Result + C;
  316.         end;
  317. end;
  318.  
  319. procedure StreamWriteLn (Stream : TStream; Str : string);
  320. begin
  321.     Str:=Str + ^M^J;
  322.     Stream.Write(Str[1], Length(Str));
  323. end;
  324.  
  325. procedure StreamWrite (Stream : TStream; Str : string);
  326. begin
  327.     Stream.Write(Str[1], Length(Str));
  328. end;
  329.  
  330. procedure StreamReadStrings (Stream : TStream; Strings : TStrings);
  331. var
  332.   I, N : Integer;
  333. begin
  334.   I:=0;
  335.   Stream.Read(I, SizeOf(I));
  336.   Strings.Clear;
  337.   for N:=0 to I - 1 do
  338.     Strings.Add(StreamReadString(Stream));
  339. end;
  340.  
  341. procedure StreamWriteStrings (Stream : TStream; Strings : TStrings);
  342. var
  343.   I, N : Integer;
  344. begin
  345.   if Strings <> nil then
  346.     I:=Strings.Count
  347.   else
  348.     I:=0;
  349.   Stream.Write(I, SizeOf(I));
  350.   for N:=0 to I - 1 do
  351.     StreamWriteString(Stream, Strings.Strings[N]);
  352. end;
  353.  
  354. function GetEnvironmentVarStr (const VarName : string) : string;
  355. var
  356.     Buf : array[0..128] of Char;
  357.     Len : Integer;
  358. begin
  359.     Len:=GetEnvironmentVariable(PChar(VarName), @Buf, SizeOf(Buf));
  360.     if Len > 0 then
  361.         Result:=string(Buf)
  362.     else
  363.         Result:='';
  364. end;
  365.  
  366. function ExpandEnvironmentStr (const Str : string) : string;
  367. var
  368.   Len : Integer;
  369.   Buffer : array[Byte] of Char;
  370. begin
  371.   Len:=ExpandEnvironmentStrings(PChar(Str), Buffer, SizeOf(Buffer));
  372.   if Len = 0 then
  373.     raise EConvertError.CreateFmt(
  374.       'Error %d calling ExpandEnvironmentStrings', [GetLastError]);
  375.   Result:=string(Buffer);
  376. end;
  377.  
  378. function GetUserNameStr : string;
  379. var
  380.   Buffer : array[0..127] of Char;
  381.   Len : Integer;
  382. begin
  383.   Len:=SizeOf(Buffer);
  384. {
  385.   if GetUserName(@Buffer, Len) then
  386.     Result:=string(Buffer)
  387.   else
  388. }
  389.     Result:='';
  390. end;
  391.  
  392. function GetComputerNameStr : string;
  393. var
  394.   Buffer : array[0..MAX_COMPUTERNAME_LENGTH - 1] of Char;
  395.   Len : Integer;
  396. begin
  397.   Len:=SizeOf(Buffer);
  398. {
  399.   if GetComputerName(@Buffer, Len) then
  400.     Result:=string(Buffer)
  401.   else
  402. }  
  403.     Result:='';
  404. end;
  405.  
  406. function GetTempFileNameStr (const Path, Prefix : string;
  407.   Unique : Longint) : string;
  408. var
  409.   Buffer : array[0..MAX_PATH - 1] of Char;
  410. begin
  411.   if GetTempFileName(PChar(Path), PChar(Prefix), Unique, @Buffer) <> 0 then
  412.     Result:=string(Buffer)
  413.   else
  414.     Result:=''
  415. end;
  416.  
  417. function GetTempPathStr : string;
  418. var
  419.   Buffer : array[0..MAX_PATH - 1] of Char;
  420. begin
  421.   if GetTempPath(SizeOf(Buffer) - 1, @Buffer) <> 0 then
  422.     Result:=string(Buffer)
  423.   else
  424.     Result:=''
  425. end;
  426.  
  427. function GetSystemDirectoryStr : string;
  428. var
  429.   Buffer : array[0..MAX_PATH - 1] of Char;
  430. begin
  431.   if GetSystemDirectory(@Buffer, SizeOf(Buffer) - 1) <> 0 then
  432.     Result:=string(Buffer)
  433.   else
  434.     Result:=''
  435. end;
  436.  
  437. function LongSub (A, B : Longint) : Longint;
  438. asm
  439.   mov eax, A
  440.   mov ebx, B
  441.   sub eax, ebx
  442. end;
  443.  
  444. function NullTicks : TTicks;
  445. asm
  446.   mov eax, 0
  447. end;
  448.  
  449. function GetTicks; external 'kernel32.dll' name 'GetTickCount';
  450.  
  451. function TicksSub (A, B : TTicks) : TTicks;
  452. asm
  453.   mov eax, A
  454.   mov ebx, B
  455.   sub eax, ebx
  456. end;
  457.  
  458. function TicksToInt (Ticks : TTicks) : Integer;
  459. asm
  460.   mov eax, Ticks
  461. end;
  462.  
  463. function TicksToSec (Ticks : TTicks) : Integer;
  464. begin
  465.   Result:=TicksToInt(Ticks) div 1000;
  466. end;
  467.  
  468. function StrGetWord (const S : string; N : Integer;
  469.   const Delims : TCharSet; const Options : TWordOptions) : string;
  470. var
  471.   I, I0 : Integer;
  472.   QuoteChar : string;
  473. begin
  474.   I0:=1;
  475.   I:=1;
  476.   if woNoSkipQuotes in Options then
  477.     QuoteChar:=''
  478.   else
  479.     QuoteChar:='"';
  480.   if S <> '' then
  481.     while I <= Length(S) + 1 do
  482.       begin
  483.         if (I > Length(S)) or (S[I] in Delims) then
  484.           begin
  485.             if N > 0 then
  486.               Dec(N);
  487.             if N = 0 then
  488.               begin
  489.                 Result:=Copy(S, I0, I - I0);
  490.                 if Result <> '' then
  491.                   Exit;
  492.               end;
  493.             if woNoConsecutiveDelims in Options then
  494.               I0:=I + 1
  495.             else
  496.               begin
  497.                 while (I <= Length(S)) and (S[I] in Delims) do
  498.                   Inc(I);
  499.                 I0:=I;
  500.               end;
  501.           end;
  502.         if S[I] = QuoteChar then
  503.           begin
  504.             Inc(I);
  505.             while (I <= Length(S)) and (S[I] <> QuoteChar) do
  506.               Inc(I);
  507.           end;
  508.         Inc(I);
  509.       end;
  510.   Result:='';
  511. end;
  512.  
  513. function StrWordCount (const S : string; const Delims : TCharSet;
  514.   const Options : TWordOptions) : Integer;
  515. var
  516.   I : Integer;
  517.   QuoteChar : string;
  518. begin
  519.   Result:=0;
  520.   I:=1;
  521.   if woNoSkipQuotes in Options then
  522.     QuoteChar:=''
  523.   else
  524.     QuoteChar:='"';
  525.   if S <> '' then
  526.     while I <= Length(S) + 1 do
  527.       begin
  528.         if (I > Length(S)) or (S[I] in Delims) then
  529.           begin
  530.             Inc(Result);
  531.             if not (woNoConsecutiveDelims in Options) then
  532.               while (I <= Length(S)) and (S[I] in Delims) do
  533.                 Inc(I);
  534.           end;
  535.         if S[I] = QuoteChar then
  536.           begin
  537.             Inc(I);
  538.             while (I <= Length(S)) and (S[I] <> QuoteChar) do
  539.               Inc(I);
  540.           end;
  541.         Inc(I);
  542.       end;
  543. end;
  544.  
  545. function StrWordPos (const S : string; N : Integer;
  546.   const Delims : TCharSet; const Options : TWordOptions) : Integer;
  547. var
  548.   I : Integer;
  549.   QuoteChar : string;
  550. begin
  551.   Result:=1;
  552.   I:=1;
  553.   if woNoSkipQuotes in Options then
  554.     QuoteChar:=''
  555.   else
  556.     QuoteChar:='"';
  557.   if S <> '' then
  558.     while (N > 0) and (I <= Length(S)) do
  559.       begin
  560.         if S[I] in Delims then
  561.           begin
  562.             Dec(N);
  563.             if N = 0 then
  564.               Exit;
  565.             if not (woNoConsecutiveDelims in Options) then
  566.               while (I <= Length(S)) and (S[I] in Delims) do
  567.                 Inc(I);
  568.             Result:=I;
  569.           end
  570.         else if S[I] = QuoteChar then
  571.           begin
  572.             Inc(I);
  573.             while (I <= Length(S)) and (S[I] <> '"') do
  574.               Inc(I);
  575.           end;
  576.         Inc(I);
  577.       end;
  578. end;
  579.  
  580. function UnquoteStr (const Str : string) : string;
  581. begin
  582.   if (Length(Str) >= 2) and (Str[1] = '"') and (Str[Length(Str)] = '"') then
  583.     Result:=Copy(Str, 2, Length(Str) - 2)
  584.   else
  585.     Result:=Str;
  586. end;
  587.  
  588. function StrCompareWildCards (const A, B : string) : Boolean;
  589. var
  590.     PosA, PosB : Integer;
  591. begin
  592.     PosA:=1;
  593.     PosB:=1;
  594.     Result:=True;
  595.  
  596.     if (Length(A) = 0) and (Length(B) = 0) then
  597.         Result:=True
  598.     else
  599.         if Length(A) = 0 then
  600.             begin
  601.         if B[1] = '*' then
  602.                   Result:=True
  603.               else
  604.                   Result:=False
  605.       end
  606.         else if Length(B) = 0 then
  607.             begin
  608.         if A[1] = '*' then
  609.                   Result:=True
  610.               else
  611.                   Result:=False;
  612.       end;
  613.         
  614.     while (Result = True) and (PosA <= Length(A)) and (PosB <= Length(B)) do
  615.         if (A[PosA] = '?') or (B[PosB] = '?') then
  616.             begin
  617.                 Inc(PosA);
  618.                 Inc(PosB);
  619.             end
  620.         else if A[PosA] = '*' then
  621.             begin
  622.                 Inc(PosA);
  623.                 if PosA <= Length(A) then
  624.                     begin
  625.                         while (PosB <= Length(B)) and not StrCompareWildCards(
  626.               Copy(A, PosA, Length(A) - PosA + 1),
  627.               Copy(B, PosB, Length(B) - PosB + 1)) do
  628.                             Inc(PosB);
  629.  
  630.                         if PosB > Length(B) then
  631.                             Result:=False
  632.                         else
  633.                             begin
  634.                                 PosA:=Succ(Length(A));
  635.                                 PosB:=Succ(Length(B));
  636.                             end
  637.                     end
  638.                 else
  639.                     PosB:=Succ(Length(B));
  640.             end
  641.         else if B[PosB] = '*' then
  642.             begin
  643.                 Inc(PosB);
  644.                 if PosB <= Length(B) then
  645.                     begin
  646.                         while (PosA <= Length(A)) and not StrCompareWildCards(
  647.               Copy(A, PosA, Length(A) - PosA + 1),
  648.               Copy(B, PosB, Length(B) - PosB + 1)) do
  649.                             Inc(PosA);
  650.  
  651.                         if PosA > Length(A) then
  652.                             Result:=False
  653.                         else
  654.                             begin
  655.                                 PosA:=Succ(Length(A));
  656.                                 PosB:=Succ(Length(B));
  657.                             end
  658.                     end
  659.                 else
  660.                     PosA:=Succ(Length(A));
  661.             end
  662.         else if UpCase(A[PosA]) = UpCase(B[PosB]) then
  663.             begin
  664.                 Inc(PosA);
  665.                 Inc(PosB);
  666.             end
  667.         else
  668.             Result:=False;
  669.  
  670.     if PosA > Length(A) then
  671.         begin
  672.             while (PosB <= Length(B)) and (B[PosB] = '*') do
  673.                 Inc(PosB);
  674.  
  675.             if PosB <= Length(B) then
  676.                 Result:=False;
  677.         end;
  678.  
  679.     if PosB > Length(B) then
  680.         begin
  681.             while (PosA <= Length(A)) and (A[PosA] = '*') do
  682.                 Inc(PosA);
  683.             if PosA <= Length(A) then
  684.                 Result:=False;
  685.         end;
  686. end;
  687.  
  688. function ReplaceString (const Str, SubStr, NewStr : string) : string;
  689. var
  690.   I : Integer;
  691. begin
  692.   Result:=Str;
  693.   while True do
  694.     begin
  695.       I:=Pos(SubStr, Result);
  696.       if I > 0 then
  697.         begin
  698.           Delete(Result, I, Length(SubStr));
  699.           Insert(NewStr, Result, I);
  700.         end
  701.       else
  702.         Break;
  703.     end;
  704. end;
  705.  
  706. end.
  707.  
  708.