From 64c27a86a8544dd6e0eb8ef0353afb4180b48c28 Mon Sep 17 00:00:00 2001 From: Frederic Kehrein Date: Mon, 11 Nov 2024 12:15:24 +0100 Subject: [PATCH] * Adding new generic Extract and Swap function to RTL These allow to move data from one variable to another without triggering the copy operation. Extract makes use of the newly introduced move semantic for function results and Swap uses System.Move to not trigger the copy mechanism. --- rtl/objpas/sysutils/sysutilh.inc | 2 ++ rtl/objpas/sysutils/sysutils.inc | 15 ++++++++++++ tests/test/tmoperator13.pp | 40 ++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 tests/test/tmoperator13.pp diff --git a/rtl/objpas/sysutils/sysutilh.inc b/rtl/objpas/sysutils/sysutilh.inc index 6f28c66d98..66a0d91abb 100644 --- a/rtl/objpas/sysutils/sysutilh.inc +++ b/rtl/objpas/sysutils/sysutilh.inc @@ -290,6 +290,8 @@ type generic function IfThen(val:boolean;const iftrue:T; const iffalse:T) :T; inline; overload; generic function Exchange(var target:T; const newvalue:T) :T; inline; +generic function Extract(var from: T) :T;inline;overload; +generic procedure Swap(var lhs,rhs: T);inline;overload; Var OnShowException : Procedure (Msg : ShortString); diff --git a/rtl/objpas/sysutils/sysutils.inc b/rtl/objpas/sysutils/sysutils.inc index dff400bdc4..e95337959c 100644 --- a/rtl/objpas/sysutils/sysutils.inc +++ b/rtl/objpas/sysutils/sysutils.inc @@ -913,6 +913,21 @@ begin target := newvalue; end; +generic function Extract(var from: T) :T; +begin + Finalize(Result); + Move(from,Result,SizeOf(T)); + Initialize(from); +end; + +generic procedure Swap(var lhs,rhs: T); +var + tmp:array[0..sizeof(T)-1] of Byte; +begin + Move(lhs,tmp,sizeof(T)); + Move(rhs,lhs,sizeof(T)); + Move(tmp,rhs,sizeof(T)); +end; Function ArrayOfConstToStrArray(const Args: array of const) : TUTF8StringDynArray; diff --git a/tests/test/tmoperator13.pp b/tests/test/tmoperator13.pp new file mode 100644 index 0000000000..054700261e --- /dev/null +++ b/tests/test/tmoperator13.pp @@ -0,0 +1,40 @@ +{$Mode ObjFpc}{$H+} +{$ModeSwitch AdvancedRecords} + +uses SysUtils; + +type + TMyRec = record + i: Integer; + class operator :=(const rhs: Integer): TMyRec; + class operator Copy(constref src: TMyRec; var dst: TMyRec); + end; + +class operator TMyRec.:=(const rhs: Integer): TMyRec; +begin + Result.i:=rhs; +end; + +var + CopyCount: Integer = 0; +class operator TMyRec.Copy(constref src: TMyRec; var dst: TMyRec); +begin + Inc(CopyCount); + dst.i:=src.i; +end; + +var + r1, r2, r3: TMyRec; +begin + r1 := 42; + r2 := 32; + specialize Swap(r1,r2); + if (r1.i<>32) or (r2.i<>42) then + Halt(1); + r3 := specialize Extract(r1); + if (r3.i<>32) then + Halt(2); + if CopyCount <> 0 then + Halt(3); + WriteLn('Ok'); +end.