Преглед изворни кода

Simplify shortstr_concat(_multi).

Rika Ichinose пре 1 година
родитељ
комит
0fe3633044
1 измењених фајлова са 32 додато и 63 уклоњено
  1. 32 63
      rtl/inc/generic.inc

+ 32 - 63
rtl/inc/generic.inc

@@ -849,19 +849,10 @@ begin
         s1l:=high(dests);
       s2l:=high(dests)-s1l;
     end;
-  if @dests=@s1 then
-    fpc_shortstr_shortstr_intern_charmove(s2,1,dests,s1l+1,s2l)
-  else
-    if @dests=@s2 then
-      begin
-        fpc_shortstr_shortstr_intern_charmove(dests,1,dests,s1l+1,s2l);
-        fpc_shortstr_shortstr_intern_charmove(s1,1,dests,1,s1l);
-      end
-  else
-    begin
-      fpc_shortstr_shortstr_intern_charmove(s1,1,dests,1,s1l);
-      fpc_shortstr_shortstr_intern_charmove(s2,1,dests,s1l+1,s2l);
-    end;
+  { Copy s2 first, as in the case of @dests = @s2 it must be copied first and in other cases the order does not matter. }
+  fpc_shortstr_shortstr_intern_charmove(s2,1,dests,s1l+1,s2l);
+  if @dests<>@s1 then
+    fpc_shortstr_shortstr_intern_charmove(s1,1,dests,1,s1l);
   dests[0]:=chr(s1l+s2l);
 end;
 {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
@@ -869,64 +860,42 @@ end;
 {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT_MULTI}
 procedure fpc_shortstr_concat_multi(var dests:shortstring;const sarr:array of pshortstring);compilerproc;
 var
-  s2l : byte;
-  LowStart,i,
-  Len : ObjpasInt;
-  needtemp : boolean;
-  tmpstr  : shortstring;
-  p,pdest  : pshortstring;
+  i,s2l,Len,destpos0 : ObjpasInt;
+  p : pshortstring;
 begin
-  if high(sarr)=0 then
-    begin
-      DestS:='';
-      exit;
-    end;
-  lowstart:=low(sarr);
-  if Pointer(@DestS)=Pointer(sarr[lowstart]) then
-    inc(lowstart);
-  { Check for another reuse, then we can't use
-    the append optimization and need to use a temp }
-  needtemp:=false;
-  for i:=lowstart to high(sarr) do
-    begin
-      if Pointer(@DestS)=Pointer(sarr[i]) then
-        begin
-          needtemp:=true;
-          break;
-        end;
-    end;
-  if needtemp then
-    begin
-      lowstart:=low(sarr);
-      tmpstr:='';
-      pdest:=@tmpstr
-    end
-  else
+  Len:=0;
+  i:=0;
+  while (i<=high(sarr)) do
     begin
-      { Start with empty DestS if we start with concatting
-        the first array element }
-      if lowstart=low(sarr) then
-        DestS:='';
-      pdest:=@DestS;
+      p:=sarr[i];
+      if assigned(p) then
+        inc(Len,length(p^));
+      inc(i);
     end;
-  { Concat all strings, except the string we already
-    copied in DestS }
-  Len:=length(pdest^);
-  for i:=lowstart to high(sarr) do
+  destpos0:=Len;
+  { Copy strings from the last to the first, so that possible occurences of DestS read correct DestS.
+    DestS[0] = length(DestS) must have its original value for a while! }
+  while (destpos0>0) do
     begin
+      dec(i);
       p:=sarr[i];
-      if assigned(p) then
+      if not assigned(p) then
+        continue;
+      s2l:=length(p^);
+      dec(destpos0,s2l);
+      if (destpos0=0) and (p=@dests) then { Skip moving DestS to itself when appending. This destpos0-based form also catches DestS := '' + '' + DestS. }
+        break;
+      if destpos0+s2l>high(dests) then
         begin
-          s2l:=length(p^);
-          if Len+s2l>high(dests) then
-            s2l:=high(dests)-Len;
-          fpc_shortstr_shortstr_intern_charmove(p^,1,pdest^,Len+1,s2l);
-          inc(Len,s2l);
+          if destpos0>=high(dests) then
+            continue;
+          s2l:=high(dests)-destpos0;
         end;
+      fpc_shortstr_shortstr_intern_charmove(p^,1,dests,destpos0+1,s2l);
     end;
-  pdest^[0]:=Chr(Len);
-  if needtemp then
-    DestS:=TmpStr;
+  if Len>high(dests) then
+    Len:=high(dests);
+  dests[0]:=Chr(Len); { Careful, loop above relies on DestS[0] having the original value. }
 end;
 {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT_MULTI}