From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,dcfafdc50abb8ce4 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2001-06-06 16:24:29 PST Newsgroups: comp.lang.ada Path: archiver1.google.com!newsfeed.google.com!sn-xit-02!supernews.com!nntp-relay.ihug.net!ihug.co.nz!news-spur1.maxwell.syr.edu!news.maxwell.syr.edu!howland.erols.net!newsfeed.fast.net!uunet!dca.uu.net!ash.uu.net!xyzzy!nntp From: Jeffrey Carter Subject: Re: records containing variable length arrays [long] X-Nntp-Posting-Host: e246420.msc.az.boeing.com Content-Type: text/plain; charset=us-ascii Message-ID: <3B1EB781.11B6923D@boeing.com> Sender: nntp@news.boeing.com (Boeing NNTP News Access) Content-Transfer-Encoding: 7bit Organization: The Boeing Company X-Accept-Language: en References: <3B1E8BB9.42BF95D2@mida.se> Mime-Version: 1.0 Date: Wed, 6 Jun 2001 23:06:41 GMT X-Mailer: Mozilla 4.5 [en]C-CCK-MCD Boeing Kit (WinNT; U) Xref: archiver1.google.com comp.lang.ada:8281 Date: 2001-06-06T23:06:41+00:00 List-Id: Mats Karlssohn wrote: > > I would like to declare a record type containing two (possibly more) > arrays of variable lengths, the length of each array is another element > of the record. I also need to specify an exact representation for the > record since it is a message that I cant change the format of. > > A piece of code to illustrate (please not that this is NOT compilable) > > package Communication is > -- Basic types > type Byte is mod 2**8; > for Byte'size use 8; > > type Word is mod 2**16; > for Word'size use 16; > > -- Variable length buffer > type Buffer is array(Byte range <>) of Byte; > pragma Pack(Buffer); > > -- Declaring the variable length elements is one major headache > -- note that at least Output_Length may legally be 0 > type Message is > record > Magic : Word; > Operation : Word; > Status : Word; > Response_Length : Byte; > Output_Length : Byte; > Response_Data : Buffer(0..(Response_Length - 1)); > Output_Data : Buffer(0..(Output_Length - 1)); > CRC : Word; > end record; The basic concept for what you're trying to do is a discriminated record type: type Bounded_String (Max_Length : Positive) is record Current_Length : Natural := 0; Value : String (1 .. Max_Length) := (others => '*'); end record; > > -- the other big problem is to get the correct representation > for Message use > record > Magic at 0 range 0..15; > Operation at 2 range 0..15; > Status at 4 range 0..15; > Response_Length at 4 range 0.. 7; > Output_Length at 5 range 0.. 7; > Response_Data at 6 range 0..(Response_Length * Byte'size - 1); > Response_Data at (6 + Response_Length) range 0..(Output_Length * Byte'size - 1); > CRC at (6 + Response_Length + Output_Length) range 0..15; > end record; > > end Communication; However, you have additional problems, such as overlaying your lengths, which would be your discriminants, with Status. I presume that you receive your message as a simple Buffer. In that case you might be able to work something along these lines type Message (Response_Length : Byte; Output_Length : Byte) is record Magic : Word; Operation : Word; Response_Data : Buffer (1 .. Response_Length); Output_Data : Buffer (1 .. Output_Length); CRC : Word; end record; I have specified the Buffers starting at one because Ada does not allow an expression containing a discriminant. for Message use record Magic at 0 range 0..15; Operation at 2 range 0..15; Response_Length at 4 range 0.. 7; Output_Length at 5 range 0.. 7; end record; pragma Pack (Message); We will have to ensure that the compiler will lay out the Buffers and CRC properly, but that seems the most likely result. Assume we have Raw_Message : Buffer (0 .. Some_Value); containing the raw received message. Then we can translate it by doing Translate_Message : declare subtype Raw_Buffer is Buffer (Raw_Message'range); subtype This_Message is Message (Response_Length => Raw_Message (4), Output_Length => Raw_Message (5) ); function Translate is new Ada.Unchecked_Conversion (Source => Raw_Buffer, Target => This_Message); Translated : [constant] This_Message := Translate (Raw_Message); begin -- Translate_Message -- Reference Translated here end Translate_Message; Note that if Translated is constant, a good compiler will not copy the contents of Raw_Message to create Translated. Your only issue now is to reconstruct Status from the 2 discriminants. This is reasonably simple and left as an exercise for the reader. -- Jeffrey Carter