diff --git a/rtl/objpas/classes/stringl.inc b/rtl/objpas/classes/stringl.inc index fc5279b327..0f4651fac2 100644 --- a/rtl/objpas/classes/stringl.inc +++ b/rtl/objpas/classes/stringl.inc @@ -610,57 +610,72 @@ end; Class Function TStrings.GetNextLine (Const Value : String; Var S : String; Var P : SizeInt) : Boolean; -Var - PS : PChar; - IP,L : SizeInt; - +var + LengthOfValue: SizeInt; + StartPos, FuturePos: SizeInt; + begin - L:=Length(Value); - S:=''; - Result:=False; - If ((L-P)<0) then - exit; - if ((L-P)=0) and (not (value[P] in [#10,#13])) Then - Begin - s:=value[P]; - inc(P); - Exit(True); - End; - PS:=PChar(Value)+P-1; - IP:=P; - While ((L-P)>=0) and (not (PS^ in [#10,#13])) do + LengthOfValue := Length(Value); + StartPos := P; + if (StartPos <= 0) or (StartPos > LengthOfValue) then // True for LengthOfValue <= 0 begin - P:=P+1; - Inc(PS); + S := ''; + Exit(False); end; - SetLength (S,P-IP); - System.Move (Value[IP],Pointer(S)^,P-IP); - If (P<=L) and (Value[P]=#13) then - Inc(P); - If (P<=L) and (Value[P]=#10) then - Inc(P); // Point to character after #10(#13) - Result:=True; + FuturePos := StartPos; + while (FuturePos <= LengthOfValue) and not (Value[FuturePos] in [#10, #13]) do + Inc(FuturePos); + // If we use S := Copy(Value, StartPos, FuturePos - StartPos); then compiler + // generate TempS := Copy(...); S := TempS to eliminate side effects and + // implicit "try finally" for TempS finalization + // When we use SetString then no TempS, no try finally generated, + // but we must check case when Value and S is same (side effects) + if Pointer(S) = Pointer(Value) then + System.Delete(S, FuturePos, High(FuturePos)) + else + begin + SetString(S, @Value[StartPos], FuturePos - StartPos); + if (FuturePos <= LengthOfValue) and (Value[FuturePos] = #13) then + Inc(FuturePos); + if (FuturePos <= LengthOfValue) and (Value[FuturePos] = #10) then + Inc(FuturePos); + end; + P := FuturePos; + Result := True; end; Function TStrings.GetNextLineBreak (Const Value : String; Var S : String; Var P : SizeInt) : Boolean; -Var - PS,PC,PP : PChar; - +var + StartPos, FuturePos: SizeInt; + begin - S:=''; - Result:=False; - If ((Length(Value)-P)<0) then - exit; - PS:=@Value[P]; - PC:=PS; - PP:=AnsiStrPos(PS,PChar(FLineBreak)); - // Stop on #0. - While (PC^<>#0) and (PC<>PP) do - Inc(PC); - P:=P+(PC-PS)+Length(FLineBreak); - SetString(S,PS,PC-PS); - Result:=True; + StartPos := P; + if (StartPos <= 0) or (StartPos > Length(Value)) then // True for Length <= 0 + begin + S := ''; + Exit(False); + end; + FuturePos := Pos(FLineBreak, Value, StartPos); // Use PosEx in old RTL + // Why we don't use Copy but use SetString read in GetNextLine + if FuturePos = 0 then // No line breaks + begin + FuturePos := Length(Value) + 1; + if Pointer(S) = Pointer(Value) then + // Nothing to do + else + SetString(S, @Value[StartPos], FuturePos - StartPos) + end + else + if Pointer(S) = Pointer(Value) then + System.Delete(S, FuturePos, High(FuturePos)) + else + begin + SetString(S, @Value[StartPos], FuturePos - StartPos); + Inc(FuturePos, Length(FLineBreak)); + end; + P := FuturePos; + Result := True; end; {$IF (SizeOf(Integer) < SizeOf(SizeInt)) }