Reputation: 726
I have a record made of smaller types, a total of 16 bits in size.
type Type_1 is (val1, val2, val3, val4, val5, val6, val7, val8);
for Type_1 use (val1 => 0, val2 = 1, val3 = 2, val4 => 3
val5 => 4, val6 => 5, val7 => 6, val8 => 7);
for Type_1'Size use 3;
type Type_2 is (val1, val2);
for Type_2 use (val1 => 0, val2 = 1);
for Type_2'Size use 1;
etc, etc
type The_Record is record
element_1 : Type_1;
element_2 : Type_2;
element_3 : Type_3;
element_4 : Type_4;
end record;
for the_Record use record
element_1 at 0 range 0 .. 2;
element_2 at 0 range 3 .. 4;
element_3 at 0 range 5 .. 12;
element_4 at 0 range 13 .. 15;
end record;
for The_Record'Size use 16;
How can I flatten 'The_Record' into an array of bytes or something similar?
Thank you!
Upvotes: 2
Views: 4230
Reputation:
This in an example of how to use the Unchecked Conversion
way:
with Ada.Unchecked_Conversion;
with Ada.Text_Io;
procedure Uc is
type The_Record is record
A : Integer;
B : Integer;
end record;
-- define a byte sized thing...
type U8 is mod 2**8;
for U8'Size use 8;
-- have your array defined according to
-- the size of the record it needs to hold
type U8_Record_Array is array (1 .. The_Record'Size / U8'Size) of U8;
-- instantiate Unchecked_Conversion
function To_Array is new Ada.Unchecked_Conversion (Source => The_Record,
Target => U8_Record_Array);
-- Declare a record and convert it to an array
R : constant The_Record := (A => 1, B => 2);
A : constant U8_Record_Array := To_Array (R);
begin
-- Print the Array As Bytes
for I in A'Range loop
Ada.Text_Io.Put (U8'Image (A(I)));
end loop;
end Uc;
Depending on Exactly what you are intending to do, Both the Overlay & Unchecked Conversion
ways will have pros & cons associated with them :)
Upvotes: 4
Reputation: 4198
You can always use Unchecked_conversion
, however, this approach is unchecked and you are therefore telling the compiler (a) that you know what you're doing, and (b) that it cannot help you [otherwise it would be named checked_conversion].
Another way that you can do the conversion is with overlaying, this is my preferred approach (if it is not a simple type-renaming issue) as if things change then the conversion-function can be modified as needed.
-- Subtype-renaming.
Subtype Byte is Interfaces.Unsigned_8;
-- General type for conversion to a collection of bytes.
Type Byte_Array is Array (Positive Range <>) of Byte;
-- Speciffic collection of bytes from The_Record.
Subtype Record_Bytes is Byte_Array(1..The_Record'Size/Byte'Size);
-- Converting record to bytes...
Function Convert( Input : The_Record ) return Record_Bytes is
Result : Constant Record_Bytes;
For Result'Address use Input'Address;
Pragma Import( Convention => Ada, Entity => Result );
begin
Return Result;
end Convert;
-- Converting bytes to record... in Ada 2012!
Function Convert( Input : Record_Bytes ) return The_Record is
Result : The_Record with
Import, Convention => Ada, Address => Input'Address;
begin
Return Result;
end Convert;
Another, and probably better, way (if you are trying for serialization. as I suspect) of doing this would be to create read/write functions and override the default 'read
and 'write
attributes.
Upvotes: 4