unit ABSStrUtils;

interface

{$I ABSVer.inc}

uses SysUtils, Windows;

type                        

  PABSCharTable = ^TABSCharTable;
  TABSCharTable = array[0..255] of AnsiChar;
  PABSByteTable = ^TABSByteTable;
  TABSByteTable = array[0..255] of Byte;

var
  ToUpperChars, ToLowerChars: TABSCharTable;
  OrderedChars: TABSByteTable;

// unicode support in Win95/98/ME
type TCompareStringW = function (Locale: LCID; dwCmpFlags: DWORD; lpString1: PWideChar;
  cchCount1: Integer; lpString2: PWideChar; cchCount2: Integer): Integer; stdcall;
type TCharUpperBuffW = function (lpsz: PWideChar; cchLength: DWORD): DWORD; stdcall;
type TCharLowerBuffW = function (lpsz: PWideChar; cchLength: DWORD): DWORD; stdcall;

var
  CompareStringW: TCompareStringW;
  CharUpperBuffW: TCharUpperBuffW;
  CharLowerBuffW: TCharLowerBuffW;

function WideUpperCase(const S: WideString): WideString;
function WideLowerCase(const S: WideString): WideString;

{
  function StrComp(P1, P2: PAnsiChar): Integer; overload;
  function StrComp(P1, P2: PAnsiChar; OrderTable: PABSByteTable): Integer; overload;
  function StrCompL(P1, P2: PAnsiChar; MaxLen: Cardinal): Integer; overload;
  function StrCompL(P1, P2: PAnsiChar; MaxLen: Cardinal; OrderTable: PABSByteTable): Integer; overload;

  function StrIComp(P1, P2: PAnsiChar): Integer; overload;
  function StrIComp(P1, P2: PAnsiChar; OrderTable: PABSByteTable; UpperTable: TABSCharTable): Integer; overload;
  function StrICompL(P1, P2: PAnsiChar; MaxLen: Cardinal): Integer; overload;
  function StrICompL(P1, P2: PAnsiChar; MaxLen: Cardinal; OrderTable: PABSByteTable; UpperTable: TABSCharTable): Integer; overload;
}



  procedure ChangeCaseCustom(Buffer: PAnsiChar; PTable: PABSCharTable); register;
  //procedure ToLowerCase(Buffer: PAnsiChar); register;
  //procedure ToUpperCase(Buffer: PAnsiChar); register;


implementation

function WideUpperCase(const S: WideString): WideString;
var
  Len: Integer;
begin
  Len := Length(S);
  SetString(Result, PWideChar(S), Len);
  if Len > 0 then CharUpperBuffW(Pointer(Result), Len);
end;

function WideLowerCase(const S: WideString): WideString;
var
  Len: Integer;
begin
  Len := Length(S);
  SetString(Result, PWideChar(S), Len);
  if Len > 0 then CharLowerBuffW(Pointer(Result), Len);
end;


procedure ChangeCaseCustom(Buffer: PAnsiChar; PTable: PABSCharTable);
asm
        TEST    EAX, EAX                                   // Buffer = nil ?
        JE      @exit
        TEST    EDX, EDX                                   // Table = nil ?
        JE      @exit

@loop:  MOVZX   ECX, BYTE PTR [EAX]
        TEST    CL, CL                                     // End of String ?
        JE      @exit
        MOV     CL, BYTE PTR [EDX + ECX]
        MOV     BYTE PTR [EAX], CL
        INC     EAX
        JMP     @loop
@exit:
end;


{
procedure ToLowerCase(Buffer: PAnsiChar);
asm
        TEST    EAX, EAX                                   // Buffer = nil ?
        JE      @exit
@loop:  MOVZX   ECX, BYTE PTR [EAX]
        TEST    CL, CL                                     // End of String ?
        JE      @exit
        MOV     CL, BYTE PTR [ToLowerChars + ECX]
        MOV     BYTE PTR [EAX], CL
        INC     EAX
        JMP     @loop
@exit:
end;


procedure ToUpperCase(Buffer: PAnsiChar);
asm
        TEST    EAX, EAX                                   // Buffer = nil ?
        JE      @exit
@loop:  MOVZX   ECX, BYTE PTR [EAX]
        TEST    CL, CL                                     // End of String ?
        JE      @exit
        MOV     CL, BYTE PTR [ToUpperChars + ECX]
        MOV     BYTE PTR [EAX], CL
        INC     EAX
        JMP     @loop
@exit:
end;
}


procedure InitOrderedChars;
var i,j: Integer;
  a1, a2: array[0..1] of Byte;
  p1, p2: PAnsiChar;
  n: Byte;
begin
  a1[1] := 0;
  a2[1] := 0;
  p1 := @a1;
  p2 := @a2;
  for i:=0 to 255 do
    begin
      n := 0;
      a1[0] := i;
      for j:=0 to 255 do
        begin
          a2[0] := j;
//          if (AnsiStrLComp(p1, p2, 1) > 0) then  // commented in 6.0 to avoid duplicated 0 in chars table
          if (StrLComp(p1, p2, 1) > 0) then
            Inc(n);
        end;
      OrderedChars[i] := n;
    end;
end;


var i: Integer;
    LibHandle  : THandle;

initialization
  for i:=0 to 255 do
    ToUpperChars[i] := AnsiChar(i);
  move(ToUpperChars, ToLowerChars, 256);
  CharUpperBuffA(PAnsiChar(@ToUpperChars), 256);
  CharLowerBuffA(PAnsiChar(@ToLowerChars), 256);
  InitOrderedChars;

  // unicode support in Win95/98/Me
  if (FileExists('unicows.dll')) then
    LibHandle := LoadLibrary('unicows.dll')
  else
    LibHandle := 0;
  // CompareStringW
  if (LibHandle <> 0) then
    @CompareStringW := GetProcAddress(LibHandle, 'CompareStringW')
  else
    @CompareStringW := nil;
  if (@CompareStringW = nil) then
   @CompareStringW := @Windows.CompareStringW;

  // CharUpperBuffW
  if (LibHandle <> 0) then
    @CharUpperBuffW := GetProcAddress(LibHandle, 'CharUpperBuffW')
  else
    @CharUpperBuffW := nil;
  if (@CharUpperBuffW = nil) then
   @CharUpperBuffW := @Windows.CharUpperBuffW;

  // CharLowerBuffW
  if (LibHandle <> 0) then
    @CharLowerBuffW := GetProcAddress(LibHandle, 'CharLowerBuffW')
  else
    @CharLowerBuffW := nil;
  if (@CharLowerBuffW = nil) then
   @CharLowerBuffW := @Windows.CharLowerBuffW;

end.
