|
@@ -214,10 +214,9 @@ Var
|
|
|
S1CP, S2CP, DestCP: TSystemCodePage;
|
|
|
begin
|
|
|
{$ifdef FPC_HAS_CPSTRING}
|
|
|
- if (Pointer(DestS)=nil) then
|
|
|
- DestCP:=cp
|
|
|
- else
|
|
|
- DestCP:=StringCodePage(DestS);
|
|
|
+ DestCP:=cp;
|
|
|
+ if DestCp=CP_NONE then
|
|
|
+ DestCP:=DefaultSystemCodePage;
|
|
|
{$else FPC_HAS_CPSTRING}
|
|
|
DestCP:=StringCodePage(DestS);
|
|
|
{$endif FPC_HAS_CPSTRING}
|
|
@@ -235,6 +234,13 @@ begin
|
|
|
else
|
|
|
S2CP:=StringCodePage(S2);
|
|
|
S2CP:=TranslatePlaceholderCP(S2CP);
|
|
|
+{$ifdef FPC_HAS_CPSTRING}
|
|
|
+ { if the result is rawbytestring and both strings have the same code page,
|
|
|
+ keep that code page }
|
|
|
+ if (cp=CP_NONE) and
|
|
|
+ (S1CP=S2CP) then
|
|
|
+ DestCP:=S1CP;
|
|
|
+{$endif FPC_HAS_CPSTRING}
|
|
|
if (S1CP<>DestCP) or (S2CP<>DestCP) then
|
|
|
begin
|
|
|
ansistr_concat_complex(DestS,S1,S2,DestCP);
|
|
@@ -284,15 +290,17 @@ end;
|
|
|
{$define FPC_HAS_ANSISTR_CONCAT_MULTI}
|
|
|
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;
|
|
|
+ lowstart,
|
|
|
+ nonemptystart,
|
|
|
+ i : Longint;
|
|
|
p,pc : pointer;
|
|
|
Size,NewLen,
|
|
|
OldDestLen : SizeInt;
|
|
|
destcopy : pointer;
|
|
|
- DestCP : TSystemCodePage;
|
|
|
U : UnicodeString;
|
|
|
- sameCP : Boolean;
|
|
|
+ DestCP,
|
|
|
tmpCP : TSystemCodePage;
|
|
|
+ sameCP : Boolean;
|
|
|
begin
|
|
|
if high(sarr)=0 then
|
|
|
begin
|
|
@@ -300,20 +308,26 @@ begin
|
|
|
exit;
|
|
|
end;
|
|
|
{$ifdef FPC_HAS_CPSTRING}
|
|
|
- if (Pointer(DestS)=nil) then
|
|
|
- DestCP:=cp
|
|
|
- else
|
|
|
- DestCP:=StringCodePage(DestS);
|
|
|
+ DestCP:=cp;
|
|
|
+ if DestCp=CP_NONE then
|
|
|
+ DestCP:=DefaultSystemCodePage;
|
|
|
{$else FPC_HAS_CPSTRING}
|
|
|
DestCP:=StringCodePage(DestS);
|
|
|
{$endif FPC_HAS_CPSTRING}
|
|
|
DestCP:=TranslatePlaceholderCP(DestCP);
|
|
|
sameCP:=true;
|
|
|
lowstart:=low(sarr);
|
|
|
- for i:=lowstart to high(sarr) do
|
|
|
+ { skip empty strings }
|
|
|
+ while (lowstart<=high(sarr)) and
|
|
|
+ (sarr[lowstart]='') do
|
|
|
+ inc(lowstart);
|
|
|
+ tmpCP:=TranslatePlaceholderCP(StringCodePage(sarr[lowstart]));
|
|
|
+ for i:=lowstart+1 to high(sarr) do
|
|
|
begin
|
|
|
- tmpCP:=TranslatePlaceholderCP(StringCodePage(sarr[i]));
|
|
|
- if (DestCP<>tmpCp) then
|
|
|
+ { ignore the code page of empty strings, it will always be
|
|
|
+ DefaultSystemCodePage but it doesn't matter for the outcome }
|
|
|
+ if (sarr[i]<>'') and
|
|
|
+ (tmpCP<>TranslatePlaceholderCP(StringCodePage(sarr[i]))) then
|
|
|
begin
|
|
|
sameCP:=false;
|
|
|
break;
|
|
@@ -323,45 +337,52 @@ begin
|
|
|
begin
|
|
|
U:='';
|
|
|
for i:=lowstart to high(sarr) do
|
|
|
- U:=U+UnicodeString(sarr[i]);
|
|
|
+ if sarr[i]<>'' then
|
|
|
+ U:=U+UnicodeString(sarr[i]);
|
|
|
|
|
|
DestS:='';
|
|
|
widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(U)),DestS,DestCP,Length(U));
|
|
|
exit;
|
|
|
end;
|
|
|
-
|
|
|
+{$ifdef FPC_HAS_CPSTRING}
|
|
|
+ { if the result is rawbytestring and all strings have the same code page,
|
|
|
+ keep that code page }
|
|
|
+ if cp=CP_NONE then
|
|
|
+ DestCP:=tmpCP;
|
|
|
+{$endif FPC_HAS_CPSTRING}
|
|
|
destcopy:=nil;
|
|
|
- lowstart:=low(sarr);
|
|
|
- if Pointer(DestS)=Pointer(sarr[lowstart]) then
|
|
|
- inc(lowstart);
|
|
|
+ nonemptystart:=lowstart;
|
|
|
{ Check for another reuse, then we can't use
|
|
|
the append optimization }
|
|
|
- for i:=lowstart to high(sarr) do
|
|
|
+ if DestS<>'' then
|
|
|
begin
|
|
|
- if Pointer(DestS)=Pointer(sarr[i]) then
|
|
|
+ if Pointer(DestS)=Pointer(sarr[lowstart]) then
|
|
|
+ inc(lowstart);
|
|
|
+ for i:=lowstart to high(sarr) do
|
|
|
begin
|
|
|
- { if DestS is used somewhere in the middle of the expression,
|
|
|
- we need to make sure the original string still exists after
|
|
|
- we empty/modify DestS }
|
|
|
- destcopy:=pointer(dests);
|
|
|
- fpc_AnsiStr_Incr_Ref(destcopy);
|
|
|
- lowstart:=low(sarr);
|
|
|
- break;
|
|
|
+ if Pointer(DestS)=Pointer(sarr[i]) then
|
|
|
+ begin
|
|
|
+ { if DestS is used somewhere in the middle of the expression,
|
|
|
+ we need to make sure the original string still exists after
|
|
|
+ we empty/modify DestS }
|
|
|
+ destcopy:=pointer(dests);
|
|
|
+ fpc_AnsiStr_Incr_Ref(destcopy);
|
|
|
+ lowstart:=nonemptystart;
|
|
|
+ break;
|
|
|
+ end;
|
|
|
end;
|
|
|
end;
|
|
|
{ Start with empty DestS if we start with concatting
|
|
|
- the first array element }
|
|
|
- if lowstart=low(sarr) then
|
|
|
+ the first (non-empty) array element }
|
|
|
+ if lowstart=nonemptystart then
|
|
|
DestS:='';
|
|
|
OldDestLen:=length(DestS);
|
|
|
{ Calculate size of the result so we can do
|
|
|
a single call to SetLength() }
|
|
|
NewLen:=0;
|
|
|
- for i:=low(sarr) to high(sarr) do
|
|
|
+ for i:=nonemptystart 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;
|
|
@@ -375,6 +396,8 @@ begin
|
|
|
inc(pc,size);
|
|
|
end;
|
|
|
end;
|
|
|
+ SetCodePage(DestS,tmpCP,False);
|
|
|
+ SetCodePage(DestS,DestCP,True);
|
|
|
fpc_AnsiStr_Decr_Ref(destcopy);
|
|
|
end;
|
|
|
{$endif FPC_HAS_ANSISTR_CONCAT_MULTI}
|