mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-16 18:39:19 +02:00
* completed cwstring unit
* optimized LowerWideString/UpperWideString not to call UniqueString for each string character * fixed LowerAnsiString/UpperAnsiString in case an ascii character has a lower/uppercase version with a different length than 1 + generic test for ansistring comparisons using on the widestring manager (based on glibc test) - removed ansi2ucs4-related stuff as it's not used/needed git-svn-id: trunk@9440 -
This commit is contained in:
parent
32921dcafb
commit
60ccf03a0b
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -7407,6 +7407,7 @@ tests/test/units/system/tvalc.pp -text
|
|||||||
tests/test/units/sysutils/execansi.pp svneol=native#text/plain
|
tests/test/units/sysutils/execansi.pp svneol=native#text/plain
|
||||||
tests/test/units/sysutils/execedbya.pp svneol=native#text/plain
|
tests/test/units/sysutils/execedbya.pp svneol=native#text/plain
|
||||||
tests/test/units/sysutils/extractquote.pp svneol=native#text/plain
|
tests/test/units/sysutils/extractquote.pp svneol=native#text/plain
|
||||||
|
tests/test/units/sysutils/tastrcmp.pp svneol=native#text/plain
|
||||||
tests/test/units/sysutils/tfile1.pp svneol=native#text/plain
|
tests/test/units/sysutils/tfile1.pp svneol=native#text/plain
|
||||||
tests/test/units/sysutils/tfloattostr.pp -text
|
tests/test/units/sysutils/tfloattostr.pp -text
|
||||||
tests/test/units/sysutils/tsscanf.pp svneol=native#text/plain
|
tests/test/units/sysutils/tsscanf.pp svneol=native#text/plain
|
||||||
|
@ -46,20 +46,20 @@ Const
|
|||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
{ helper functions from libc }
|
{ helper functions from libc }
|
||||||
function tolower(__wc:cint):cint;cdecl;external libiconvname name 'tolower';
|
function towlower(__wc:wint_t):wint_t;cdecl;external clib name 'towlower';
|
||||||
function toupper(__wc:cint):cint;cdecl;external libiconvname name 'toupper';
|
function towupper(__wc:wint_t):wint_t;cdecl;external clib name 'towupper';
|
||||||
function towlower(__wc:wint_t):wint_t;cdecl;external libiconvname name 'towlower';
|
|
||||||
function towupper(__wc:wint_t):wint_t;cdecl;external libiconvname name 'towupper';
|
|
||||||
|
|
||||||
function wcscoll (__s1:pwchar_t; __s2:pwchar_t):cint;cdecl;external libiconvname name 'wcscoll';
|
function wcscoll (__s1:pwchar_t; __s2:pwchar_t):cint;cdecl;external clib name 'wcscoll';
|
||||||
function strcoll (__s1:pchar; __s2:pchar):cint;cdecl;external libiconvname name 'strcoll';
|
function strcoll (__s1:pchar; __s2:pchar):cint;cdecl;external clib name 'strcoll';
|
||||||
function setlocale(category: cint; locale: pchar): pchar; cdecl; external clib name 'setlocale';
|
function setlocale(category: cint; locale: pchar): pchar; cdecl; external clib name 'setlocale';
|
||||||
{$ifndef beos}
|
{$ifndef beos}
|
||||||
function mbrtowc(pwc: pwchar_t; const s: pchar; n: size_t; ps: pmbstate_t): size_t; cdecl; external clib name 'mbrtowc';
|
function mbrtowc(pwc: pwchar_t; const s: pchar; n: size_t; ps: pmbstate_t): size_t; cdecl; external clib name 'mbrtowc';
|
||||||
function wcrtomb(s: pchar; wc: wchar_t; ps: pmbstate_t): size_t; cdecl; external clib name 'wcrtomb';
|
function wcrtomb(s: pchar; wc: wchar_t; ps: pmbstate_t): size_t; cdecl; external clib name 'wcrtomb';
|
||||||
|
function mbrlen(const s: pchar; n: size_t; ps: pmbstate_t): size_t; cdecl; external clib name 'mbrlen';
|
||||||
{$else beos}
|
{$else beos}
|
||||||
function mbtowc(pwc: pwchar_t; const s: pchar; n: size_t): size_t; cdecl; external clib name 'mbtowc';
|
function mbtowc(pwc: pwchar_t; const s: pchar; n: size_t): size_t; cdecl; external clib name 'mbtowc';
|
||||||
function wctomb(s: pchar; wc: wchar_t): size_t; cdecl; external clib name 'wctomb';
|
function wctomb(s: pchar; wc: wchar_t): size_t; cdecl; external clib name 'wctomb';
|
||||||
|
function mblen(const s: pchar; n: size_t): size_t; cdecl; external clib name 'mblen';
|
||||||
{$endif beos}
|
{$endif beos}
|
||||||
|
|
||||||
|
|
||||||
@ -109,6 +109,13 @@ const
|
|||||||
unicode_encoding4 = 'UCS-4BE';
|
unicode_encoding4 = 'UCS-4BE';
|
||||||
{$endif FPC_LITTLE_ENDIAN}
|
{$endif FPC_LITTLE_ENDIAN}
|
||||||
|
|
||||||
|
{ en_US.UTF-8 needs maximally 6 chars, UCS-4/UTF-32 needs 4 }
|
||||||
|
{ -> 10 should be enough? Should actually use MB_CUR_MAX, but }
|
||||||
|
{ that's a libc macro mapped to internal functions/variables }
|
||||||
|
{ and thus not a stable external API on systems where libc }
|
||||||
|
{ breaks backwards compatibility every now and then }
|
||||||
|
MB_CUR_MAX = 10;
|
||||||
|
|
||||||
type
|
type
|
||||||
piconv_t = ^iconv_t;
|
piconv_t = ^iconv_t;
|
||||||
iconv_t = pointer;
|
iconv_t = pointer;
|
||||||
@ -127,9 +134,10 @@ function iconv(__cd:iconv_t; __inbuf:ppchar; __inbytesleft:psize_t; __outbuf:ppc
|
|||||||
function iconv_close(__cd:iconv_t):cint;cdecl;external libiconvname name 'libiconv_close';
|
function iconv_close(__cd:iconv_t):cint;cdecl;external libiconvname name 'libiconv_close';
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
|
procedure fpc_rangeerror; [external name 'FPC_RANGEERROR'];
|
||||||
|
|
||||||
|
|
||||||
threadvar
|
threadvar
|
||||||
iconv_ansi2ucs4,
|
|
||||||
iconv_ucs42ansi,
|
|
||||||
iconv_ansi2wide,
|
iconv_ansi2wide,
|
||||||
iconv_wide2ansi : iconv_t;
|
iconv_wide2ansi : iconv_t;
|
||||||
|
|
||||||
@ -270,8 +278,8 @@ function LowerWideString(const s : WideString) : WideString;
|
|||||||
i : SizeInt;
|
i : SizeInt;
|
||||||
begin
|
begin
|
||||||
SetLength(result,length(s));
|
SetLength(result,length(s));
|
||||||
for i:=1 to length(s) do
|
for i:=0 to length(s)-1 do
|
||||||
result[i]:=WideChar(towlower(wint_t(s[i])));
|
pwidechar(result)[i]:=WideChar(towlower(wint_t(s[i+1])));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -280,8 +288,8 @@ function UpperWideString(const s : WideString) : WideString;
|
|||||||
i : SizeInt;
|
i : SizeInt;
|
||||||
begin
|
begin
|
||||||
SetLength(result,length(s));
|
SetLength(result,length(s));
|
||||||
for i:=1 to length(s) do
|
for i:=0 to length(s)-1 do
|
||||||
result[i]:=WideChar(towupper(wint_t(s[i])));
|
pwidechar(result)[i]:=WideChar(towupper(wint_t(s[i+1])));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -319,12 +327,7 @@ begin
|
|||||||
ConcatCharToAnsiStr(char(nc),s,index)
|
ConcatCharToAnsiStr(char(nc),s,index)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
{ en_US.UTF-8 needs maximally 6 chars, UCS-4/UTF-32 needs 4 }
|
EnsureAnsiLen(s,index+MB_CUR_MAX);
|
||||||
{ -> 10 should be enough? Should actually use MB_CUR_MAX, but }
|
|
||||||
{ that's a libc macro mapped to internal functions/variables }
|
|
||||||
{ and thus not a stable external API on systems where libc }
|
|
||||||
{ breaks backwards compatibility every now and then }
|
|
||||||
EnsureAnsiLen(s,index+10);
|
|
||||||
{$ifndef beos}
|
{$ifndef beos}
|
||||||
mblen:=wcrtomb(p,wchar_t(nc),@mbstate);
|
mblen:=wcrtomb(p,wchar_t(nc),@mbstate);
|
||||||
{$else not beos}
|
{$else not beos}
|
||||||
@ -365,46 +368,44 @@ function LowerAnsiString(const s : AnsiString) : AnsiString;
|
|||||||
begin
|
begin
|
||||||
if (s[i]<=#127) then
|
if (s[i]<=#127) then
|
||||||
begin
|
begin
|
||||||
ConcatCharToAnsiStr(char(tolower(cint(s[i]))),result,resindex);
|
wc:=wchar_t(s[i]);
|
||||||
inc(i)
|
mblen:= 1;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
|
||||||
{$ifndef beos}
|
{$ifndef beos}
|
||||||
mblen:=mbrtowc(@wc, pchar(@s[i]), slen-i+1, @ombstate);
|
mblen:=mbrtowc(@wc, pchar(@s[i]), slen-i+1, @ombstate);
|
||||||
{$else not beos}
|
{$else not beos}
|
||||||
mblen:=mbtowc(@wc, pchar(@s[i]), slen-i+1);
|
mblen:=mbtowc(@wc, pchar(@s[i]), slen-i+1);
|
||||||
{$endif not beos}
|
{$endif not beos}
|
||||||
case mblen of
|
case mblen of
|
||||||
size_t(-2):
|
size_t(-2):
|
||||||
begin
|
begin
|
||||||
{ partial invalid character, copy literally }
|
{ partial invalid character, copy literally }
|
||||||
while (i<=slen) do
|
while (i<=slen) do
|
||||||
begin
|
begin
|
||||||
ConcatCharToAnsiStr(s[i],result,resindex);
|
ConcatCharToAnsiStr(s[i],result,resindex);
|
||||||
inc(i);
|
inc(i);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
size_t(-1), 0:
|
size_t(-1), 0:
|
||||||
begin
|
begin
|
||||||
{ invalid or null character }
|
{ invalid or null character }
|
||||||
ConcatCharToAnsiStr(s[i],result,resindex);
|
ConcatCharToAnsiStr(s[i],result,resindex);
|
||||||
inc(i);
|
inc(i);
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
{ a valid sequence }
|
{ a valid sequence }
|
||||||
{ even if mblen = 1, the lowercase version may have a }
|
{ even if mblen = 1, the lowercase version may have a }
|
||||||
{ different length }
|
{ different length }
|
||||||
{ We can't do anything special if wchar_t is 16 bit... }
|
{ We can't do anything special if wchar_t is 16 bit... }
|
||||||
{$ifndef beos}
|
{$ifndef beos}
|
||||||
ConcatUTF32ToAnsiStr(towlower(wint_t(wc)),result,resindex,nmbstate);
|
ConcatUTF32ToAnsiStr(towlower(wint_t(wc)),result,resindex,nmbstate);
|
||||||
{$else not beos}
|
{$else not beos}
|
||||||
ConcatUTF32ToAnsiStr(towlower(wint_t(wc)),result,resindex);
|
ConcatUTF32ToAnsiStr(towlower(wint_t(wc)),result,resindex);
|
||||||
{$endif not beos}
|
{$endif not beos}
|
||||||
inc(i,mblen);
|
inc(i,mblen);
|
||||||
end;
|
end;
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
SetLength(result,resindex-1);
|
SetLength(result,resindex-1);
|
||||||
@ -434,109 +435,50 @@ function UpperAnsiString(const s : AnsiString) : AnsiString;
|
|||||||
begin
|
begin
|
||||||
if (s[i]<=#127) then
|
if (s[i]<=#127) then
|
||||||
begin
|
begin
|
||||||
ConcatCharToAnsiStr(char(toupper(cint(s[i]))),result,resindex);
|
wc:=wchar_t(s[i]);
|
||||||
inc(i)
|
mblen:= 1;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
|
||||||
{$ifndef beos}
|
{$ifndef beos}
|
||||||
mblen:=mbrtowc(@wc, pchar(@s[i]), slen-i+1, @ombstate);
|
mblen:=mbrtowc(@wc, pchar(@s[i]), slen-i+1, @ombstate);
|
||||||
{$else not beos}
|
{$else not beos}
|
||||||
mblen:=mbtowc(@wc, pchar(@s[i]), slen-i+1);
|
mblen:=mbtowc(@wc, pchar(@s[i]), slen-i+1);
|
||||||
{$endif beos}
|
{$endif beos}
|
||||||
case mblen of
|
case mblen of
|
||||||
size_t(-2):
|
size_t(-2):
|
||||||
begin
|
begin
|
||||||
{ partial invalid character, copy literally }
|
{ partial invalid character, copy literally }
|
||||||
while (i<=slen) do
|
while (i<=slen) do
|
||||||
begin
|
begin
|
||||||
ConcatCharToAnsiStr(s[i],result,resindex);
|
ConcatCharToAnsiStr(s[i],result,resindex);
|
||||||
inc(i);
|
inc(i);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
size_t(-1), 0:
|
size_t(-1), 0:
|
||||||
begin
|
begin
|
||||||
{ invalid or null character }
|
{ invalid or null character }
|
||||||
ConcatCharToAnsiStr(s[i],result,resindex);
|
ConcatCharToAnsiStr(s[i],result,resindex);
|
||||||
inc(i);
|
inc(i);
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
{ a valid sequence }
|
{ a valid sequence }
|
||||||
{ even if mblen = 1, the uppercase version may have a }
|
{ even if mblen = 1, the uppercase version may have a }
|
||||||
{ different length }
|
{ different length }
|
||||||
{ We can't do anything special if wchar_t is 16 bit... }
|
{ We can't do anything special if wchar_t is 16 bit... }
|
||||||
{$ifndef beos}
|
{$ifndef beos}
|
||||||
ConcatUTF32ToAnsiStr(towupper(wint_t(wc)),result,resindex,nmbstate);
|
ConcatUTF32ToAnsiStr(towupper(wint_t(wc)),result,resindex,nmbstate);
|
||||||
{$else not beos}
|
{$else not beos}
|
||||||
ConcatUTF32ToAnsiStr(towupper(wint_t(wc)),result,resindex);
|
ConcatUTF32ToAnsiStr(towupper(wint_t(wc)),result,resindex);
|
||||||
{$endif not beos}
|
{$endif not beos}
|
||||||
inc(i,mblen);
|
inc(i,mblen);
|
||||||
end;
|
end;
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
SetLength(result,resindex-1);
|
SetLength(result,resindex-1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure Ansi2UCS4Move(source:pchar;var dest:UCS4String;len:SizeInt);
|
|
||||||
var
|
|
||||||
outlength,
|
|
||||||
outoffset,
|
|
||||||
outleft : size_t;
|
|
||||||
err: cint;
|
|
||||||
srcpos,
|
|
||||||
destpos: pchar;
|
|
||||||
mynil : pchar;
|
|
||||||
my0 : size_t;
|
|
||||||
begin
|
|
||||||
mynil:=nil;
|
|
||||||
my0:=0;
|
|
||||||
// extra space
|
|
||||||
outlength:=len+1;
|
|
||||||
setlength(dest,outlength);
|
|
||||||
outlength:=len+1;
|
|
||||||
srcpos:=source;
|
|
||||||
destpos:=pchar(dest);
|
|
||||||
outleft:=outlength*4;
|
|
||||||
while iconv(iconv_ansi2ucs4,@srcpos,psize(@len),@destpos,@outleft)=size_t(-1) do
|
|
||||||
begin
|
|
||||||
err:=fpgetCerrno;
|
|
||||||
case err of
|
|
||||||
ESysEINVAL,
|
|
||||||
ESysEILSEQ:
|
|
||||||
begin
|
|
||||||
{ skip and set to '?' }
|
|
||||||
inc(srcpos);
|
|
||||||
dec(len);
|
|
||||||
plongint(destpos)^:=longint('?');
|
|
||||||
inc(destpos,4);
|
|
||||||
dec(outleft,4);
|
|
||||||
{ reset }
|
|
||||||
iconv(iconv_ansi2ucs4,@mynil,@my0,@mynil,@my0);
|
|
||||||
if err=ESysEINVAL then
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
ESysE2BIG:
|
|
||||||
begin
|
|
||||||
outoffset:=destpos-pchar(dest);
|
|
||||||
{ extend }
|
|
||||||
setlength(dest,outlength+len);
|
|
||||||
inc(outleft,len*4);
|
|
||||||
inc(outlength,len);
|
|
||||||
{ string could have been moved }
|
|
||||||
destpos:=pchar(dest)+outoffset;
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
runerror(231);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
// truncate string
|
|
||||||
setlength(dest,length(dest)-outleft div 4);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
function utf16toutf32(const S: WideString; const index: SizeInt; out len: longint): UCS4Char; external name 'FPC_UTF16TOUTF32';
|
function utf16toutf32(const S: WideString; const index: SizeInt; out len: longint): UCS4Char; external name 'FPC_UTF16TOUTF32';
|
||||||
|
|
||||||
function WideStringToUCS4StringNoNulls(const s : WideString) : UCS4String;
|
function WideStringToUCS4StringNoNulls(const s : WideString) : UCS4String;
|
||||||
@ -582,18 +524,169 @@ function CompareTextWideString(const s1, s2 : WideString): PtrInt;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function CharLengthPChar(const Str: PChar): PtrInt;
|
||||||
|
var
|
||||||
|
nextlen: ptrint;
|
||||||
|
s: pchar;
|
||||||
|
{$ifndef beos}
|
||||||
|
mbstate: mbstate_t;
|
||||||
|
{$endif not beos}
|
||||||
|
begin
|
||||||
|
result:=0;
|
||||||
|
s:=str;
|
||||||
|
repeat
|
||||||
|
{$ifdef beos}
|
||||||
|
nextlen:=ptrint(mblen(str,MB_CUR_MAX));
|
||||||
|
{$else beos}
|
||||||
|
nextlen:=ptrint(mbrlen(str,MB_CUR_MAX,@mbstate));
|
||||||
|
{$endif beos}
|
||||||
|
{ skip invalid/incomplete sequences }
|
||||||
|
if (nextlen<0) then
|
||||||
|
nextlen:=1;
|
||||||
|
inc(result,nextlen);
|
||||||
|
inc(s,nextlen);
|
||||||
|
until (nextlen=0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function StrCompAnsiIntern(const s1,s2 : PChar; len1, len2: PtrInt): PtrInt;
|
||||||
|
var
|
||||||
|
a,b: pchar;
|
||||||
|
i: PtrInt;
|
||||||
|
begin
|
||||||
|
getmem(a,len1+1);
|
||||||
|
getmem(b,len2+1);
|
||||||
|
for i:=0 to len1-1 do
|
||||||
|
if s1[i]<>#0 then
|
||||||
|
a[i]:=s1[i]
|
||||||
|
else
|
||||||
|
a[i]:=#32;
|
||||||
|
a[len1]:=#0;
|
||||||
|
for i:=0 to len2-1 do
|
||||||
|
if s2[i]<>#0 then
|
||||||
|
b[i]:=s2[i]
|
||||||
|
else
|
||||||
|
b[i]:=#32;
|
||||||
|
b[len2]:=#0;
|
||||||
|
result:=strcoll(a,b);
|
||||||
|
freemem(a);
|
||||||
|
freemem(b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function CompareStrAnsiString(const s1, s2: ansistring): PtrInt;
|
||||||
|
begin
|
||||||
|
result:=StrCompAnsiIntern(pchar(s1),pchar(s2),length(s1),length(s2));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function StrCompAnsi(s1,s2 : PChar): PtrInt;
|
function StrCompAnsi(s1,s2 : PChar): PtrInt;
|
||||||
begin
|
begin
|
||||||
result:=strcoll(s1,s2);
|
result:=strcoll(s1,s2);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function AnsiCompareText(const S1, S2: ansistring): PtrInt;
|
||||||
|
var
|
||||||
|
a, b: AnsiString;
|
||||||
|
begin
|
||||||
|
a:=UpperAnsistring(s1);
|
||||||
|
b:=UpperAnsistring(s2);
|
||||||
|
result:=StrCompAnsiIntern(pchar(a),pchar(b),length(a),length(b));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function AnsiStrIComp(S1, S2: PChar): PtrInt;
|
||||||
|
begin
|
||||||
|
result:=AnsiCompareText(ansistring(s1),ansistring(s2));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function AnsiStrLComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
|
||||||
|
var
|
||||||
|
a, b: pchar;
|
||||||
|
begin
|
||||||
|
if (IndexChar(s1^,maxlen,#0)<0) then
|
||||||
|
begin
|
||||||
|
getmem(a,maxlen+1);
|
||||||
|
move(s1^,a^,maxlen);
|
||||||
|
a[maxlen]:=#0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
a:=s1;
|
||||||
|
if (IndexChar(s2^,maxlen,#0)<0) then
|
||||||
|
begin
|
||||||
|
getmem(b,maxlen+1);
|
||||||
|
move(s2^,b^,maxlen);
|
||||||
|
b[maxlen]:=#0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
b:=s2;
|
||||||
|
result:=strcoll(a,b);
|
||||||
|
if (a<>s1) then
|
||||||
|
freemem(a);
|
||||||
|
if (b<>s2) then
|
||||||
|
freemem(b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function AnsiStrLIComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
|
||||||
|
var
|
||||||
|
a, b: ansistring;
|
||||||
|
len1,len2: SizeInt;
|
||||||
|
begin
|
||||||
|
len1:=IndexChar(s1^,maxlen,#0);
|
||||||
|
if (len1<0) then
|
||||||
|
len1:=maxlen;
|
||||||
|
setlength(a,len1);
|
||||||
|
if (len1<>0) then
|
||||||
|
move(s1^,a[1],len1);
|
||||||
|
len2:=IndexChar(s2^,maxlen,#0);
|
||||||
|
if (len2<0) then
|
||||||
|
len2:=maxlen;
|
||||||
|
setlength(b,len2);
|
||||||
|
if (len2<>0) then
|
||||||
|
move(s2^,b[1],len2);
|
||||||
|
result:=AnsiCompareText(a,b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure ansi2pchar(const s: ansistring; const orgp: pchar; out p: pchar);
|
||||||
|
var
|
||||||
|
newlen: sizeint;
|
||||||
|
begin
|
||||||
|
newlen:=length(s);
|
||||||
|
if newlen>strlen(orgp) then
|
||||||
|
fpc_rangeerror;
|
||||||
|
p:=orgp;
|
||||||
|
if (newlen>0) then
|
||||||
|
move(s[1],p[0],newlen);
|
||||||
|
p[newlen]:=#0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function AnsiStrLower(Str: PChar): PChar;
|
||||||
|
var
|
||||||
|
temp: ansistring;
|
||||||
|
begin
|
||||||
|
temp:=upperansistring(str);
|
||||||
|
ansi2pchar(temp,str,result);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function AnsiStrUpper(Str: PChar): PChar;
|
||||||
|
var
|
||||||
|
temp: ansistring;
|
||||||
|
begin
|
||||||
|
temp:=loweransistring(str);
|
||||||
|
ansi2pchar(temp,str,result);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure InitThread;
|
procedure InitThread;
|
||||||
begin
|
begin
|
||||||
iconv_wide2ansi:=iconv_open(nl_langinfo(CODESET),unicode_encoding2);
|
iconv_wide2ansi:=iconv_open(nl_langinfo(CODESET),unicode_encoding2);
|
||||||
iconv_ansi2wide:=iconv_open(unicode_encoding2,nl_langinfo(CODESET));
|
iconv_ansi2wide:=iconv_open(unicode_encoding2,nl_langinfo(CODESET));
|
||||||
iconv_ucs42ansi:=iconv_open(nl_langinfo(CODESET),unicode_encoding4);
|
|
||||||
iconv_ansi2ucs4:=iconv_open(unicode_encoding4,nl_langinfo(CODESET));
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -603,10 +696,6 @@ begin
|
|||||||
iconv_close(iconv_wide2ansi);
|
iconv_close(iconv_wide2ansi);
|
||||||
if (iconv_ansi2wide <> iconv_t(-1)) then
|
if (iconv_ansi2wide <> iconv_t(-1)) then
|
||||||
iconv_close(iconv_ansi2wide);
|
iconv_close(iconv_ansi2wide);
|
||||||
if (iconv_ucs42ansi <> iconv_t(-1)) then
|
|
||||||
iconv_close(iconv_ucs42ansi);
|
|
||||||
if (iconv_ansi2ucs4 <> iconv_t(-1)) then
|
|
||||||
iconv_close(iconv_ansi2ucs4);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -625,23 +714,19 @@ begin
|
|||||||
|
|
||||||
CompareWideStringProc:=@CompareWideString;
|
CompareWideStringProc:=@CompareWideString;
|
||||||
CompareTextWideStringProc:=@CompareTextWideString;
|
CompareTextWideStringProc:=@CompareTextWideString;
|
||||||
{
|
|
||||||
CharLengthPCharProc
|
CharLengthPCharProc:=@CharLengthPChar;
|
||||||
}
|
|
||||||
UpperAnsiStringProc:=@UpperAnsiString;
|
UpperAnsiStringProc:=@UpperAnsiString;
|
||||||
LowerAnsiStringProc:=@LowerAnsiString;
|
LowerAnsiStringProc:=@LowerAnsiString;
|
||||||
{
|
CompareStrAnsiStringProc:=@CompareStrAnsiString;
|
||||||
CompareStrAnsiStringProc
|
CompareTextAnsiStringProc:=@AnsiCompareText;
|
||||||
CompareTextAnsiStringProc
|
|
||||||
}
|
|
||||||
StrCompAnsiStringProc:=@StrCompAnsi;
|
StrCompAnsiStringProc:=@StrCompAnsi;
|
||||||
{
|
StrICompAnsiStringProc:=@AnsiStrIComp;
|
||||||
StrICompAnsiStringProc
|
StrLCompAnsiStringProc:=@AnsiStrLComp;
|
||||||
StrLCompAnsiStringProc
|
StrLICompAnsiStringProc:=@AnsiStrLIComp;
|
||||||
StrLICompAnsiStringProc
|
StrLowerAnsiStringProc:=@AnsiStrLower;
|
||||||
StrLowerAnsiStringProc
|
StrUpperAnsiStringProc:=@AnsiStrUpper;
|
||||||
StrUpperAnsiStringProc
|
|
||||||
}
|
|
||||||
ThreadInitProc:=@InitThread;
|
ThreadInitProc:=@InitThread;
|
||||||
ThreadFiniProc:=@FiniThread;
|
ThreadFiniProc:=@FiniThread;
|
||||||
end;
|
end;
|
||||||
|
167
tests/test/units/sysutils/tastrcmp.pp
Normal file
167
tests/test/units/sysutils/tastrcmp.pp
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
{ based on string/tester.c of glibc 2.3.6
|
||||||
|
|
||||||
|
* Tester for string functions.
|
||||||
|
Copyright (C) 1995-2000, 2001, 2003 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the GNU C Library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
}
|
||||||
|
|
||||||
|
{$ifdef fpc}
|
||||||
|
{$mode delphi}
|
||||||
|
{$endif fpc}
|
||||||
|
|
||||||
|
uses
|
||||||
|
{$ifdef unix}
|
||||||
|
cwstring,
|
||||||
|
{$endif unix}
|
||||||
|
SysUtils;
|
||||||
|
|
||||||
|
var
|
||||||
|
teststr: string;
|
||||||
|
goterror: boolean;
|
||||||
|
|
||||||
|
procedure check(b: boolean; testnr: longint);
|
||||||
|
begin
|
||||||
|
if not (b) then
|
||||||
|
begin
|
||||||
|
writeln(teststr,' error nr ',testnr);
|
||||||
|
goterror:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure testAnsiCompareText;
|
||||||
|
begin
|
||||||
|
teststr:='AnsiCompareText';
|
||||||
|
check(ansicomparetext('a', 'a') = 0, 1);
|
||||||
|
check(ansicomparetext('a', 'A') = 0, 2);
|
||||||
|
check(ansicomparetext('A', 'a') = 0, 3);
|
||||||
|
check(ansicomparetext('a', 'b') < 0, 4);
|
||||||
|
check(ansicomparetext('c', 'b') > 0, 5);
|
||||||
|
check(ansicomparetext('abc', 'AbC') = 0, 6);
|
||||||
|
check(ansicomparetext('0123456789', '0123456789') = 0, 7);
|
||||||
|
check(ansicomparetext('', '0123456789') < 0, 8);
|
||||||
|
check(ansicomparetext('AbC', '') > 0, 9);
|
||||||
|
check(ansicomparetext('AbC', 'A') > 0, 10);
|
||||||
|
check(ansicomparetext('AbC', 'Ab') > 0, 11);
|
||||||
|
check(ansicomparetext('AbC', 'ab') > 0, 12);
|
||||||
|
check(ansicomparetext('Ab'#0'C', 'ab'#0) > 0, 13);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure testAnsiStrIComp;
|
||||||
|
begin
|
||||||
|
teststr:='AnsiStrIComp';
|
||||||
|
check(ansistricomp('a', 'a') = 0, 1);
|
||||||
|
check(ansistricomp('a', 'A') = 0, 2);
|
||||||
|
check(ansistricomp('A', 'a') = 0, 3);
|
||||||
|
check(ansistricomp('a', 'b') < 0, 4);
|
||||||
|
check(ansistricomp('c', 'b') > 0, 5);
|
||||||
|
check(ansistricomp('abc', 'AbC') = 0, 6);
|
||||||
|
check(ansistricomp('0123456789', '0123456789') = 0, 7);
|
||||||
|
check(ansistricomp('', '0123456789') < 0, 8);
|
||||||
|
check(ansistricomp('AbC', '') > 0, 9);
|
||||||
|
check(ansistricomp('AbC', 'A') > 0, 10);
|
||||||
|
check(ansistricomp('AbC', 'Ab') > 0, 11);
|
||||||
|
check(ansistricomp('AbC', 'ab') > 0, 12);
|
||||||
|
check(ansistricomp('Ab'#0'C', 'ab'#0) = 0, 13);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure testAnsiStrLComp;
|
||||||
|
begin
|
||||||
|
teststr:='AnsiStrIComp';
|
||||||
|
check (ansistrlcomp ('', '', 99) = 0, 1); { Trivial case. }
|
||||||
|
check (ansistrlcomp ('a', 'a', 99) = 0, 2); { Identity. }
|
||||||
|
check (ansistrlcomp ('abc', 'abc', 99) = 0, 3); { Multicharacter. }
|
||||||
|
check (ansistrlcomp ('abc', 'abcd', 99) < 0, 4); { Length unequal. }
|
||||||
|
check (ansistrlcomp ('abcd', 'abc', 99) > 0, 5);
|
||||||
|
check (ansistrlcomp ('abcd', 'abce', 99) < 0, 6); { Honestly unequal. }
|
||||||
|
check (ansistrlcomp ('abce', 'abcd', 99) > 0, 7);
|
||||||
|
check (ansistrlcomp ('abce', 'abcd', 3) = 0, 10); { Count limited. }
|
||||||
|
check (ansistrlcomp ('abce', 'abc', 3) = 0, 11); { Count = length. }
|
||||||
|
check (ansistrlcomp ('abcd', 'abce', 4) < 0, 12); { Nudging limit. }
|
||||||
|
check (ansistrlcomp ('abc', 'def', 0) = 0, 13); { Zero count. }
|
||||||
|
check (ansistrlcomp ('abc'#0'e', 'abc'#0'd', 99) = 0, 14);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure testAnsiCompareStr;
|
||||||
|
begin
|
||||||
|
teststr:='AnsiCompareStr';
|
||||||
|
check (ansicomparestr ('', '') = 0, 1); { Trivial case. }
|
||||||
|
check (ansicomparestr ('a', 'a') = 0, 2); { Identity. }
|
||||||
|
check (ansicomparestr ('abc', 'abc') = 0, 3); { Multicharacter. }
|
||||||
|
check (ansicomparestr ('abc', 'abcd') < 0, 4); { Length mismatches. }
|
||||||
|
check (ansicomparestr ('abcd', 'abc') > 0, 5);
|
||||||
|
check (ansicomparestr ('abcd', 'abce') < 0, 6); { Honest miscompares. }
|
||||||
|
check (ansicomparestr ('abce', 'abcd') > 0, 7);
|
||||||
|
check (ansicomparestr ('abc'#0'e', 'abc'#0'd') > 0, 8);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure testAnsiStrComp;
|
||||||
|
begin
|
||||||
|
teststr:='AnsiStrComp';
|
||||||
|
check (ansistrcomp ('', '') = 0, 1); { Trivial case. }
|
||||||
|
check (ansistrcomp ('a', 'a') = 0, 2); { Identity. }
|
||||||
|
check (ansistrcomp ('abc', 'abc') = 0, 3); { Multicharacter. }
|
||||||
|
check (ansistrcomp ('abc', 'abcd') < 0, 4); { Length mismatches. }
|
||||||
|
check (ansistrcomp ('abcd', 'abc') > 0, 5);
|
||||||
|
check (ansistrcomp ('abcd', 'abce') < 0, 6); { Honest miscompares. }
|
||||||
|
check (ansistrcomp ('abce', 'abcd') > 0, 7);
|
||||||
|
check (ansistrcomp ('abc'#0'e', 'abc'#0'd') = 0, 8);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure testAnsiStrLIComp;
|
||||||
|
begin
|
||||||
|
teststr:='AnsiStrLIComp';
|
||||||
|
check(ansistrlicomp('a', 'a', 5) = 0, 1);
|
||||||
|
check(ansistrlicomp('a', 'A', 5) = 0, 2);
|
||||||
|
check(ansistrlicomp('A', 'a', 5) = 0, 3);
|
||||||
|
check(ansistrlicomp('a', 'b', 5) < 0, 4);
|
||||||
|
check(ansistrlicomp('c', 'b', 5) > 0, 5);
|
||||||
|
check(ansistrlicomp('abc', 'AbC', 5) = 0, 6);
|
||||||
|
check(ansistrlicomp('0123456789', '0123456789', 10) = 0, 7);
|
||||||
|
check(ansistrlicomp('', '0123456789', 10) < 0, 8);
|
||||||
|
check(ansistrlicomp('AbC', '', 5) > 0, 9);
|
||||||
|
check(ansistrlicomp('AbC', 'A', 5) > 0, 10);
|
||||||
|
check(ansistrlicomp('AbC', 'Ab', 5) > 0, 11);
|
||||||
|
check(ansistrlicomp('AbC', 'ab', 5) > 0, 12);
|
||||||
|
check(ansistrlicomp('0123456789', 'AbC', 0) = 0, 13);
|
||||||
|
check(ansistrlicomp('AbC', 'abc', 1) = 0, 14);
|
||||||
|
check(ansistrlicomp('AbC', 'abc', 2) = 0, 15);
|
||||||
|
check(ansistrlicomp('AbC', 'abc', 3) = 0, 16);
|
||||||
|
check(ansistrlicomp('AbC', 'abcd', 3) = 0, 17);
|
||||||
|
check(ansistrlicomp('AbC', 'abcd', 4) < 0, 18);
|
||||||
|
check(ansistrlicomp('ADC', 'abcd', 1) = 0, 19);
|
||||||
|
check(ansistrlicomp('ADC', 'abcd', 2) > 0, 20);
|
||||||
|
check(ansistrlicomp('abc'#0'e', 'abc'#0'd', 99) = 0, 21);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
begin
|
||||||
|
goterror:=false;
|
||||||
|
testAnsiCompareText;
|
||||||
|
testAnsiStrIComp;
|
||||||
|
testAnsiStrLComp;
|
||||||
|
testAnsiCompareStr;
|
||||||
|
testAnsiStrComp;
|
||||||
|
testAnsiStrLIComp;
|
||||||
|
if goterror then
|
||||||
|
halt(1);
|
||||||
|
end.
|
Loading…
Reference in New Issue
Block a user