From 22b19220a3cfd35e08ae4eb2d1b181547c62d9f2 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 17 Sep 2011 13:34:37 +0000 Subject: [PATCH] merge r17485 from cpstrnew branch by michael: Patch from Inoussa: * rtl/inc/astrings.inc ** "fpc_AnsiStr_Concat_multi" : add "cp" parameter. If the "DestS" variable is "nil" this code page is use in order not to loose the declared code page of the original (result)variable. ** "fpc_AnsiStr_Compare" : modify to compare taking care of the code page of the arguments. ** "fpc_AnsiStr_Compare_equal" : modify to compare taking care of the code page of the arguments. ** "fpc_AnsiStr_SetLength" : add "cp" parameter. If the "S" variable is "nil" this code page is use in order not to loose the declared code page of the original (result)variable. * rtl/inc/systemh.inc ** add "SetCodePage" prototype. git-svn-id: trunk@19114 - --- rtl/inc/astrings.inc | 138 +++++++++++++++++++++++++++++++++++++------ rtl/inc/compproc.inc | 8 +-- rtl/inc/systemh.inc | 1 + 3 files changed, 124 insertions(+), 23 deletions(-) diff --git a/rtl/inc/astrings.inc b/rtl/inc/astrings.inc index 68c168696c..1becfe8585 100644 --- a/rtl/inc/astrings.inc +++ b/rtl/inc/astrings.inc @@ -270,19 +270,62 @@ begin end; -procedure fpc_AnsiStr_Concat_multi (var DestS:ansistring;const sarr:array of Ansistring); compilerproc; +procedure fpc_AnsiStr_Concat_multi (var DestS:RawByteString;const sarr:array of RawByteString{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}); compilerproc; Var lowstart,i : Longint; p,pc : pointer; Size,NewLen, OldDestLen : SizeInt; - destcopy : pointer; + destcopy : pointer; + DestCP : TSystemCodePage; + U : UnicodeString; + sameCP : Boolean; + tmpStr : RawByteString; begin if high(sarr)=0 then begin DestS:=''; exit; end; +{$ifdef FPC_HAS_CPSTRING} + if (Pointer(DestS)=nil) then + DestCP:=cp + else + DestCP:=StringCodePage(DestS); +{$else FPC_HAS_CPSTRING} + DestCP:=StringCodePage(DestS); +{$endif FPC_HAS_CPSTRING} + if (DestCP=$ffff) then + DestCP:=DefaultSystemCodePage; + sameCP:=true; + lowstart:=low(sarr); + for i:=lowstart to high(sarr) do + begin + if (DestCP<>StringCodePage(sarr[i])) then + begin + sameCP:=false; + break; + end; + end; + if not sameCP then + begin + U:=''; + for i:=lowstart to high(sarr) do begin + if (StringCodePage(sarr[i]) = $ffff) then + begin + tmpStr:=sarr[i]; + SetCodePage(tmpStr,DefaultSystemCodePage,False); + U:=U+UnicodeString(tmpStr); + end + else + U:=U+UnicodeString(sarr[i]); + end; + + DestS:=''; + widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(U)),DestS,DestCP,Length(U)); + exit; + end; + destcopy:=nil; lowstart:=low(sarr); if Pointer(DestS)=Pointer(sarr[lowstart]) then @@ -313,6 +356,8 @@ begin for i:=low(sarr) to high(sarr) do inc(NewLen,length(sarr[i])); SetLength(DestS,NewLen); + if (StringCodePage(DestS) <> DestCP) then + SetCodePage(DestS,DestCP,False); { Concat all strings, except the string we already copied in DestS } pc:=Pointer(DestS)+OldDestLen; @@ -525,7 +570,7 @@ end; {$endif ndef FPC_STRTOCHARARRAYPROC} -Function fpc_AnsiStr_Compare(const S1,S2 : AnsiString): SizeInt;[Public,Alias : 'FPC_ANSISTR_COMPARE']; compilerproc; +Function fpc_AnsiStr_Compare(const S1,S2 : RawByteString): SizeInt;[Public,Alias : 'FPC_ANSISTR_COMPARE']; compilerproc; { Compares 2 AnsiStrings; The result is @@ -535,27 +580,58 @@ Function fpc_AnsiStr_Compare(const S1,S2 : AnsiString): SizeInt;[Public,Alias : } Var MaxI,Temp : SizeInt; + cp1,cp2 : TSystemCodePage; + r1,r2 : RawByteString; + u1,u2 : UTF8String; begin if pointer(S1)=pointer(S2) then begin result:=0; exit; end; - Maxi:=Length(S1); - temp:=Length(S2); - If MaxI>Temp then - MaxI:=Temp; - if MaxI>0 then + if (pointer(S1)=nil) then begin - result:=CompareByte(S1[1],S2[1],MaxI); - if result=0 then + result:=-Length(S2); + exit; + end; + if (pointer(S2)=nil) then + begin + result:=Length(S1); + exit; + end; + cp1:=StringCodePage(S1); + cp2:=StringCodePage(S2); + if (cp1=cp2) then + begin + Maxi:=Length(S1); + temp:=Length(S2); + If MaxI>Temp then + MaxI:=Temp; + if MaxI>0 then + begin + result:=CompareByte(S1[1],S2[1],MaxI); + if result=0 then + result:=Length(S1)-Length(S2); + end + else result:=Length(S1)-Length(S2); end else - result:=Length(S1)-Length(S2); + begin + r1:=S1; + if (cp1=$ffff) then + SetCodePage(r1,DefaultSystemCodePage,false); + r2:=S2; + if (cp2=$ffff) then + SetCodePage(r2,DefaultSystemCodePage,false); + //convert them to utf8 then compare + SetCodePage(r1,65001); + SetCodePage(r2,65001); + Result := fpc_AnsiStr_Compare(r1,r2); + end; end; -Function fpc_AnsiStr_Compare_equal(const S1,S2 : AnsiString): SizeInt;[Public,Alias : 'FPC_ANSISTR_COMPARE_EQUAL']; compilerproc; +Function fpc_AnsiStr_Compare_equal(const S1,S2 : RawByteString): SizeInt;[Public,Alias : 'FPC_ANSISTR_COMPARE_EQUAL']; compilerproc; { Compares 2 AnsiStrings for equality/inequality only; The result is @@ -564,18 +640,35 @@ Function fpc_AnsiStr_Compare_equal(const S1,S2 : AnsiString): SizeInt;[Public,Al } Var MaxI,Temp : SizeInt; + cp1,cp2 : TSystemCodePage; + r1,r2 : RawByteString; begin if pointer(S1)=pointer(S2) then begin result:=0; exit; end; - Maxi:=Length(S1); - temp:=Length(S2); - Result := Maxi - temp; - if Result = 0 then - if MaxI>0 then - result:=CompareByte(S1[1],S2[1],MaxI); + cp1:=StringCodePage(S1); + cp2:=StringCodePage(S2); + if (cp1=cp2) then + begin + Maxi:=Length(S1); + temp:=Length(S2); + Result := Maxi - temp; + if Result = 0 then + if MaxI>0 then + result:=CompareByte(S1[1],S2[1],MaxI); + end + else + begin + r1:=S1; + if (cp1=$ffff) then + SetCodePage(r1,DefaultSystemCodePage,false); + r2:=S2; + if (cp2=$ffff) then + SetCodePage(r2,DefaultSystemCodePage,false); + Result:=widestringmanager.CompareTextUnicodeStringProc(UnicodeString(r1),UnicodeString(r2)); + end; end; {$ifdef VER2_4} @@ -600,7 +693,7 @@ begin end; {$endif VER2_4} -Procedure fpc_AnsiStr_SetLength (Var S : RawByteString; l : SizeInt);[Public,Alias : 'FPC_ANSISTR_SETLENGTH']; compilerproc; +Procedure fpc_AnsiStr_SetLength (Var S : RawByteString; l : SizeInt{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING});[Public,Alias : 'FPC_ANSISTR_SETLENGTH']; compilerproc; { Sets The length of string S to L. Makes sure S is unique, and contains enough room. @@ -616,7 +709,11 @@ begin begin GetMem(Pointer(S),AnsiRecLen+L); PAnsiRec(S)^.Ref:=1; +{$ifdef FPC_HAS_CPSTRING} + PAnsiRec(S)^.CodePage:=cp; +{$else} PAnsiRec(S)^.CodePage:=DefaultSystemCodePage; +{$endif FPC_HAS_CPSTRING} PAnsiRec(S)^.ElementSize:=1; inc(Pointer(S),AnsiFirstOff); end @@ -634,6 +731,9 @@ begin begin { Reallocation is needed... } Temp:=Pointer(NewAnsiString(L)); +{$ifdef FPC_HAS_CPSTRING} + PAnsiRec(Pointer(Temp)-AnsiFirstOff)^.CodePage:=cp; +{$endif FPC_HAS_CPSTRING} { also move terminating null } lens:=succ(length(s)); diff --git a/rtl/inc/compproc.inc b/rtl/inc/compproc.inc index 6fbfcef3ff..73e01f5f1b 100644 --- a/rtl/inc/compproc.inc +++ b/rtl/inc/compproc.inc @@ -250,7 +250,7 @@ Procedure fpc_ansistr_incr_ref (S : Pointer); compilerproc; Procedure fpc_AnsiStr_Assign (Var DestS : Pointer;S2 : Pointer); compilerproc; {$ifdef STR_CONCAT_PROCS} Procedure fpc_AnsiStr_Concat (Var DestS : RawByteString;const S1,S2 : RawByteString); compilerproc; -Procedure fpc_AnsiStr_Concat_multi (Var DestS : Ansistring;const sarr:array of Ansistring); compilerproc; +Procedure fpc_AnsiStr_Concat_multi (Var DestS : RawByteString;const sarr:array of RawByteString{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}); compilerproc; {$else STR_CONCAT_PROCS} function fpc_AnsiStr_Concat (const S1,S2 : AnsiString): AnsiString; compilerproc; function fpc_AnsiStr_Concat_multi (const sarr:array of Ansistring): ansistring; compilerproc; @@ -279,8 +279,8 @@ function fpc_ansistr_to_chararray(arraysize: SizeInt; const src: ansistring): fp {$else ndef FPC_STRTOCHARARRAYPROC} procedure fpc_ansistr_to_chararray(out res: array of char; const src: ansistring)compilerproc; {$endif ndef FPC_STRTOCHARARRAYPROC} -Function fpc_AnsiStr_Compare(const S1,S2 : AnsiString): SizeInt; compilerproc; -Function fpc_AnsiStr_Compare_equal(const S1,S2 : AnsiString): SizeInt; compilerproc; +Function fpc_AnsiStr_Compare(const S1,S2 : RawByteString): SizeInt; compilerproc; +Function fpc_AnsiStr_Compare_equal(const S1,S2 : RawByteString): SizeInt; compilerproc; {$ifdef VER2_4} // obsolete but needed for bootstrapping with 2.4 Procedure fpc_AnsiStr_CheckZero(p : pointer); compilerproc; @@ -289,7 +289,7 @@ Procedure fpc_AnsiStr_CheckRange(len,index : SizeInt); compilerproc; Procedure fpc_AnsiStr_CheckRange(p : Pointer; index : SizeInt); compilerproc; {$endif VER2_4} -Procedure fpc_AnsiStr_SetLength (Var S : RawByteString; l : SizeInt); compilerproc; +Procedure fpc_AnsiStr_SetLength (Var S : RawByteString; l : SizeInt{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}); compilerproc; Function fpc_ansistr_Copy (Const S : RawByteString; Index,Size : SizeInt) : AnsiString;compilerproc; {$ifdef EXTRAANSISHORT} Function fpc_AnsiStr_ShortStr_Compare (Var S1 : Pointer; Var S2 : ShortString): SizeInt; compilerproc; diff --git a/rtl/inc/systemh.inc b/rtl/inc/systemh.inc index 99a08917ea..aaf0203d92 100644 --- a/rtl/inc/systemh.inc +++ b/rtl/inc/systemh.inc @@ -892,6 +892,7 @@ function lowercase(const s : ansistring) : ansistring; function StringCodePage(const S : RawByteString): TSystemCodePage; overload; function StringElementSize(const S : RawByteString): Word; overload; function StringRefCount(const S : RawByteString): SizeInt; overload; +procedure SetCodePage(var s : RawByteString; CodePage : TSystemCodePage; Convert : Boolean = True); procedure SetMultiByteConversionCodePage(CodePage: TSystemCodePage); {$endif FPC_HAS_FEATURE_ANSISTRINGS}