Reputation: 455
I am having problem with the logic. I have no idea how to copy record to another record in Delphi.
TypeA = record
value1 : word;
value2 : word;
value3 : word;
end;
TypeB = record
b1 : byte;
b2 : byte;
end;
I have my two records TypeA and TypeB. For example, I found out that data in TypeA record is belong to TypeB records. Note: TypeA has longer Data Length.
Question: How do i copy TypeA memory and place it in TypeB record?
CopyMemory(@TypeA, @TypeB, Length(TypeB))
When i tried CopyMemory and got an error (Incompaible types).
PS: I don't want to copy or assign it like below.
TypeB.b1 := TypeA.value1 && $FF;
TypeA and TypeB are just example records. Most of thecases, record TypeA and TypeB may contain multple records and it will be harder to allocate form TypeA and assign to TypeB record.
Thanks in advance
----Addition question:
Is there a way to copy Delphi record to Byte array and how? If there is,
Will this logic work?
Upvotes: 4
Views: 17290
Reputation: 13590
All the other answers are variations of copying memory directly, but I think that is the wrong approach. It's low-level and you're using a high-level language, it's easy to make mistakes, and it is risky if your records contain managed data types.
If you're trying to get the first two bytes of one element of a record, try using a variant record (in C, a union.) It is a section of a record that can be addressed several ways, and here you want to address it either as a word or series of bytes.
Try something like this (untested, just typed in the SO editor):
type
TTwoBytes : packed record
ByteA, ByteB : Byte;
end;
TValueRecord : packed record:
case Boolean of
True: (Value: SmallInt);
False: (ValueBytes : TTwoBytes);
end;
end;
TMyRecord = packed record
Value1, Value2, Value3 : TValueRecord;
end;
Then for code:
var
MyRecord: TMyRecord;
MyBytes: TTwoBytes;
begin
MyRecord := ...; // Fill it with data here
// Access the words / smallints by something like: MyRecord.Value1.Value
MyBytes := MyRecord.ValueBytes; // The key bit: type safe assignment
// Do something with MyBytes.ByteA or MyBytes.ByteB
end;
What does this give you that's better than directly copying memory?
case ... of
' syntax for this is silly, but that's another discussion... :))Some notes:
Word
to SmallInt
since I find Word
confusing - it's not actually the 'word size' of the machine, it's 16 bits.packed record
', the justification for this is... iffy.Upvotes: 3
Reputation: 24907
Variant records:
TypeA = packed record
value1 : word;
value2 : word;
value3 : word;
end;
TypeB = packed record
b1 : byte;
b2 : byte;
end;
TypeAB = packed record
case boolean of
false:(a:TypeA);
true:(b:TypeB);
end;
..
..
var someRec:TypeAB;
anotherRec:TypeAB;
..
..
anotherRec.b:=someRec.b
Upvotes: 5
Reputation: 3234
to copy A record to B record there is a good way - operator overloading; in this case you can simply overload Implicit and Explicit operations and write code likeb := a
:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses System.SysUtils;
type
TTypeA = record
value1 : integer;
value2 : integer;
value3 : integer;
end;
TTypeB = record
b1 : byte;
b2 : byte;
class operator Implicit(value : TTypeA):TTypeB;
end;
class operator TTypeB.Implicit(value: TTypeA): TTypeB;
begin
result.b1 := Hi(value.value1);
result.b2 := Lo(value.value1);
end;
var a : TTypeA;
b : TTypeB;
begin
b := a;
end.
you can use TBytesStream to copy record to byte array:
var a : TTypeA;
bs : TBytesStream;
bArr : TArray<byte>;//array of byte;
begin
bs := TBytesStream.Create();
bs.Write(a, sizeof(a));
bArr := bs.Bytes;
end;
or simply set size of byte array to sizeof(A)
and then copyMemory
Upvotes: 3
Reputation: 507
You can omit CopyMemory() (Windows unit) use by:
type
PTypeA = ^TTypeA;
TTypeA = record
value1 : word;
value2 : word;
value3 : word;
end;
PTypeB = ^TTypeB;
TTypeB = record
b1 : byte;
b2 : byte;
end;
var
A: TTypeA = (value1 : 11; value2 : 22; value3 : 33);
B: TTypeB;
B1: TTypeB;
C: {packed?} array of Byte;
begin
Assert(SizeOf(TTypeA) >= SizeOf(TTypeB));
//...
B:= PTypeB(@A)^;
//...
SetLength(C, SizeOf(A));
// TTypeA record to Byte Array
PTypeA(@C[0])^:= A;
// Byte Array to TTypeB
B1:= PTypeB(@C[0])^
end;
Upvotes: 2
Reputation: 12729
procedure CopyAtoB( const A: TypeA; var B: TypeB);
begin
// Assume A is bigger than B.
Move( A, B, SizeOf( TypeB))
end;
or (with Math unit)
procedure CopyAtoB( const A: TypeA; var B: TypeB);
begin
// No assumptions about A, B sizes.
FillChar( B, SizeOf( B), 0);
Move( A, B, Min( SizeOf( TypeA), SizeOf( TypeB)))
end;
Upvotes: 3
Reputation: 109003
CopyMemory(@a, @b, SizeOf(TypeB))
if a
is of type TypeA
and b
is of type TypeB
.
Upvotes: 8
Reputation: 8261
Use MOVE instead of CopyMemory if you want to simply copy the bytes from one place to another.
And to get the size of a record use SizeOf instead of Length.
Upvotes: 0