home *** CD-ROM | disk | FTP | other *** search
- {++
-
- u t i l i t y . p a s
- Copyright (c) 1995-1997 by Alexander Staubo, all rights reserved.
-
- Abstract:
-
- Utility functions.
-
- Additional notes:
-
- - The string functions are not optimized.
-
- - StreamReadLn is quite slow unless used on a buffered stream.
-
- --}
-
- {$WEAKPACKAGEUNIT ON}
- {$I+}
- {$IFNDEF Win32}
- !! // 32-bit compilation only.
- {$ENDIF}
-
- unit Utility;
-
- interface
-
- uses
- SysUtils, Classes;
-
- { Types }
-
- type
- TCharSet = set of Char;
-
- { Exception classes }
-
- EApiError =
- class(Exception)
- protected
- FErrorCode : Longint;
- public
- constructor Create (ErrorCode : Longint);
- constructor CreateMsg (ErrorCode : Longint; const Message : string);
- property ErrorCode : Longint read FErrorCode write FErrorCode;
- end;
-
- { System functions }
-
- procedure ApiCheck (Result : Boolean);
- { If Error is True, this function raises an EApiError with the last error
- code and message }
-
- procedure ApiError (ErrorCode : Longint);
- { Raises an EApiError with the specified system error code }
-
- { File utility functions }
-
- function AddFileExt (const S, Ext : string) : string;
- { Add extension to file name if the file name does not already contain an
- extension. Ext must not contain period character }
-
- function ForceFileExt (const S, Ext : string) : string;
- { Add extension to file name, deleting old extension. Equivalent to the
- ChangeFileExt procedure in SysUtils, except Ext must not contain period }
-
- function AssurePath (const Path : string) : Boolean;
- { Assure that all directories in path exist. Equivalent to the
- ForceDirectories function in the Borland FileCtrl unit }
-
- { File string functions }
-
- function AddBkSlash (const S : string) : string;
- { Returns S with backslash added}
-
- function RemBkSlash (const S : string) : string;
- { Returns S with backslash removed}
-
- { Stream utilities }
-
- procedure StreamWriteString (Stream : TStream; const Str : string);
- { Write string Str to stream }
-
- function StreamReadString (Stream : TStream) : string;
- { Read string from stream }
-
- function StreamReadLn (Stream : TStream) : string;
- { Read crlf-terminated line from stream }
-
- procedure StreamWriteLn (Stream : TStream; Str : string);
- { Write crlf-terminated line to stream }
-
- procedure StreamWrite (Stream : TStream; Str : string);
- { Write string to stream }
-
- procedure StreamReadStrings (Stream : TStream; Strings : TStrings);
- { Read list of strings written with StreamWriteStrings from stream }
-
- procedure StreamWriteStrings (Stream : TStream; Strings : TStrings);
- { Write list of strings to stream }
-
- { System functions }
-
- function GetEnvironmentVarStr (const VarName : string) : string;
- { Read variable from environment block of the calling process }
-
- function ExpandEnvironmentStr (const Str : string) : string;
- { Expands variables in Str to their equivalent environment variable values }
-
- function GetUserNameStr : string;
- { Retrieve the user name of the current thread. This is the name of the user
- currently logged onto the system. }
-
- function GetComputerNameStr : string;
- { Retrieve the computer name of the current system. This name is established
- at system startup, when it is initialized from the registry }
-
- function GetTempFileNameStr (const Path, Prefix : string;
- Unique : Longint) : string;
- { Generate a unique temporary file name. If successful, the file is also
- created with zero length. The resulting file name is the concatenation of
- specified path and prefix strings, a hexadecimal string formed from a
- specified integer, and the .TMP extension. If Unique is zero, a random
- number is used for the integer value; otherwise this value is used }
-
- function GetTempPathStr : string;
- { Retrieve the path of the directory designated for temporary files }
-
- function GetSystemDirectoryStr : string;
- { Retrieve system directory }
-
- { Miscellaneous low-level functions }
-
- function LongSub (A, B : Longint) : Longint;
- { Evaluates the unsigned integer expression A-B, returning the result }
-
- { Timing functions. The tick routines avoid problems with 32-bit integers in
- Delphi, providing a separate type for storing the tick value }
-
- type
- TTicks =
- record
- L, H : Word;
- end;
-
- function NullTicks : TTicks;
- { Returns an empty tick value }
-
- function GetTicks : TTicks; stdcall;
- { Get current tick count. Maps to GetTickCount }
-
- function TicksSub (A, B : TTicks) : TTicks;
- { Subtract B ticks from A }
-
- function TicksToInt (Ticks : TTicks) : Integer;
- { Convert ticks to integer }
-
- function TicksToSec (Ticks : TTicks) : Integer;
- { Convert ticks to seconds }
-
- { String utilities }
-
- type
- TWordOptions = set of
- (
- woNoSkipQuotes,
- woNoConsecutiveDelims
- );
-
- function StrGetWord (const S : string; N : Integer;
- const Delims : TCharSet; const Options : TWordOptions) : string;
- { Extracts word number N from string S. Delims specify the characters used to
- delimit words }
-
- function StrWordCount (const S : string; const Delims : TCharSet;
- const Options : TWordOptions) : Integer;
- { Returns number of words in S }
-
- function StrWordPos (const S : string; N : Integer;
- const Delims : TCharSet; const Options : TWordOptions) : Integer;
- { Returns the character position of a word in S }
-
- function UnquoteStr (const Str : string) : string;
- { Removes double quotes ("") from string Str }
-
- function StrCompareWildCards (const A, B : string) : Boolean;
- { Compares two strings using Unix-like wild cards. Both A and B may contain
- the wild cards * and ? }
-
- function ReplaceString (const Str, SubStr, NewStr : string) : string;
- { Replace occurences of SubStr in Str with NewStr }
-
- implementation
-
- uses
- Windows;
-
- { Resource strings }
-
- {$I strconst.inc}
-
- { EApiError }
-
- constructor EApiError.Create (ErrorCode : Longint);
- begin
- inherited CreateFmt(strApiError, [ErrorCode, SysErrorMessage(ErrorCode)]);
- end;
-
- constructor EApiError.CreateMsg (ErrorCode : Longint; const Message : string);
- begin
- inherited CreateFmt(Message, [ErrorCode]);
- end;
-
- { Functions }
-
- procedure ApiCheck (Result : Boolean);
- begin
- if not Result then
- ApiError(GetLastError);
- end;
-
- procedure ApiError (ErrorCode : Longint);
- begin
- raise EApiError.Create(ErrorCode);
- end;
-
- function AddFileExt (const S, Ext : string) : string;
- begin
- if Pos('.', S) > 0 then
- Result:=S
- else
- Result:=S + '.' + Ext;
- end;
-
- function ForceFileExt (const S, Ext : string) : string;
- begin
- if S <> '' then
- Result:=ChangeFileExt(S, '') + '.' + Ext
- else
- Result:='';
- end;
-
- function AssurePath (const Path : string) : Boolean;
- begin
- if (Path = '') or ((Length(Path) = 2) and (Path[2] = ':') and
- (UpCase(Path[1]) in ['A'..'Z'])) then
- Result:=True
- else
- begin
- Result:=False;
- if AssurePath(RemBkSlash(ExtractFilePath(RemBkSlash(Path)))) then
- begin
- try
- MkDir(RemBkSlash(Path));
- except
- on E : EInOutError do
- if (E.ErrorCode <> 0) and
- (E.ErrorCode <> ERROR_ACCESS_DENIED) and
- (E.ErrorCode <> ERROR_ALREADY_EXISTS) then
- Exit;
- end;
- Result:=True;
- end
- end;
- end;
-
- function AddBkSlash (const S : string) : string;
- begin
- if (S = '') or (S[Length(S)] = '\') then
- Result:=S
- else
- Result:=S + '\';
- end;
-
- function RemBkSlash (const S : string) : string;
- begin
- if (S <> '') and (S[Length(S)] = '\') then
- Result:=Copy(S, 1, Length(S) - 1)
- else
- Result:=S;
- end;
-
- procedure StreamWriteString (Stream : TStream; const Str : string);
- var
- Len : Longint;
- begin
- Len:=Length(Str);
- Stream.Write(Len, SizeOf(Len));
- Stream.Write(Str[1], Len);
- end;
-
- function StreamReadString (Stream : TStream) : string;
- var
- Len : Longint;
- begin
- Stream.Read(Len, SizeOf(Len));
- SetLength(Result, Len);
- Stream.Read(Result[1], Len);
- end;
-
- function StreamReadLn (Stream : TStream) : string;
- var
- C : Char;
- begin
- Result:='';
- while True do
- begin
- if Stream.Read(C, SizeOf(C)) = 0 then
- Break;
-
- if C <> #13 then
- if C = #10 then
- Break
- else
- Result:=Result + C;
- end;
- end;
-
- procedure StreamWriteLn (Stream : TStream; Str : string);
- begin
- Str:=Str + ^M^J;
- Stream.Write(Str[1], Length(Str));
- end;
-
- procedure StreamWrite (Stream : TStream; Str : string);
- begin
- Stream.Write(Str[1], Length(Str));
- end;
-
- procedure StreamReadStrings (Stream : TStream; Strings : TStrings);
- var
- I, N : Integer;
- begin
- I:=0;
- Stream.Read(I, SizeOf(I));
- Strings.Clear;
- for N:=0 to I - 1 do
- Strings.Add(StreamReadString(Stream));
- end;
-
- procedure StreamWriteStrings (Stream : TStream; Strings : TStrings);
- var
- I, N : Integer;
- begin
- if Strings <> nil then
- I:=Strings.Count
- else
- I:=0;
- Stream.Write(I, SizeOf(I));
- for N:=0 to I - 1 do
- StreamWriteString(Stream, Strings.Strings[N]);
- end;
-
- function GetEnvironmentVarStr (const VarName : string) : string;
- var
- Buf : array[0..128] of Char;
- Len : Integer;
- begin
- Len:=GetEnvironmentVariable(PChar(VarName), @Buf, SizeOf(Buf));
- if Len > 0 then
- Result:=string(Buf)
- else
- Result:='';
- end;
-
- function ExpandEnvironmentStr (const Str : string) : string;
- var
- Len : Integer;
- Buffer : array[Byte] of Char;
- begin
- Len:=ExpandEnvironmentStrings(PChar(Str), Buffer, SizeOf(Buffer));
- if Len = 0 then
- raise EConvertError.CreateFmt(
- 'Error %d calling ExpandEnvironmentStrings', [GetLastError]);
- Result:=string(Buffer);
- end;
-
- function GetUserNameStr : string;
- var
- Buffer : array[0..127] of Char;
- Len : Integer;
- begin
- Len:=SizeOf(Buffer);
- {
- if GetUserName(@Buffer, Len) then
- Result:=string(Buffer)
- else
- }
- Result:='';
- end;
-
- function GetComputerNameStr : string;
- var
- Buffer : array[0..MAX_COMPUTERNAME_LENGTH - 1] of Char;
- Len : Integer;
- begin
- Len:=SizeOf(Buffer);
- {
- if GetComputerName(@Buffer, Len) then
- Result:=string(Buffer)
- else
- }
- Result:='';
- end;
-
- function GetTempFileNameStr (const Path, Prefix : string;
- Unique : Longint) : string;
- var
- Buffer : array[0..MAX_PATH - 1] of Char;
- begin
- if GetTempFileName(PChar(Path), PChar(Prefix), Unique, @Buffer) <> 0 then
- Result:=string(Buffer)
- else
- Result:=''
- end;
-
- function GetTempPathStr : string;
- var
- Buffer : array[0..MAX_PATH - 1] of Char;
- begin
- if GetTempPath(SizeOf(Buffer) - 1, @Buffer) <> 0 then
- Result:=string(Buffer)
- else
- Result:=''
- end;
-
- function GetSystemDirectoryStr : string;
- var
- Buffer : array[0..MAX_PATH - 1] of Char;
- begin
- if GetSystemDirectory(@Buffer, SizeOf(Buffer) - 1) <> 0 then
- Result:=string(Buffer)
- else
- Result:=''
- end;
-
- function LongSub (A, B : Longint) : Longint;
- asm
- mov eax, A
- mov ebx, B
- sub eax, ebx
- end;
-
- function NullTicks : TTicks;
- asm
- mov eax, 0
- end;
-
- function GetTicks; external 'kernel32.dll' name 'GetTickCount';
-
- function TicksSub (A, B : TTicks) : TTicks;
- asm
- mov eax, A
- mov ebx, B
- sub eax, ebx
- end;
-
- function TicksToInt (Ticks : TTicks) : Integer;
- asm
- mov eax, Ticks
- end;
-
- function TicksToSec (Ticks : TTicks) : Integer;
- begin
- Result:=TicksToInt(Ticks) div 1000;
- end;
-
- function StrGetWord (const S : string; N : Integer;
- const Delims : TCharSet; const Options : TWordOptions) : string;
- var
- I, I0 : Integer;
- QuoteChar : string;
- begin
- I0:=1;
- I:=1;
- if woNoSkipQuotes in Options then
- QuoteChar:=''
- else
- QuoteChar:='"';
- if S <> '' then
- while I <= Length(S) + 1 do
- begin
- if (I > Length(S)) or (S[I] in Delims) then
- begin
- if N > 0 then
- Dec(N);
- if N = 0 then
- begin
- Result:=Copy(S, I0, I - I0);
- if Result <> '' then
- Exit;
- end;
- if woNoConsecutiveDelims in Options then
- I0:=I + 1
- else
- begin
- while (I <= Length(S)) and (S[I] in Delims) do
- Inc(I);
- I0:=I;
- end;
- end;
- if S[I] = QuoteChar then
- begin
- Inc(I);
- while (I <= Length(S)) and (S[I] <> QuoteChar) do
- Inc(I);
- end;
- Inc(I);
- end;
- Result:='';
- end;
-
- function StrWordCount (const S : string; const Delims : TCharSet;
- const Options : TWordOptions) : Integer;
- var
- I : Integer;
- QuoteChar : string;
- begin
- Result:=0;
- I:=1;
- if woNoSkipQuotes in Options then
- QuoteChar:=''
- else
- QuoteChar:='"';
- if S <> '' then
- while I <= Length(S) + 1 do
- begin
- if (I > Length(S)) or (S[I] in Delims) then
- begin
- Inc(Result);
- if not (woNoConsecutiveDelims in Options) then
- while (I <= Length(S)) and (S[I] in Delims) do
- Inc(I);
- end;
- if S[I] = QuoteChar then
- begin
- Inc(I);
- while (I <= Length(S)) and (S[I] <> QuoteChar) do
- Inc(I);
- end;
- Inc(I);
- end;
- end;
-
- function StrWordPos (const S : string; N : Integer;
- const Delims : TCharSet; const Options : TWordOptions) : Integer;
- var
- I : Integer;
- QuoteChar : string;
- begin
- Result:=1;
- I:=1;
- if woNoSkipQuotes in Options then
- QuoteChar:=''
- else
- QuoteChar:='"';
- if S <> '' then
- while (N > 0) and (I <= Length(S)) do
- begin
- if S[I] in Delims then
- begin
- Dec(N);
- if N = 0 then
- Exit;
- if not (woNoConsecutiveDelims in Options) then
- while (I <= Length(S)) and (S[I] in Delims) do
- Inc(I);
- Result:=I;
- end
- else if S[I] = QuoteChar then
- begin
- Inc(I);
- while (I <= Length(S)) and (S[I] <> '"') do
- Inc(I);
- end;
- Inc(I);
- end;
- end;
-
- function UnquoteStr (const Str : string) : string;
- begin
- if (Length(Str) >= 2) and (Str[1] = '"') and (Str[Length(Str)] = '"') then
- Result:=Copy(Str, 2, Length(Str) - 2)
- else
- Result:=Str;
- end;
-
- function StrCompareWildCards (const A, B : string) : Boolean;
- var
- PosA, PosB : Integer;
- begin
- PosA:=1;
- PosB:=1;
- Result:=True;
-
- if (Length(A) = 0) and (Length(B) = 0) then
- Result:=True
- else
- if Length(A) = 0 then
- begin
- if B[1] = '*' then
- Result:=True
- else
- Result:=False
- end
- else if Length(B) = 0 then
- begin
- if A[1] = '*' then
- Result:=True
- else
- Result:=False;
- end;
-
- while (Result = True) and (PosA <= Length(A)) and (PosB <= Length(B)) do
- if (A[PosA] = '?') or (B[PosB] = '?') then
- begin
- Inc(PosA);
- Inc(PosB);
- end
- else if A[PosA] = '*' then
- begin
- Inc(PosA);
- if PosA <= Length(A) then
- begin
- while (PosB <= Length(B)) and not StrCompareWildCards(
- Copy(A, PosA, Length(A) - PosA + 1),
- Copy(B, PosB, Length(B) - PosB + 1)) do
- Inc(PosB);
-
- if PosB > Length(B) then
- Result:=False
- else
- begin
- PosA:=Succ(Length(A));
- PosB:=Succ(Length(B));
- end
- end
- else
- PosB:=Succ(Length(B));
- end
- else if B[PosB] = '*' then
- begin
- Inc(PosB);
- if PosB <= Length(B) then
- begin
- while (PosA <= Length(A)) and not StrCompareWildCards(
- Copy(A, PosA, Length(A) - PosA + 1),
- Copy(B, PosB, Length(B) - PosB + 1)) do
- Inc(PosA);
-
- if PosA > Length(A) then
- Result:=False
- else
- begin
- PosA:=Succ(Length(A));
- PosB:=Succ(Length(B));
- end
- end
- else
- PosA:=Succ(Length(A));
- end
- else if UpCase(A[PosA]) = UpCase(B[PosB]) then
- begin
- Inc(PosA);
- Inc(PosB);
- end
- else
- Result:=False;
-
- if PosA > Length(A) then
- begin
- while (PosB <= Length(B)) and (B[PosB] = '*') do
- Inc(PosB);
-
- if PosB <= Length(B) then
- Result:=False;
- end;
-
- if PosB > Length(B) then
- begin
- while (PosA <= Length(A)) and (A[PosA] = '*') do
- Inc(PosA);
- if PosA <= Length(A) then
- Result:=False;
- end;
- end;
-
- function ReplaceString (const Str, SubStr, NewStr : string) : string;
- var
- I : Integer;
- begin
- Result:=Str;
- while True do
- begin
- I:=Pos(SubStr, Result);
- if I > 0 then
- begin
- Delete(Result, I, Length(SubStr));
- Insert(NewStr, Result, I);
- end
- else
- Break;
- end;
- end;
-
- end.
-
-