Recent

Author Topic: Fill a TRecord with data from an array  (Read 571 times)

bobby100

  • Full Member
  • ***
  • Posts: 161
    • Malzilla
Fill a TRecord with data from an array
« on: January 04, 2023, 12:44:54 pm »
Hi,

I have a TRecord with e.g. 100 members, all of them are bytes. I receive data from outside as an array of bytes.
Is there a way to copy the array values to the TRecord members in a loop?

Pseudocode of what I am doing at the moment:
Code: Pascal  [Select][+][-]
  1. type
  2.   MyInternalStorage = record
  3.     Param1: byte;
  4.     Param2: byte
  5.     ...
  6.   end;
  7.  
  8.   MyReceivedData: array[0..99] of byte;
  9.  
  10.  
  11. function CopyArrayToRecord(aPar: MyReceivedData): boolean;
  12. var
  13.   i: integer;
  14. begin
  15.   Result := True;
  16.   try
  17.     for i := low(aPar) to high(aPar) do
  18.       FillByte(MyInternalStorage , SizeOf(byte), aPar[i]);
  19.   except
  20.     on e: Exception do Result := False;
  21.   end;
  22. end;

Is this OK or am I doing a memory corruption of MyInternalStorage record this way?

Second problem would be, would this cast work?
Code: Pascal  [Select][+][-]
  1. MyInternalStorage(MyReceivedData).Param1

Compiler does not complain, but I am not sure if this is OK at all.
https://gitlab.com/bobby100 - my Lazarus components and units
https://sourceforge.net/u/boban_spasic/profile/ - my open source apps

https://malzilla.org/ - remainder at my previous life as a web security expert

korba812

  • Sr. Member
  • ****
  • Posts: 392
Re: Fill a TRecord with data from an array
« Reply #1 on: January 04, 2023, 12:52:03 pm »
Use a record with a variable structure:
Code: Pascal  [Select][+][-]
  1. type
  2.   MyInternalStorage = packed record
  3.     case Bolean of
  4.     False: (MyReceivedData: array[0..99] of byte),
  5.     True: (
  6.       Param1: byte;
  7.       Param2: byte
  8.       ...
  9.     )
  10.   end;
  11.  

bobby100

  • Full Member
  • ***
  • Posts: 161
    • Malzilla
Re: Fill a TRecord with data from an array
« Reply #2 on: January 04, 2023, 01:01:48 pm »
hi Korba812,

does your method maps/assigns MyReceivedData[0] to Param1?

I have 700kb of source code based on that Record. I would not change the structure of that record now.
I would rather do a step-by-step loading (MyInternalStorage.Param1 := MyReceivedData[0] etc) if there is no other solution.
https://gitlab.com/bobby100 - my Lazarus components and units
https://sourceforge.net/u/boban_spasic/profile/ - my open source apps

https://malzilla.org/ - remainder at my previous life as a web security expert

korba812

  • Sr. Member
  • ****
  • Posts: 392
Re: Fill a TRecord with data from an array
« Reply #3 on: January 04, 2023, 01:07:42 pm »
Yes, variable part shares the same memory. See documentation:
https://www.freepascal.org/docs-html/ref/refsu15.html
https://wiki.freepascal.org/Record

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Fill a TRecord with data from an array
« Reply #4 on: January 04, 2023, 10:59:36 pm »
Is this OK or am I doing a memory corruption of MyInternalStorage record this way?

There won't be a memory corruption, but using FillByte as you do you will only overwrite the first field all the time. Considering that fields of type Byte will have no padding between them you can simply do a Move:

Code: Pascal  [Select][+][-]
  1. function CopyArrayToRecord(aPar: MyReceivedData): boolean;
  2. var
  3.   i: integer;
  4. begin
  5.   if SizeOf(MyInternalStorage) < SizeOf(aPar) then
  6.     Exit(False);
  7.   Move(aPar, MyInternalStorage, SizeOf(aPar));
  8.   Result := True;
  9. end;

Second problem would be, would this cast work?
Code: Pascal  [Select][+][-]
  1. MyInternalStorage(MyReceivedData).Param1

Compiler does not complain, but I am not sure if this is OK at all.

Yes, that would be correct as well.

 

TinyPortal © 2005-2018