 | 
|
|
|
{ }
{ Unicode string functions v3.07 }
{ }
{ This unit is copyright © 2002-2004 by David J Butler }
{ }
{ This unit is part of Delphi Fundamentals. }
{ Its original file name is cUnicode.pas }
{ The latest version is available from the Fundamentals home page }
{ http://fundementals.sourceforge.net/ }
{ }
{ I invite you to use this unit, free of charge. }
{ I invite you to distibute this unit, but it must be for free. }
{ I also invite you to contribute to its development, }
{ but do not distribute a modified copy of this file. }
{ }
{ A forum is available on SourceForge for general discussion }
{ http://sourceforge.net/forum/forum.php?forum_id=2117 }
{ }
{ }
{ Description: }
{ Unicode functions for using WideStrings. }
{ }
{ Revision history: }
{ 19/04/2002 0.01 Initial version }
{ 26/04/2002 0.02 Added WidePos, WideReplace and Append functions. }
{ 28/10/2002 3.03 Refactored for Fundamentals 3. }
{ 18/12/2002 3.04 Removed dependancy on cUnicodeChar unit. }
{ 07/09/2003 3.05 Revisions. }
{ 10/01/2004 3.06 Unit now uses cUnicodeChar for character functions. }
{ Removed dependancy on cUtils unit. }
{ 01/04/2004 3.07 Compilable with FreePascal-1.92/Win32. }
{ }
{$INCLUDE ..\cDefines.inc}
unit cUnicode;
interface
uses
{ Delphi }
SysUtils,
{ Fundamentals }
cUnicodeChar;
const
UnitName = 'cUnicode';
UnitVersion = '3.07';
UnitCopyright = 'Copyright (c) 2002-2004 David J Butler';
{ }
{ Unicode errors }
{ }
type
EUnicode = class(Exception);
{ }
{ WideString functions }
{ }
type
AnsiCharSet = Set of AnsiChar;
function WideMatchAnsiCharNoCase(const M: Char; const C: WideChar): Boolean;
function WidePMatchChars(const CharMatchFunc: WideCharMatchFunction;
const P: PWideChar; const Length: Integer = -1): Integer;
function WidePMatchCharsRev(const CharMatchFunc: WideCharMatchFunction;
const P: PWideChar; const Length: Integer = -1): Integer;
function WidePMatchAllChars(const CharMatchFunc: WideCharMatchFunction;
const P: PWideChar; const Length: Integer = -1): Integer;
function WidePMatchAnsiStr(const M: String; const P: PWideChar;
const CaseSensitive: Boolean = True): Boolean;
function WidePMatch(const M: WideString; const P: PWideChar): Boolean;
function WideEqualAnsiStr(const M: String; const S: WideString;
const CaseSensitive: Boolean = True): Boolean;
function WideMatchLeftAnsiStr(const M: String; const S: WideString;
const CaseSensitive: Boolean = True): Boolean;
function WideZPosChar(const F: WideChar; const P: PWideChar): Integer;
function WideZPosAnsiChar(const F: Char; const P: PWideChar): Integer;
function WideZPosAnsiCharSet(const F: AnsiCharSet; const P: PWideChar): Integer;
function WideZPosAnsiStr(const F: String; const P: PWideChar;
const CaseSensitive: Boolean = True): Integer;
function WideZSkipChar(const CharMatchFunc: WideCharMatchFunction;
var P: PWideChar): Boolean;
function WideZSkipChars(const CharMatchFunc: WideCharMatchFunction;
var P: PWideChar): Integer;
function WidePSkipAnsiChar(const Ch: Char; var P: PWideChar): Boolean;
function WidePSkipAnsiStr(const M: String; var P: PWideChar;
const CaseSensitive: Boolean = True): Boolean;
function WideZExtractBeforeChar(const Ch: WideChar; var P: PWideChar;
var S: WideString): Boolean;
function WideZExtractBeforeAnsiChar(const Ch: Char; var P: PWideChar;
var S: WideString): Boolean;
function WideZExtractBeforeAnsiCharSet(const C: AnsiCharSet; var P: PWideChar;
var S: WideString): Boolean;
function WideZExtractAnsiCharDelimited(const LeftDelimiter, RightDelimiter: Char;
var P: PWideChar; var S: WideString): Boolean;
function WideZExtractAnsiCharQuoted(const Delimiter: Char;
var P: PWideChar; var S: WideString): Boolean;
function WideDup(const Ch: WideChar; const Count: Integer): WideString;
procedure WideTrimInPlace(var S: WideString;
const MatchFunc: WideCharMatchfunction = nil);
procedure WideTrimLeftInPlace(var S: WideString;
const MatchFunc: WideCharMatchfunction = nil);
procedure WideTrimRightInPlace(var S: WideString;
const MatchFunc: WideCharMatchfunction = nil);
function WideTrim(const S: WideString;
const MatchFunc: WideCharMatchfunction = nil): WideString;
function WideTrimLeft(const S: WideString;
const MatchFunc: WideCharMatchfunction = nil): WideString;
function WideTrimRight(const S: WideString;
const MatchFunc: WideCharMatchfunction = nil): WideString;
function WideCountChar(const CharMatchFunc: WideCharMatchFunction;
const S: WideString): Integer; overload;
function WideCountChar(const Ch: WideChar; const S: WideString): Integer; overload;
function WidePosChar(const F: WideChar; const S: WideString;
const StartIndex: Integer = 1): Integer; overload;
function WidePosAnsiCharSet(const F: AnsiCharSet; const S: WideString;
const StartIndex: Integer = 1): Integer;
function WidePos(const F: WideString; const S: WideString;
const StartIndex: Integer = 1): Integer; overload;
procedure WideReplaceChar(const Find: WideChar; const Replace: WideString;
var S: WideString);
procedure WideSetLengthAndZero(var S: WideString; const NewLength: Integer);
{$IFDEF DELPHI5}
function WideUpperCase(const S: WideString): WideString;
function WideLowerCase(const S: WideString): WideString;
{$ENDIF}
function WideCopyRange(const S: WideString; const StartIndex, StopIndex: Integer): WideString;
function WideCopyFrom(const S: WideString; const Index: Integer): WideString;
{ }
{ Dynamic Array functions }
{ }
type
WideStringArray = Array of WideString;
function WideAppend(var V : WideStringArray;
const R: WideString): Integer; overload;
function WideAppendWideStringArray(var V : WideStringArray;
const R: WideStringArray): Integer;
function WideSplit(const S, D: WideString): WideStringArray;
{ }
{ Self-testing code }
{ }
procedure SelfTest;
implementation
{ }
{ Match }
{ }
function WideMatchAnsiCharNoCase(const M: Char; const C: WideChar): Boolean;
const ASCIICaseOffset = Ord('a') - Ord('A');
var D, N : Char;
begin
if Ord(C) > $7F then
begin
Result := False;
exit;
end;
D := Char(Ord(C));
if D in ['A'..'Z'] then
D := Char(Ord(D) + ASCIICaseOffset);
N := M;
if N in ['A'..'Z'] then
N := Char(Ord(N) + ASCIICaseOffset);
Result := D = N;
end;
function WidePMatchChars(const CharMatchFunc: WideCharMatchFunction;
const P: PWideChar; const Length: Integer): Integer;
var Q : PWideChar;
L : Integer;
C : WideChar;
begin
Result := 0;
Q := P;
L := Length;
if not Assigned(Q) or (L = 0) then
exit;
C := Q^;
if (L < 0) and (Ord(C) = 0) then
exit;
Repeat
if not CharMatchFunc(C) then
exit;
Inc(Result);
Inc(Q);
if L > 0 then
Dec(L);
C := Q^;
Until (L = 0) or ((L < 0) and (Ord(C) = 0));
end;
function WidePMatchCharsRev(const CharMatchFunc: WideCharMatchFunction;
const P: PWideChar; const Length: Integer): Integer;
var Q : PWideChar;
L : Integer;
C : WideChar;
begin
Result := 0;
Q := P;
L := Length;
if not Assigned(Q) or (L = 0) then
exit;
Inc(Q, L - 1);
C := Q^;
if (L < 0) and (Ord(C) = 0) then
exit;
Repeat
if not CharMatchFunc(C) then
exit;
Inc(Result);
Dec(Q);
if L < 0 then
C := Q^ else
begin
Dec(L);
if L > 0 then
C := Q^;
end;
Until (L = 0) or ((L < 0) and (Ord(C) = 0));
end;
function WidePMatchAllChars(const CharMatchFunc: WideCharMatchFunction; const P: PWideChar; const Length: Integer): Integer;
var Q : PWideChar;
L : Integer;
C : WideChar;
begin
Result := 0;
Q := P;
L := Length;
if not Assigned(Q) or (L = 0) then
exit;
C := Q^;
if (L < 0) and (Ord(C) = 0) then
exit;
Repeat
if CharMatchFunc(C) then
Inc(Result);
Inc(Q);
if L > 0 then
Dec(L);
C := Q^;
Until (L = 0) or ((L < 0) and (Ord(C) = 0));
end;
function WidePMatchAnsiStr(const M: String; const P: PWideChar;
const CaseSensitive: Boolean): Boolean;
var I, L : Integer;
Q : PWideChar;
R : PChar;
begin
L := Length(M);
if L = 0 then
begin
Result := False;
exit;
end;
R := Pointer(M);
Q := P;
if CaseSensitive then
begin
For I := 1 to L do
if Ord(R^) <> Ord(Q^) then
begin
Result := False;
exit;
end else
begin
Inc(R);
Inc(Q);
end;
end else
begin
For I := 1 to L do
if not WideMatchAnsiCharNoCase(R^, Q^) then
begin
Result := False;
exit;
end else
begin
Inc(R);
Inc(Q);
end;
end;
Result := True;
end;
function WidePMatch(const M: WideString; const P: PWideChar): Boolean;
var I, L : Integer;
Q, R : PWideChar;
begin
L := Length(M);
if L = 0 then
begin
Result := False;
exit;
end;
R := Pointer(M);
Q := P;
For I := 1 to L do
if R^ <> Q^ then
begin
Result := False;
exit;
end else
begin
Inc(R);
Inc(Q);
end;
Result := True;
end;
function WideEqualAnsiStr(const M: String; const S: WideString;
const CaseSensitive: Boolean): Boolean;
var L : Integer;
begin
L := Length(M);
Result := L = Length(S);
if not Result or (L = 0) then
exit;
Result := WidePMatchAnsiStr(M, Pointer(S), CaseSensitive);
end;
function WideMatchLeftAnsiStr(const M: String; const S: WideString;
const CaseSensitive: Boolean): Boolean;
var L, N : Integer;
begin
L := Length(M);
N := Length(S);
if (L = 0) or (N = 0) or (L > N) then
begin
Result := False;
exit;
end;
Result := WidePMatchAnsiStr(M, Pointer(S), CaseSensitive);
end;
{ }
{ Pos }
{ }
function WideZPosAnsiChar(const F: Char; const P: PWideChar): Integer;
var Q : PWideChar;
I : Integer;
begin
Result := -1;
Q := P;
if not Assigned(Q) then
exit;
I := 0;
While Ord(Q^) <> 0 do
if Ord(Q^) = Ord(F) then
begin
Result := I;
exit;
end else
begin
Inc(Q);
Inc(I);
end;
end;
function WideZPosAnsiCharSet(const F: AnsiCharSet; const P: PWideChar): Integer;
var Q : PWideChar;
I : Integer;
begin
Result := -1;
Q := P;
if not Assigned(Q) then
exit;
I := 0;
While Ord(Q^) <> 0 do
if (Ord(Q^) < $80) and (Char(Ord(Q^)) in F) then
begin
Result := I;
exit;
end else
begin
Inc(Q);
Inc(I);
end;
end;
function WideZPosChar(const F: WideChar; const P: PWideChar): Integer;
var Q : PWideChar;
I : Integer;
begin
Result := -1;
Q := P;
if not Assigned(Q) then
exit;
I := 0;
While Ord(Q^) <> 0 do
if Q^ = F then
begin
Result := I;
exit;
end else
begin
Inc(Q);
Inc(I);
end;
end;
function WideZPosAnsiStr(const F: String; const P: PWideChar; const CaseSensitive: Boolean): Integer;
var Q : PWideChar;
I : Integer;
begin
Result := -1;
Q := P;
if not Assigned(Q) then
exit;
I := 0;
While Ord(Q^) <> 0 do
if WidePMatchAnsiStr(F, Q, CaseSensitive) then
begin
Result := I;
exit;
end else
begin
Inc(Q);
Inc(I);
end;
end;
{ }
{ Skip }
{ }
function WideZSkipChar(const CharMatchFunc: WideCharMatchFunction; var P: PWideChar): Boolean;
var C : WideChar;
begin
Assert(Assigned(CharMatchFunc));
C := P^;
if Ord(C) = 0 then
begin
Result := False;
exit;
end;
Result := CharMatchFunc(C);
if Result then
Inc(P);
end;
function WideZSkipChars(const CharMatchFunc: WideCharMatchFunction; var P: PWideChar): Integer;
var C : WideChar;
begin
Assert(Assigned(CharMatchFunc));
Result := 0;
if not Assigned(P) then
exit;
C := P^;
While Ord(C) <> 0 do
if not CharMatchFunc(C) then
exit
else
begin
Inc(P);
Inc(Result);
C := P^;
end;
end;
function WidePSkipAnsiChar(const Ch: Char; var P: PWideChar): Boolean;
begin
Result := Ord(P^) = Ord(Ch);
if Result then
Inc(P);
end;
function WidePSkipAnsiStr(const M: String; var P: PWideChar; const CaseSensitive: Boolean): Boolean;
begin
Result := WidePMatchAnsiStr(M, P, CaseSensitive);
if Result then
Inc(P, Length(M));
end;
{ }
{ Extract }
{ }
function WideZExtractBeforeChar(const Ch: WideChar; var P: PWideChar; var S: WideString): Boolean;
var I : Integer;
begin
I := WideZPosChar(Ch, P);
Result := I >= 0;
if I <= 0 then
begin
S := '';
exit;
end;
SetLength(S, I);
Move(P^, Pointer(S)^, I * Sizeof(WideChar));
Inc(P, I);
end;
function WideZExtractBeforeAnsiChar(const Ch: Char; var P: PWideChar; var S: WideString): Boolean;
var I : Integer;
begin
I := WideZPosAnsiChar(Ch, P);
Result := I >= 0;
if I <= 0 then
begin
S := '';
exit;
end;
SetLength(S, I);
Move(P^, Pointer(S)^, I * Sizeof(WideChar));
Inc(P, I);
end;
function WideZExtractBeforeAnsiCharSet(const C: AnsiCharSet; var P: PWideChar; var S: WideString): Boolean;
var I : Integer;
begin
I := WideZPosAnsiCharSet(C, P);
Result := I >= 0;
if I <= 0 then
begin
S := '';
exit;
end;
SetLength(S, I);
Move(P^, Pointer(S)^, I * Sizeof(WideChar));
Inc(P, I);
end;
function WideZExtractAnsiCharDelimited(const LeftDelimiter, RightDelimiter: Char;
var P: PWideChar; var S: WideString): Boolean;
var Q : PWideChar;
begin
Q := P;
Result := Assigned(Q) and (Ord(Q^) < $80) and (Ord(Q^) = Ord(LeftDelimiter));
if not Result then
begin
S := '';
exit;
end;
Inc(Q);
Result := WideZExtractBeforeAnsiChar(RightDelimiter, Q, S);
if not Result then
exit;
Inc(Q);
P := Q;
end;
function WideZExtractAnsiCharQuoted(const Delimiter: Char; var P: PWideChar; var S: WideString): Boolean;
begin
Result := WideZExtractAnsiCharDelimited(Delimiter, Delimiter, P, S);
end;
{ }
{ Dup }
{ }
function WideDup(const Ch: WideChar; const Count: Integer): WideString;
var I : Integer;
P : PWideChar;
begin
if Count <= 0 then
begin
Result := '';
exit;
end;
SetLength(Result, Count);
P := Pointer(Result);
For I := 1 to Count do
begin
P^ := Ch;
Inc(P);
end;
end;
{ }
{ Trim }
{ }
procedure WideTrimLeftInPlace(var S: WideString; const MatchFunc: WideCharMatchFunction);
var I, L : Integer;
P : PWideChar;
F: WideCharMatchFunction;
begin
L := Length(S);
if L = 0 then
exit;
F := MatchFunc;
if not Assigned(F) then
F := IsWhiteSpace;
I := 0;
P := Pointer(S);
While F(P^) do
begin
Inc(I);
Inc(P);
Dec(L);
if L = 0 then
begin
S := '';
exit;
end;
end;
if I = 0 then
exit;
S := Copy(S, I + 1, L);
end;
procedure WideTrimRightInPlace(var S: WideString; const MatchFunc: WideCharMatchFunction);
var I, L : Integer;
P : PWideChar;
F: WideCharMatchFunction;
begin
L := Length(S);
if L = 0 then
exit;
F := MatchFunc;
if not Assigned(F) then
F := IsWhiteSpace;
I := 0;
P := Pointer(S);
Inc(P, L - 1);
While F(P^) do
begin
Inc(I);
Dec(P);
Dec(L);
if L = 0 then
begin
S := '';
exit;
end;
end;
if I = 0 then
exit;
SetLength(S, L);
end;
procedure WideTrimInPlace(var S: WideString; const MatchFunc: WideCharMatchFunction);
var I, J, L : Integer;
P : PWideChar;
F: WideCharMatchFunction;
begin
L := Length(S);
if L = 0 then
exit;
F := MatchFunc;
if not Assigned(F) then
F := IsWhiteSpace;
I := 0;
P := Pointer(S);
Inc(P, L - 1);
While F(P^) or IsControl(P^) do
begin
Inc(I);
Dec(P);
Dec(L);
if L = 0 then
begin
S := '';
exit;
end;
end;
J := 0;
P := Pointer(S);
While F(P^) or IsControl(P^) do
begin
Inc(J);
Inc(P);
Dec(L);
if L = 0 then
begin
S := '';
exit;
end;
end;
if (I = 0) and (J = 0) then
exit;
S := Copy(S, J + 1, L);
end;
function WideTrimLeft(const S: WideString; const MatchFunc: WideCharMatchFunction): WideString;
begin
Result := S;
WideTrimLeftInPlace(Result, MatchFunc);
end;
function WideTrimRight(const S: WideString; const MatchFunc: WideCharMatchFunction): WideString;
begin
Result := S;
WideTrimRightInPlace(Result, MatchFunc);
end;
function WideTrim(const S: WideString; const MatchFunc: WideCharMatchFunction): WideString;
begin
Result := S;
WideTrimInPlace(Result, MatchFunc);
end;
{ }
{ Count }
{ }
function WideCountChar(const CharMatchFunc: WideCharMatchFunction; const S: WideString): Integer;
begin
Result := WidePMatchAllChars(CharMatchFunc, Pointer(S), Length(S));
end;
function WideCountChar(const Ch: WideChar; const S: WideString): Integer;
var Q : PWideChar;
I : Integer;
begin
Result := 0;
Q := PWideChar(S);
if not Assigned(Q) then
exit;
For I := 1 to Length(S) do
begin
if Q^ = Ch then
Inc(Result);
Inc(Q);
end;
end;
{ }
{ Pos }
{ }
function WidePosChar(const F: WideChar; const S: WideString; const StartIndex: Integer): Integer;
var P : PWideChar;
I, L : Integer;
begin
L := Length(S);
if (StartIndex > L) or (StartIndex < 1) then
begin
Result := 0;
exit;
end;
P := Pointer(S);
Inc(P, StartIndex - 1);
For I := StartIndex to L do
if P^ = F then
begin
Result := I;
exit;
end
else
Inc(P);
Result := 0;
end;
function WidePosAnsiCharSet(const F: AnsiCharSet; const S: WideString; const StartIndex: Integer): Integer;
var P : PWideChar;
I, L : Integer;
begin
L := Length(S);
if (StartIndex > L) or (StartIndex < 1) then
begin
Result := 0;
exit;
end;
P := Pointer(S);
Inc(P, StartIndex - 1);
For I := StartIndex to L do
if (Ord(P^) <= $FF) and (Char(P^) in F) then
begin
Result := I;
exit;
end
else
Inc(P);
Result := 0;
end;
function WidePos(const F: WideString; const S: WideString; const StartIndex: Integer): Integer;
var P : PWideChar;
I, L : Integer;
begin
L := Length(S);
if (StartIndex > L) or (StartIndex < 1) then
begin
Result := 0;
exit;
end;
P := Pointer(S);
Inc(P, StartIndex - 1);
For I := StartIndex to L do
if WidePMatch(F, P) then
begin
Result := I;
exit;
end
else
Inc(P);
Result := 0;
end;
{ }
{ Replace }
{ }
procedure WideReplaceChar(const Find: WideChar; const Replace: WideString; var S: WideString);
var C, L, M, I, R : Integer;
P, Q : PWideChar;
T : WideString;
begin
C := WideCountChar(Find, S);
if C = 0 then
exit;
R := Length(Replace);
M := Length(S);
L := M + (R - 1) * C;
if L = 0 then
begin
S := '';
exit;
end;
SetLength(T, L);
P := Pointer(S);
Q := Pointer(T);
For I := 1 to M do
if P^ = Find then
begin
if R > 0 then
begin
Move(Pointer(Replace)^, Q^, Sizeof(WideChar) * R);
Inc(Q, R);
end;
Inc(P);
end
else
begin
Q^ := P^;
Inc(P);
Inc(Q);
end;
S := T;
end;
procedure WideSetLengthAndZero(var S: WideString; const NewLength: Integer);
var L : Integer;
P : PWideChar;
begin
L := Length(S);
if L = NewLength then
exit;
SetLength(S, NewLength);
if L > NewLength then
exit;
P := Pointer(S);
Inc(P, L);
FillChar(P^, (NewLength - L) * Sizeof(WideChar), #0);
end;
{$IFDEF DELPHI5}
function WideUpperCase(const S: WideString): WideString;
var I : Integer;
begin
Result := '';
For I := 1 to Length(S) do
Result := Result + WideUpCaseFolding(S[I]);
end;
function WideLowerCase(const S: WideString): WideString;
var I : Integer;
begin
Result := '';
For I := 1 to Length(S) do
Result := Result + WideLowCaseFolding(S[I]);
end;
{$ENDIF}
function WideCopyRange(const S: WideString; const StartIndex, StopIndex: Integer): WideString;
var L, I : Integer;
begin
L := Length(S);
if (StartIndex > StopIndex) or (StopIndex < 1) or (StartIndex > L) or (L = 0) then
Result := ''
else
begin
if StartIndex <= 1 then
if StopIndex >= L then
begin
Result := S;
exit;
end
else
I := 1
else
I := StartIndex;
Result := Copy(S, I, StopIndex - I + 1);
end;
end;
function WideCopyFrom(const S: WideString; const Index: Integer): WideString;
var L : Integer;
begin
if Index <= 1 then
Result := S
else
begin
L := Length(S);
if (L = 0) or (Index > L) then
Result := ''
else
Result := Copy(S, Index, L - Index + 1);
end;
end;
{ }
{ Dynamic Array functions }
{ }
function WideAppend(var V : WideStringArray; const R: WideString): Integer;
begin
Result := Length(V);
SetLength(V, Result + 1);
V[Result] := R;
end;
function WideAppendWideStringArray(var V : WideStringArray; const R: WideStringArray): Integer;
var I, LR : Integer;
begin
Result := Length(V);
LR := Length(R);
if LR > 0 then
begin
SetLength(V, Result + LR);
For I := 0 to LR - 1 do
V[Result + I] := R[I];
end;
end;
function WideSplit(const S, D: WideString): WideStringArray;
var I, J, L, M: Integer;
begin
if S = '' then
begin
Result := nil;
exit;
end;
M := Length(D);
if M = 0 then
begin
SetLength(Result, 1);
Result[0] := S;
exit;
end;
L := 0;
I := 1;
Repeat
I := WidePos(D, S, I);
if I = 0 then
break;
Inc(L);
Inc(I, M);
Until False;
SetLength(Result, L + 1);
if L = 0 then
begin
Result[0] := S;
exit;
end;
L := 0;
I := 1;
Repeat
J := WidePos(D, S, I);
if J = 0 then
begin
Result[L] := WideCopyFrom(S, I);
break;
end;
Result[L] := WideCopyRange(S, I, J - 1);
Inc(L);
I := J + M;
Until False;
end;
{ }
{ Self-testing code }
{ }
{$ASSERTIONS ON}
procedure SelfTest;
var S: WideString;
begin
Assert(WideMatchAnsiCharNoCase('A', 'a'), 'WideMatchAnsiCharNoCase');
Assert(WideMatchAnsiCharNoCase('z', 'Z'), 'WideMatchAnsiCharNoCase');
Assert(WideMatchAnsiCharNoCase('1', '1'), 'WideMatchAnsiCharNoCase');
Assert(not WideMatchAnsiCharNoCase('A', 'B'), 'WideMatchAnsiCharNoCase');
Assert(not WideMatchAnsiCharNoCase('0', 'A'), 'WideMatchAnsiCharNoCase');
Assert(WidePMatchAnsiStr('Unicode', 'uNicode', False), 'WidePMatchAnsiStr');
Assert(not WidePMatchAnsiStr('Unicode', 'uNicode', True), 'WidePMatchAnsiStr');
Assert(WidePMatchAnsiStr('Unicode', 'Unicode', True), 'WidePMatchAnsiStr');
Assert(WideTrimLeft(' X ') = 'X ', 'WideTrimLeft');
Assert(WideTrimRight(' X ') = ' X', 'WideTrimRight');
Assert(WideTrim(' X ') = 'X', 'WideTrim');
Assert(WideDup('X', 0) = '', 'WideDup');
Assert(WideDup('X', 1) = 'X', 'WideDup');
Assert(WideDup('A', 4) = 'AAAA', 'WideDup');
S := 'AXAYAA';
WideReplaceChar('A', '', S);
Assert(S = 'XY', 'WideReplaceChar');
S := 'AXAYAA';
WideReplaceChar('A', 'B', S);
Assert(S = 'BXBYBB', 'WideReplaceChar');
S := 'AXAYAA';
WideReplaceChar('A', 'CC', S);
Assert(S = 'CCXCCYCCCC', 'WideReplaceChar');
S := 'AXAXAA';
WideReplaceChar('X', 'IJK', S);
Assert(S = 'AIJKAIJKAA', 'WideReplaceChar');
Assert(WidePosChar(WideChar('A'), 'XYZABCAACDEF', 1) = 4, 'WidePosChar');
Assert(WidePosChar(WideChar('A'), 'XYZABCAACDEF', 5) = 7, 'WidePosChar');
Assert(WidePosChar(WideChar('A'), 'XYZABCAACDEF', 8) = 8, 'WidePosChar');
Assert(WidePosChar(WideChar('A'), 'XYZABCAACDEF', 9) = 0, 'WidePosChar');
Assert(WidePosChar(WideChar('Q'), 'XYZABCAACDEF', 1) = 0, 'WidePosChar');
Assert(WidePos('AB', 'XYZABCAACDEF', 1) = 4, 'WidePos');
Assert(WidePos('AA', 'XYZABCAACDEF', 1) = 7, 'WidePos');
Assert(WidePos('A', 'XYZABCAACDEF', 8) = 8, 'WidePos');
Assert(WidePos('AA', 'XYZABCAACDEF', 8) = 0, 'WidePos');
Assert(WidePos('AAQ', 'XYZABCAACDEF', 1) = 0, 'WidePos');
Assert(WideZPosAnsiChar('A', 'XYZABCAACDEF') = 3, 'WideZPosAnsiChar');
Assert(WideZPosAnsiChar('Q', 'XYZABCAACDEF') = -1, 'WideZPosAnsiChar');
end;
end.