{*****************************************************************************}
{ }
{ Tnt Delphi Unicode Controls }
{ http://www.tntware.com/delphicontrols/unicode/ }
{ Version: 2.3.0 }
{ }
{ Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com) }
{ }
{*****************************************************************************}
unit TntWideStrUtils;
{$IFDEF FPC}
{$MODE Delphi}
{$ENDIF}
{$INCLUDE TntCompilers.inc}
interface
{ Wide string manipulation functions }
{$IFNDEF COMPILER_9_UP}
function WStrAlloc(Size: Cardinal): PWideChar;
function WStrBufSize(const Str: PWideChar): Cardinal;
{$ENDIF}
{$IFNDEF COMPILER_10_UP}
function WStrMove(Dest: PWideChar; const Source: PWideChar; Count: Cardinal): PWideChar;
{$ENDIF}
{$IFNDEF COMPILER_9_UP}
function WStrNew(const Str: PWideChar): PWideChar;
procedure WStrDispose(Str: PWideChar);
{$ENDIF}
//---------------------------------------------------------------------------------------------
{$IFNDEF COMPILER_9_UP}
function WStrLen(Str: PWideChar): Cardinal;
function WStrEnd(Str: PWideChar): PWideChar;
{$ENDIF}
{$IFNDEF COMPILER_10_UP}
function WStrCat(Dest: PWideChar; const Source: PWideChar): PWideChar;
{$ENDIF}
{$IFNDEF COMPILER_9_UP}
function WStrCopy(Dest, Source: PWideChar): PWideChar;
function WStrLCopy(Dest, Source: PWideChar; MaxLen: Cardinal): PWideChar;
function WStrPCopy(Dest: PWideChar; const Source: WideString): PWideChar;
function WStrPLCopy(Dest: PWideChar; const Source: WideString; MaxLen: Cardinal): PWideChar;
{$ENDIF}
{$IFNDEF COMPILER_10_UP}
function WStrScan(const Str: PWideChar; Chr: WideChar): PWideChar;
// WStrComp and WStrPos were introduced as broken in Delphi 2006, but fixed in Delphi 2006 Update 2
function WStrComp(Str1, Str2: PWideChar): Integer;
function WStrPos(Str, SubStr: PWideChar): PWideChar;
{$ENDIF}
function Tnt_WStrComp(Str1, Str2: PWideChar): Integer; deprecated;
function Tnt_WStrPos(Str, SubStr: PWideChar): PWideChar; deprecated;
{ ------------ introduced --------------- }
function WStrECopy(Dest, Source: PWideChar): PWideChar;
function WStrLComp(Str1, Str2: PWideChar; MaxLen: Cardinal): Integer;
function WStrLIComp(Str1, Str2: PWideChar; MaxLen: Cardinal): Integer;
function WStrIComp(Str1, Str2: PWideChar): Integer;
function WStrLower(Str: PWideChar): PWideChar;
function WStrUpper(Str: PWideChar): PWideChar;
function WStrRScan(const Str: PWideChar; Chr: WideChar): PWideChar;
function WStrLCat(Dest: PWideChar; const Source: PWideChar; MaxLen: Cardinal): PWideChar;
function WStrPas(const Str: PWideChar): WideString;
{ SysUtils.pas } //-------------------------------------------------------------------------
{$IFNDEF COMPILER_10_UP}
function WideLastChar(const S: WideString): PWideChar;
function WideQuotedStr(const S: WideString; Quote: WideChar): WideString;
{$ENDIF}
{$IFNDEF COMPILER_9_UP}
function WideExtractQuotedStr(var Src: PWideChar; Quote: WideChar): Widestring;
{$ENDIF}
{$IFNDEF COMPILER_10_UP}
function WideDequotedStr(const S: WideString; AQuote: WideChar): WideString;
{$ENDIF}
implementation
uses
{$IFDEF COMPILER_9_UP} WideStrUtils, {$ENDIF} Math, Windows, TntWindows;
{$IFNDEF COMPILER_9_UP}
function WStrAlloc(Size: Cardinal): PWideChar;
begin
Size := SizeOf(Cardinal) + (Size * SizeOf(WideChar));
GetMem(Result, Size);
PCardinal(Result)^ := Size;
Inc(PAnsiChar(Result), SizeOf(Cardinal));
end;
function WStrBufSize(const Str: PWideChar): Cardinal;
var
P: PWideChar;
begin
P := Str;
Dec(PAnsiChar(P), SizeOf(Cardinal));
Result := PCardinal(P)^ - SizeOf(Cardinal);
Result := Result div SizeOf(WideChar);
end;
{$ENDIF}
{$IFNDEF COMPILER_10_UP}
function WStrMove(Dest: PWideChar; const Source: PWideChar; Count: Cardinal): PWideChar;
var
Length: Integer;
begin
Result := Dest;
Length := Count * SizeOf(WideChar);
Move(Source^, Dest^, Length);
end;
{$ENDIF}
{$IFNDEF COMPILER_9_UP}
function WStrNew(const Str: PWideChar): PWideChar;
var
Size: Cardinal;
begin
if Str = nil then Result := nil else
begin
Size := WStrLen(Str) + 1;
Result := WStrMove(WStrAlloc(Size), Str, Size);
end;
end;
procedure WStrDispose(Str: PWideChar);
begin
if Str <> nil then
begin
Dec(PAnsiChar(Str), SizeOf(Cardinal));
FreeMem(Str, Cardinal(Pointer(Str)^));
end;
end;
{$ENDIF}
//---------------------------------------------------------------------------------------------
{$IFNDEF COMPILER_9_UP}
function WStrLen(Str: PWideChar): Cardinal;
begin
Result := WStrEnd(Str) - Str;
end;
function WStrEnd(Str: PWideChar): PWideChar;
begin
// returns a pointer to the end of a null terminated string
Result := Str;
While Result^ <> #0 do
Inc(Result);
end;
{$ENDIF}
{$IFNDEF COMPILER_10_UP}
function WStrCat(Dest: PWideChar; const Source: PWideChar): PWideChar;
begin
Result := Dest;
WStrCopy(WStrEnd(Dest), Source);
end;
{$ENDIF}
{$IFNDEF COMPILER_9_UP}
function WStrCopy(Dest, Source: PWideChar): PWideChar;
begin
Result := WStrLCopy(Dest, Source, MaxInt);
end;
function WStrLCopy(Dest, Source: PWideChar; MaxLen: Cardinal): PWideChar;
var
Count: Cardinal;
begin
// copies a specified maximum number of characters from Source to Dest
Result := Dest;
Count := 0;
While (Count < MaxLen) and (Source^ <> #0) do begin
Dest^ := Source^;
Inc(Source);
Inc(Dest);
Inc(Count);
end;
Dest^ := #0;
end;
function WStrPCopy(Dest: PWideChar; const Source: WideString): PWideChar;
begin
Result := WStrLCopy(Dest, PWideChar(Source), Length(Source));
end;
function WStrPLCopy(Dest: PWideChar; const Source: WideString; MaxLen: Cardinal): PWideChar;
begin
Result := WStrLCopy(Dest, PWideChar(Source), MaxLen);
end;
{$ENDIF}
{$IFNDEF COMPILER_10_UP}
function WStrScan(const Str: PWideChar; Chr: WideChar): PWideChar;
begin
Result := Str;
while Result^ <> Chr do
begin
if Result^ = #0 then
begin
Result := nil;
Exit;
end;
Inc(Result);
end;
end;
function WStrComp(Str1, Str2: PWideChar): Integer;
begin
Result := WStrLComp(Str1, Str2, MaxInt);
end;
function WStrPos(Str, SubStr: PWideChar): PWideChar;
var
PSave: PWideChar;
P: PWideChar;
PSub: PWideChar;
begin
// returns a pointer to the first occurance of SubStr in Str
Result := nil;
if (Str <> nil) and (Str^ <> #0) and (SubStr <> nil) and (SubStr^ <> #0) then begin
P := Str;
While P^ <> #0 do begin
if P^ = SubStr^ then begin
// investigate possibility here
PSave := P;
PSub := SubStr;
While (P^ = PSub^) do begin
Inc(P);
Inc(PSub);
if (PSub^ = #0) then begin
Result := PSave;
exit; // found a match
end;
if (P^ = #0) then
exit; // no match, hit end of string
end;
P := PSave;
end;
Inc(P);
end;
end;
end;
{$ENDIF}
function Tnt_WStrComp(Str1, Str2: PWideChar): Integer; deprecated;
begin
Result := WStrComp(Str1, Str2);
end;
function Tnt_WStrPos(Str, SubStr: PWideChar): PWideChar; deprecated;
begin
Result := WStrPos(Str, SubStr);
end;
//------------------------------------------------------------------------------
function WStrECopy(Dest, Source: PWideChar): PWideChar;
begin
Result := WStrEnd(WStrCopy(Dest, Source));
end;
function WStrComp_EX(Str1, Str2: PWideChar; MaxLen: Cardinal; dwCmpFlags: Cardinal): Integer;
var
Len1, Len2: Integer;
begin
if MaxLen = Cardinal(MaxInt) then begin
Len1 := -1;
Len2 := -1;
end else begin
Len1 := Min(WStrLen(Str1), MaxLen);
Len2 := Min(WStrLen(Str2), MaxLen);
end;
Result := Tnt_CompareStringW(GetThreadLocale, dwCmpFlags, Str1, Len1, Str2, Len2) - 2;
end;
function WStrLComp(Str1, Str2: PWideChar; MaxLen: Cardinal): Integer;
begin
Result := WStrComp_EX(Str1, Str2, MaxLen, 0);
end;
function WStrLIComp(Str1, Str2: PWideChar; MaxLen: Cardinal): Integer;
begin
Result := WStrComp_EX(Str1, Str2, MaxLen, NORM_IGNORECASE);
end;
function WStrIComp(Str1, Str2: PWideChar): Integer;
begin
Result := WStrLIComp(Str1, Str2, MaxInt);
end;
function WStrLower(Str: PWideChar): PWideChar;
begin
Result := Str;
Tnt_CharLowerBuffW(Str, WStrLen(Str))
end;
function WStrUpper(Str: PWideChar): PWideChar;
begin
Result := Str;
Tnt_CharUpperBuffW(Str, WStrLen(Str))
end;
function WStrRScan(const Str: PWideChar; Chr: WideChar): PWideChar;
var
MostRecentFound: PWideChar;
begin
if Chr = #0 then
Result := WStrEnd(Str)
else
begin
Result := nil;
MostRecentFound := Str;
while True do
begin
while MostRecentFound^ <> Chr do
begin
if MostRecentFound^ = #0 then
Exit;
Inc(MostRecentFound);
end;
Result := MostRecentFound;
Inc(MostRecentFound);
end;
end;
end;
function WStrLCat(Dest: PWideChar; const Source: PWideChar; MaxLen: Cardinal): PWideChar;
begin
Result := Dest;
WStrLCopy(WStrEnd(Dest), Source, MaxLen - WStrLen(Dest));
end;
function WStrPas(const Str: PWideChar): WideString;
begin
Result := Str;
end;
//---------------------------------------------------------------------------------------------
{$IFNDEF COMPILER_10_UP}
function WideLastChar(const S: WideString): PWideChar;
begin
if S = '' then
Result := nil
else
Result := @S[Length(S)];
end;
function WideQuotedStr(const S: WideString; Quote: WideChar): WideString;
var
P, Src,
Dest: PWideChar;
AddCount: Integer;
begin
AddCount := 0;
P := WStrScan(PWideChar(S), Quote);
while (P <> nil) do
begin
Inc(P);
Inc(AddCount);
P := WStrScan(P, Quote);
end;
if AddCount = 0 then
Result := Quote + S + Quote
else
begin
SetLength(Result, Length(S) + AddCount + 2);
Dest := PWideChar(Result);
Dest^ := Quote;
Inc(Dest);
Src := PWideChar(S);
P := WStrScan(Src, Quote);
repeat
Inc(P);
Move(Src^, Dest^, 2 * (P - Src));
Inc(Dest, P - Src);
Dest^ := Quote;
Inc(Dest);
Src := P;
P := WStrScan(Src, Quote);
until P = nil;
P := WStrEnd(Src);
Move(Src^, Dest^, 2 * (P - Src));
Inc(Dest, P - Src);
Dest^ := Quote;
end;
end;
{$ENDIF}
{$IFNDEF COMPILER_9_UP}
function WideExtractQuotedStr(var Src: PWideChar; Quote: WideChar): Widestring;
var
P, Dest: PWideChar;
DropCount: Integer;
begin
Result := '';
if (Src = nil) or (Src^ <> Quote) then Exit;
Inc(Src);
DropCount := 1;
P := Src;
Src := WStrScan(Src, Quote);
while Src <> nil do // count adjacent pairs of quote chars
begin
Inc(Src);
if Src^ <> Quote then Break;
Inc(Src);
Inc(DropCount);
Src := WStrScan(Src, Quote);
end;
if Src = nil then Src := WStrEnd(P);
if ((Src - P) <= 1) then Exit;
if DropCount = 1 then
SetString(Result, P, Src - P - 1)
else
begin
SetLength(Result, Src - P - DropCount);
Dest := PWideChar(Result);
Src := WStrScan(P, Quote);
while Src <> nil do
begin
Inc(Src);
if Src^ <> Quote then Break;
Move(P^, Dest^, (Src - P) * SizeOf(WideChar));
Inc(Dest, Src - P);
Inc(Src);
P := Src;
Src := WStrScan(Src, Quote);
end;
if Src = nil then Src := WStrEnd(P);
Move(P^, Dest^, (Src - P - 1) * SizeOf(WideChar));
end;
end;
{$ENDIF}
{$IFNDEF COMPILER_10_UP}
function WideDequotedStr(const S: WideString; AQuote: WideChar): WideString;
var
LText : PWideChar;
begin
LText := PWideChar(S);
Result := WideExtractQuotedStr(LText, AQuote);
if Result = '' then
Result := S;
end;
{$ENDIF}
end.