Site hosted by Angelfire.com: Build your free website today!

Home
DelphiZeus
SmallUtils.pas Version 2
Utility function Unit

Home



SmallUtils.pas is a subsitute for Delphi SysUtils, it Does Not have all of the functions and procedures in SysUtils, but does have many of the functions used in these examples. You can use this unit if a small file size for your Application is important to you, since it does not add the 20 Kb that SysUtils does when it initializes. If you need more functions then you can just use SysUtils or copy the functions from SysUtils into this. If you need the string "Format" functions you may as well use SysUtils. The 20 Kb that SysUtils adds is NOT wasted Kb, adding error messages and string Format and many other good things.

  Download version 2 as a zipped file   smallUtils.zip

unit SmallUtils;
{version 2}

interface

uses Windows;

type
TdriveSize = record
    FreeS:Int64;
    TotalS:Int64;
end;

TWinVerRec = Record
  WinPlatform: Integer;
  WinMajorVersion: Integer;
  WinMinorVersion: Integer;
  WinBuildNumber: Integer;
  WinCSDVersion: String;
end;

function AllocPadedMem(Size: Cardinal): Pointer;
procedure FreePadedMem(var P: Pointer); overload;
procedure FreePadedMem(var P: PChar); overload;
function CheckPadedMem(P: Pointer): Byte;
function GetPadMemSize(P: Pointer): Cardinal;
{padded memory functions}

function AllocMem(Size: Cardinal): Pointer;
function StrLen(const Str: PChar): Cardinal;
function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar;
function StrECopy(Dest:PChar; const Source: PChar): PChar;
function StrCopy(Dest: PChar; const Source: PChar): PChar;
function StrEnd(const Str: PChar): PChar; assembler;
function StrScan(const Str: PChar; Chr: Char): PChar;
function StrMove(Dest: PChar; const Source: PChar; Count: Cardinal): PChar; assembler;
function PCharLength(const Str: PChar): Cardinal;
function PCharUpper(Str: PChar): PChar; assembler;
function PCharLower(Str: PChar): PChar; assembler;
function StrCat(Dest: PChar; const Source: PChar): PChar;
{the functions above are like the SysUtils functions}

function LastDelimiter(const Delimiters, S: String): Integer;
function CopyTail(const S : String; Len : Integer) : String;
function Int2Thos(I : Int64) : String;
{puts commas into a string for thousands}
function UpperCase(const S: String): String;
function LowerCase(const S: string): String;
function CompareText(const S1, S2: string): Integer;
function SameText(const S1, S2: string): Boolean;
{4 functions above are like the SysUtils}

{Int2Str is like the IntToStr}
function Int2Str(Value : Int64) : String;
function Str2Int(const Value : String) : Int64;
function Str2IntDef(const S: string; Default: Int64): Int64;
  // str2IntDef will return a default value if the string is not an integer
function GetFileExt(const FileName: String): String;
function GetFilePath(const FileName: String): String;
function GetFileName(const FileName: String): String;
{3 functions above are like the ExtractFileExt, ExtractFileName, etc.}
function ChangeExt(const FileName, Extension: String): String;
function AdjustLineBreaks(const S: string): string;
function GetWindowStr(WinHandle: HWND): String;
{function above return the text in the window Handle of WinHandle
as a String}

function DiskSpace(Drive: String): TdriveSize;
{DiskSpace is like the DiskFree and DiskSize in one function}
function FileExists(FileName : String) : Boolean;
function FileSize(FileName:String):Int64;
function DirectoryExists(const Name: string): Boolean;
function SysErrorMessage(ErrorCode: Integer): string;
{for API you get Error codes from GetLastError, this will convert
it to an Error string}
function ShortPathName(const LongName: string): string;
function GetWindowVer: TWinVerRec;
{you can use GetWindowVer to get Version Info
Win32Platform = VER_PLATFORM_WIN32_NT for NT and Win2000
Win32Platform = VER_PLATFORM_WIN32_WINDOWS for Win 95/98/Me}

var
  GetDiskFreeSpaceEx: function (Directory: PChar; var FreeAvailable,
    TotalSpace: Int64; TotalFree: PLargeInteger): Boolean stdcall = nil;

    {FreePadedMem: procedure(var P: Pointer) = FreePadedMem1; overload;
    FreePadedMem: procedure(var P: PChar) = FreePadedMem1; overload;}


implementation

uses
Messages;

function AllocMem(Size: Cardinal): Pointer;
begin
  GetMem(Result, Size);
  FillChar(Result^, Size, 0);
end;

function AllocPadedMem(Size: Cardinal): Pointer;
begin
if Size = 0 then
  begin
  Result := nil;
  MessageBox(0,'Can not Create a 0 length memory block, Size must be One or more',
             'Size must be larger than Zero',MB_OK);
  Exit;
  end;
Inc(Size,12);
GetMem(Result, Size);
Cardinal(Result^) := Size;
Cardinal(Pointer(Cardinal(Result)+4)^):= $FFFFFFFE;
Cardinal(pointer(Cardinal(Result)+Size-4)^) := $FFFFFFFD;
Result := Pointer(Cardinal(Result)+8);
FillChar(Result^, Size-12, 0);
end;

function CheckPadedMem(P: Pointer): Byte;
var
Size: Cardinal;
begin
if P = nil then
  begin
  Result := 1;
  Exit;
  end;
if Cardinal(pointer(Cardinal(P)-4)^) <> $FFFFFFFE then
  begin
  Result := 2;
  Exit;
  end;

Size := Cardinal(pointer(Cardinal(P)-8)^);
if Cardinal(pointer(Cardinal(P)+Size-12)^) <> $FFFFFFFD then
  begin
  Result := 3;
  Exit;
  end;
Result := 0;
end;

procedure FreePadedMem(var P: Pointer);
begin
if P = nil then Exit;
P := Pointer(Cardinal(P)-8);
ReallocMem(P,0);
end;

procedure FreePadedMem(var P: PChar);
begin
if P = nil then Exit;
P := Pointer(Cardinal(P)-8);
ReallocMem(P,0);
end;

function GetPadMemSize(P: Pointer): Cardinal;
begin
if CheckPadedMem(P) > 0 then
  begin
  Result := 0;
  Exit;
  end;
Result := Cardinal(pointer(Cardinal(P)-8)^);
if Result < 13 then
  begin
  Result := 0;
  Exit;
  end;

Result := Result -12;
end;

function StrLen(const Str: PChar): Cardinal; assembler;
asm
        MOV     EDX,EDI
        MOV     EDI,EAX
        MOV     ECX,0FFFFFFFFH
        XOR     AL,AL
        REPNE   SCASB
        MOV     EAX,0FFFFFFFEH
        SUB     EAX,ECX
        MOV     EDI,EDX
end;

function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar; assembler;
asm
        PUSH    EDI
        PUSH    ESI
        PUSH    EBX
        MOV     ESI,EAX
        MOV     EDI,EDX
        MOV     EBX,ECX
        XOR     AL,AL
        TEST    ECX,ECX
        JZ      @@1
        REPNE   SCASB
        JNE     @@1
        INC     ECX
@@1:    SUB     EBX,ECX
        MOV     EDI,ESI
        MOV     ESI,EDX
        MOV     EDX,EDI
        MOV     ECX,EBX
        SHR     ECX,2
        REP     MOVSD
        MOV     ECX,EBX
        AND     ECX,3
        REP     MOVSB
        STOSB
        MOV     EAX,EDX
        POP     EBX
        POP     ESI
        POP     EDI
end;

function StrCopy(Dest: PChar; const Source: PChar): PChar; assembler;
asm
        PUSH    EDI
        PUSH    ESI
        MOV     ESI,EAX
        MOV     EDI,EDX
        MOV     ECX,0FFFFFFFFH
        XOR     AL,AL
        REPNE   SCASB
        NOT     ECX
        MOV     EDI,ESI
        MOV     ESI,EDX
        MOV     EDX,ECX
        MOV     EAX,EDI
        SHR     ECX,2
        REP     MOVSD
        MOV     ECX,EDX
        AND     ECX,3
        REP     MOVSB
        POP     ESI
        POP     EDI
end;

function StrECopy(Dest: PChar; const Source: PChar): PChar; assembler;
asm
        PUSH    EDI
        PUSH    ESI
        MOV     ESI,EAX
        MOV     EDI,EDX
        MOV     ECX,0FFFFFFFFH
        XOR     AL,AL
        REPNE   SCASB
        NOT     ECX
        MOV     EDI,ESI
        MOV     ESI,EDX
        MOV     EDX,ECX
        SHR     ECX,2
        REP     MOVSD
        MOV     ECX,EDX
        AND     ECX,3
        REP     MOVSB
        LEA     EAX,[EDI-1]
        POP     ESI
        POP     EDI
end;

function StrEnd(const Str: PChar): PChar; assembler;
asm
        MOV     EDX,EDI
        MOV     EDI,EAX
        MOV     ECX,0FFFFFFFFH
        XOR     AL,AL
        REPNE   SCASB
        LEA     EAX,[EDI-1]
        MOV     EDI,EDX
end;

function StrScan(const Str: PChar; Chr: Char): PChar; assembler;
asm
        PUSH    EDI
        PUSH    EAX
        MOV     EDI,Str
        MOV     ECX,0FFFFFFFFH
        XOR     AL,AL
        REPNE   SCASB
        NOT     ECX
        POP     EDI
        MOV     AL,Chr
        REPNE   SCASB
        MOV     EAX,0
        JNE     @@1
        MOV     EAX,EDI
        DEC     EAX
@@1:    POP     EDI
end;

function StrMove(Dest: PChar; const Source: PChar; Count: Cardinal): PChar; assembler;
asm
        PUSH    ESI
        PUSH    EDI
        MOV     ESI,EDX
        MOV     EDI,EAX
        MOV     EDX,ECX
        CMP     EDI,ESI
        JA      @@1
        JE      @@2
        SHR     ECX,2
        REP     MOVSD
        MOV     ECX,EDX
        AND     ECX,3
        REP     MOVSB
        JMP     @@2
@@1:    LEA     ESI,[ESI+ECX-1]
        LEA     EDI,[EDI+ECX-1]
        AND     ECX,3
        STD
        REP     MOVSB
        SUB     ESI,3
        SUB     EDI,3
        MOV     ECX,EDX
        SHR     ECX,2
        REP     MOVSD
        CLD
@@2:    POP     EDI
        POP     ESI
end;

function PCharLength(const Str: PChar): Cardinal; assembler;
asm
        MOV     EDX,EDI
        MOV     EDI,EAX
        MOV     ECX,0FFFFFFFFH
        XOR     AL,AL
        REPNE   SCASB
        MOV     EAX,0FFFFFFFEH
        SUB     EAX,ECX
        MOV     EDI,EDX
end;

function PCharUpper(Str: PChar): PChar; assembler;
asm
        PUSH    ESI
        MOV     ESI,Str
        MOV     EDX,Str
@@1:    LODSB
        OR      AL,AL
        JE      @@2
        CMP     AL,'a'
        JB      @@1
        CMP     AL,'z'
        JA      @@1
        SUB     AL,20H
        MOV     [ESI-1],AL
        JMP     @@1
@@2:    XCHG    EAX,EDX
        POP     ESI
end;

function PCharLower(Str: PChar): PChar; assembler;
asm
        PUSH    ESI
        MOV     ESI,Str
        MOV     EDX,Str
@@1:    LODSB
        OR      AL,AL
        JE      @@2
        CMP     AL,'A'
        JB      @@1
        CMP     AL,'Z'
        JA      @@1
        ADD     AL,20H
        MOV     [ESI-1],AL
        JMP     @@1
@@2:    XCHG    EAX,EDX
        POP     ESI
end;

function StrCat(Dest: PChar; const Source: PChar): PChar;
begin
  StrCopy(StrEnd(Dest), Source);
  Result := Dest;
end;

function LastDelimiter(const Delimiters, S: string): Integer;
var
  P: PChar;
begin
  Result := Length(S);
  P := PChar(Delimiters);
  while Result > 0 do
  begin
    if (S[Result] <> #0) and (StrScan(P, S[Result]) <> nil) then
      {if (ByteType(S, Result) = mbTrailByte) then
        Dec(Result)
      else}
        Exit;
    Dec(Result);
  end;
end;

function CopyTail(const S : String; Len : Integer): String;
var L : Integer;
begin
  L := Length( S );
  if L < Len then
     Len := L;
  Result := '';
  if Len = 0 then Exit;
  Result := Copy( S, L - Len + 1, Len );
end;

function CompareText(const S1, S2: string): Integer; assembler;
asm
        PUSH    ESI
        PUSH    EDI
        PUSH    EBX
        MOV     ESI,EAX
        MOV     EDI,EDX
        OR      EAX,EAX
        JE      @@0
        MOV     EAX,[EAX-4]
@@0:    OR      EDX,EDX
        JE      @@1
        MOV     EDX,[EDX-4]
@@1:    MOV     ECX,EAX
        CMP     ECX,EDX
        JBE     @@2
        MOV     ECX,EDX
@@2:    CMP     ECX,ECX
@@3:    REPE    CMPSB
        JE      @@6
        MOV     BL,BYTE PTR [ESI-1]
        CMP     BL,'a'
        JB      @@4
        CMP     BL,'z'
        JA      @@4
        SUB     BL,20H
@@4:    MOV     BH,BYTE PTR [EDI-1]
        CMP     BH,'a'
        JB      @@5
        CMP     BH,'z'
        JA      @@5
        SUB     BH,20H
@@5:    CMP     BL,BH
        JE      @@3
        MOVZX   EAX,BL
        MOVZX   EDX,BH
@@6:    SUB     EAX,EDX
        POP     EBX
        POP     EDI
        POP     ESI
end;

function SameText(const S1, S2: string): Boolean; assembler;
asm
        CMP     EAX,EDX
        JZ      @1
        OR      EAX,EAX
        JZ      @2
        OR      EDX,EDX
        JZ      @3
        MOV     ECX,[EAX-4]
        CMP     ECX,[EDX-4]
        JNE     @3
        CALL    CompareText
        TEST    EAX,EAX
        JNZ     @3
@1:     MOV     AL,1
@2:     RET
@3:     XOR     EAX,EAX
end;

function Int2Thos(I : Int64): String;
var S : String;
begin
  S := Int2Str( I );
  Result := '';
  while S <> '' do
  begin
    if Result <> '' then
       Result := ',' + Result;
    Result := CopyTail( S, 3 ) + Result;
    S := Copy( S, 1, Length( S ) - 3 );
  end;
end;

function GetFileExt(const FileName: string): string;
var
  I: Integer;
begin
  I := LastDelimiter('.\:', FileName);
  if (I > 0) and (FileName[I] = '.') then
    Result := Copy(FileName, I, MaxInt) else
    Result := '';
end;

function GetFilePath(const FileName: string): string;
var
  I: Integer;
begin
  I := LastDelimiter('\:', FileName);
  Result := Copy(FileName, 1, I);
end;

function GetFileName(const FileName: string): string;
var
  I: Integer;
begin
  I := LastDelimiter('\:', FileName);
  Result := Copy(FileName, I + 1, MaxInt);
end;

function ChangeExt(const FileName, Extension: string): string;
  // Extention needs a period like '.exe'
var
  I: Integer;
begin
  I := LastDelimiter('.\:',Filename);
  if (I = 0) or (FileName[I] <> '.') then I := MaxInt;
  Result := Copy(FileName, 1, I - 1) + Extension;
end;

function UpperCase(const S: string): string;
var I : Integer;
begin
  Result := S;
  for I := 1 to Length( S ) do
    if Result[ I ] in [ 'a'..'z' ] then
       Dec( Result[ I ], 32 );
end;

function LowerCase(const S: string): string;
var
  Ch: Char;
  L: Integer;
  Source, Dest: PChar;
begin
  L := Length(S);
  SetLength(Result, L);
  Source := Pointer(S);
  Dest := Pointer(Result);
  while L <> 0 do
  begin
    Ch := Source^;
    if (Ch >= 'A') and (Ch <= 'Z') then Inc(Ch, 32);
    Dest^ := Ch;
    Inc(Source);
    Inc(Dest);
    Dec(L);
  end;
end;

function AdjustLineBreaks(const S: string): string;
var
  Source, SourceEnd, Dest: PChar;
  Extra: Integer;
begin
  Source := Pointer(S);
  SourceEnd := Source + Length(S);
  Extra := 0;
  while Source < SourceEnd do
  begin
    case Source^ of
      #10:
        Inc(Extra);
      #13:
        if Source[1] = #10 then Inc(Source) else Inc(Extra);
    end;
    Inc(Source);
  end;
  if Extra = 0 then Result := S else
  begin
    Source := Pointer(S);
    SetString(Result, nil, SourceEnd - Source + Extra);
    Dest := Pointer(Result);
    while Source < SourceEnd do
      case Source^ of
        #10:
          begin
            Dest^ := #13;
            Inc(Dest);
            Dest^ := #10;
            Inc(Dest);
            Inc(Source);
          end;
        #13:
          begin
            Dest^ := #13;
            Inc(Dest);
            Dest^ := #10;
            Inc(Dest);
            Inc(Source);
            if Source^ = #10 then Inc(Source);
          end;
      else
        Dest^ := Source^;
        Inc(Dest);
        Inc(Source);
      end;
  end;
end;

function GetWindowStr(WinHandle: HWND): String;
var
ResultStr: String;
begin
SetLength(ResultStr, GetWindowTextLength(WinHandle));
GetWindowText(WinHandle,@ResultStr[1],Length(ResultStr)+1);
Result := ResultStr;
//UniqueString(Result);
ResultStr := '';
end;

function Int2Str( Value : Int64 ) : String;
var Minus : Boolean;
begin
   Result := '';
   if Value = 0 then
      Result := '0';
   Minus := Value < 0;
   if Minus then
      Value := -Value;
   while Value > 0 do
   begin
      Result := Char( (Value mod 10) + Integer( '0' ) ) + Result;
      Value := Value div 10;
   end;
   if Minus then
      Result := '-' + Result;
end;

function Str2Int(const Value : String) : Int64;
var M, I : Integer;
begin
   Result := 0;
   if Value = '' then Exit;
   M := 1;
   I := 1;
   if Value[ 1 ] = '-' then
   begin
      M := -1;
      Inc( I );
   end;
   for I := I to Length( Value ) do
   begin
      if (Value[ I ] < '0') or (Value[ I ] > '9') then
         break;
      Result := Result * 10 + Integer( Value[ I ] ) - Integer( '0' );
   end;
   if M < 0 then
      Result := -Result;
end;

function Str2IntDef(const S: string; Default: Int64): Int64;
var
  E: Integer;
begin
  Val(S, Result, E);
  if E <> 0 then Result := Default;
end;

function BackfillGetDiskFreeSpaceEx(Directory: PChar; var FreeAvailable,
    TotalSpace: Int64; TotalFree: PLargeInteger): Boolean; stdcall;
var
  SectorsPerCluster, BytesPerSector, FreeClusters, TotalClusters: LongWord;
  Temp: Int64;
  Dir: PChar;
begin
  if Directory <> nil then
    Dir := Directory
  else
    Dir := nil;
  Result := GetDiskFreeSpaceA(Dir, SectorsPerCluster, BytesPerSector,
    FreeClusters, TotalClusters);
  Temp := SectorsPerCluster * BytesPerSector;
  FreeAvailable := Temp * FreeClusters;
  TotalSpace := Temp * TotalClusters;
end;

procedure InitDriveSpacePtr;
var
  Kernel: HWND;
begin
  Kernel := GetModuleHandle(Windows.Kernel32);
  if Kernel <> 0 then
    @GetDiskFreeSpaceEx := GetProcAddress(Kernel, 'GetDiskFreeSpaceExA');
  if not Assigned(GetDiskFreeSpaceEx) then
    GetDiskFreeSpaceEx := @BackfillGetDiskFreeSpaceEx;
end;

function DiskSpace(Drive: String): TdriveSize;
var
  TSpace,TotalS: Int64;
  Sizes:TdriveSize;
  ErrorMode: Word;
begin
Delete(Drive, 4, 600);
ErrorMode := SetErrorMode(SEM_FailCriticalErrors);
if GetDiskFreeSpaceEx(@Drive[1], TSpace, TotalS, nil) then
begin
Sizes.FreeS :=  TSpace;
Sizes.TotalS := TotalS;
Result := Sizes;
end else
begin
Sizes.FreeS := -1;
Sizes.TotalS := -1;
Result := Sizes;
end;
SetErrorMode(ErrorMode);
end;

function FileExists( FileName : String ) : Boolean;
var
FndData: TWin32FindData;
fndHandle: Integer;
ErrorMode: Word;
begin
  Result := False;
  ErrorMode := SetErrorMode(SEM_FailCriticalErrors);
  fndHandle := FindFirstFile(PChar(FileName), FndData);
  SetErrorMode(ErrorMode);
  if fndHandle <> Integer( INVALID_HANDLE_VALUE ) then
  begin
    Windows.FindClose(fndHandle);
    if (FndData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
       Result := True;
  end;
end;

function DirectoryExists(const Name: string): Boolean;
var
  Code: Integer;
begin
  Code := GetFileAttributes(PChar(Name));
  Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
end;

function FileSize(FileName:String):Int64;
var
FindHandle:HWND;
FindData: TWin32FindData;
ErrorMode: Word;
begin
ErrorMode := SetErrorMode(SEM_FailCriticalErrors);
FindHandle := FindFirstFile(PChar(FileName), FindData);
SetErrorMode(ErrorMode);
if FindHandle <> INVALID_HANDLE_VALUE then
  begin
  Result := (FindData.nFileSizeHigh * MAXDWORD) + FindData.nFileSizeLow;
  Windows.FindClose(findHandle);
  end else Result := -1;
end;

function SysErrorMessage(ErrorCode: Integer): string;
var
  Len: Integer;
  Buffer: array[0..255] of Char;
begin
  Len := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or
    FORMAT_MESSAGE_ARGUMENT_ARRAY, nil, ErrorCode, 0, Buffer,
    SizeOf(Buffer), nil);
  while (Len > 0) and (Buffer[Len - 1] in [#0..#32, '.']) do Dec(Len);
  SetString(Result, Buffer, Len);
end;

function ShortPathName(const LongName: string): string;
var
  Buffer: array[0..MAX_PATH - 1] of Char;
begin
  SetString(Result, Buffer,
    GetShortPathName(PChar(LongName), Buffer, SizeOf(Buffer)));
end;

function GetWindowVer: TWinVerRec;
var
  OSVersionInfo: TOSVersionInfo;
begin
with Result do
      begin
      WinPlatform := 0;
      WinMajorVersion := 0;
      WinMinorVersion := 0;
      WinBuildNumber := 0;
      WinCSDVersion := '';
      end;
  OSVersionInfo.dwOSVersionInfoSize := SizeOf(OSVersionInfo);
  if GetVersionEx(OSVersionInfo) then
    with OSVersionInfo do
    begin
    with Result do
      begin
      WinPlatform := dwPlatformId;
      WinMajorVersion := dwMajorVersion;
      WinMinorVersion := dwMinorVersion;
      WinBuildNumber := dwBuildNumber;
      WinCSDVersion := szCSDVersion;
      end;
    end;
end;


initialization
  InitDriveSpacePtr;

end.


H O M E