Question

I am working on a program that needs to write a gigantic, multilayer array to several smaller buffers. I am looking to do this by using unchecked_conversion to flatten the multilayer array into a single layer array, then slice up the array. To recover it from memory, I want to append the parts back into order and Unchecked_Conversion them back to tohe original state.

The original implementation looks something like this:

-- array of up to 500 (most likely 100 - 200 though)
type Bottom_Level is array(1 .. 500) of Integer;

-- colors type
type Colors is (red, blue, green, purple);
for Colors use (red => 1, blue => 2, green => 3, purple => 4);

-- Middle Level Array
type Middle_Level is array(Colors) of Bottom_Level;

-- shapes type
type Shapes is (square, triangle, circle);
for Shapes use (square => 1, triangle => 2, circle => 3);

-- Top Level Array
type Top_Level is array(Shapes) of Middle_Level;

I would like to flatten it into an array like:

type Monolithic_Array is Array (1 .. 6000) of Integer;

Would Unchecked_Conversion do something of this sort, or would it mangle the original array so that it is unrecoverable? Thanks!

Was it helpful?

Solution

Yeah, since these are statically sized arrays, Unchecked_Conversion would work.

(But it's a rather unusual way to go about this. Had we some idea of what you're actually trying to do, a more apt data structure could perhaps be suggested.)

Another approach is aliasing (warning, not compiled):

TL     : Top_Level;

Buffer : Monolithic_Array;
for Buffer'Address use TL'Address;

So long as you populate your receiving buffer in the same sequence as you transmit the source buffer segments, it should reassemble just fine.

OTHER TIPS

Here's some examples of how to do such conversions; it also iterates through the set of conversion-functions and tests them for correctness. Implementing a Stream_Convert is left as an exercise for the reader. (Translation from programmerese: "I'm too lazy to do it.")

Pragma Ada_2012;

With
Ada.Streams.Stream_IO,
Ada.Text_IO,
Interfaces;

Procedure Test_Arrays is

    Type Byte is new Interfaces.Unsigned_8;

    Type MD is Array (1..3, 1..3) of Byte;
    Type SD is Array (1..MD'Size/MD'Component_Size) of Byte;


    -- INDEX-CALCULATION METHOD
    Function Mod_Convert( Input : SD ) return MD is
        subtype Primary   is Integer range MD'Range(1); --'
        subtype Secondary is Integer range MD'Range(2); --'
    begin
        return Result : MD do
            for Index_1 in Primary loop
                for Index_2 in Secondary loop
                    Result(Index_1, Index_2):= 
                      Input( Integer'Pred(Index_1)*Primary'Last + Index_2 );
                end loop;
            end loop;
        end return;
    end Mod_Convert;

    Function Mod_Convert( Input : MD ) return SD is
        subtype Primary   is Integer range MD'Range(1); --'
        subtype Secondary is Integer range MD'Range(2); --'
    begin
        return Result : SD do
            for Index in Result'Range loop --'
                declare
                    Index_2 : Integer renames Integer'Succ( Integer'Pred(Index) mod Secondary'Last); --'
                    Index_1 : Integer renames Integer'Succ((Index-Index_2) / Primary'Last);
                begin
                   Result(Index) := Input( Index_1, Index_2 );
                end;
            end loop;
        end return;
    end Mod_Convert;


    -- OVERLAY METHOD
    Function Overlay_Convert( Input : MD ) return SD is
        Result : SD with Import, Convention => Ada, Address => Input'Address; --'
    begin
        Return Result;
    end Overlay_Convert;

    Function Overlay_Convert( Input : SD ) return MD is
        Result : MD with Import, Convention => Ada, Address => Input'Address; --'
    begin
        Return Result;
    end Overlay_Convert;


    -- Print out MD-array.
    Procedure Print( Input : MD ) is
        Use Ada.Text_IO;
    begin
        for Index_1 in MD'Range(1) loop --'
            for Index_2 in MD'Range(2) loop --'
                Put( Byte'Image(Input(Index_1, Index_2)) ); --'
            end loop;
            New_Line;
        end loop;
    end Print;


    -- Print out SD-array.
    Procedure Print( Input : SD ) is
        Use Ada.Text_IO;
    begin
        for Item of Input loop
            Put( Byte'Image(Item) ); --'
        end loop;
        New_Line;
    end Print;


    Type Conversins is ( mod_type, overlay );

    type SD_to_MD_Conversion is not null access function(Input : SD) return MD;
    type MD_to_SD_Conversion is not null access function(Input : MD) return SD;

    type Conversion_Record is record
        SD_to_MD : SD_to_MD_Conversion;
        MD_to_SD : MD_to_SD_Conversion;
    end record;

    Conversions_Var : constant Array( Conversins ) of Conversion_Record:=
      ( mod_type => (Mod_Convert'Access, Mod_Convert'Access),
        overlay  => (Overlay_Convert'Access, Overlay_Convert'Access)
      );

    J : Constant SD := ( 9,8,7,6,5,4,3,2,1 );
Begin

    for Conversion : Conversion_Record of Conversions_Var loop
        declare
            J_prime : MD renames Conversion.SD_to_MD( J );
            J_doubleprime : SD renames Conversion.Md_to_SD( J_prime );
        begin
            Print( J );
            Print( J_prime );
            Print( J_doubleprime );
            Ada.Text_IO.New_Line;
            if J_doubleprime = J then
                Ada.Text_IO.put_line( "Conversion is good." );
            else
                Ada.Text_IO.put_line( "WARNING: BAD CONVERSION!" );
            end if;
        end;
    end loop;    

End Test_Arrays;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top