comp.lang.ada
 help / color / mirror / Atom feed
From: nickroberts@blueyonder.co.uk (Nick Roberts)
Subject: Re: Handling of unfriendly data structures
Date: Sun, 15 Sep 2002 21:54:10 GMT
Date: 2002-09-15T21:54:10+00:00	[thread overview]
Message-ID: <3d84f5a7.1271030355@news.cis.dfn.de> (raw)
In-Reply-To: cfbd115b.0209150548.75f52e4a@posting.google.com

On 15 Sep 2002 06:48:54 -0700, lsiever6619@yahoo.com (L. Siever) strongly
typed:

>Hello,
>I'm getting a block of binary data from a proprietary communication
>channel. I've successfully read the data in an array of U8 :)
>
>Now I've to interpret the data.
>The problem is that the block has a rather unfriendly data structure.
>   
>type U8  is mod 2 ** 8;

>type U8  is mod 2 ** 14;
[Presumably intended to be:]
>type U14 is mod 2 ** 14;

>type part_a is  record
>  a_byte                    : U8;
>  b_byte                    : U14;
>...
>What would be the "Ada-way" to implement this, considering that
>the code should run on little- and big-endian with 32 and 64 bit
>plattforms.
>  
>My idea is to copy&convert somehow the data into the records.
>Since I've alot of differnt records, I wonder if any OO aproaches
>would be possible and efficient? (I'm new to OOP)

Yes an object-oriented approach may well be highly suitable (and
efficient). The Ada Way to deal with the above problem is very likely to be
something like the following.

Declare a tagged, possibly abstract, base type upon which to 'hang' the
different record types for the different variations of data item you are
receiving. E.g.:

package MyTalk_IO is

   type General_Packet is abstract tagged private;

   procedure Process (Packet: in out General_Packet) is abstract;

...

   type Protocol_Negotiation_Packet is new General_Packet with
      record
         ...
      end record;

...

Now, Ada defines two special 'stream I/O' procedures for each subtype T:
T'Read and T'Write. It provides default implementations (which are based on
the base type of T, not what we want), but these can be overridden by your
own implementations if you wish. So:

   procedure Read_PNC (Stream: access Ada.Streams.Root_Stream_Type'Class;
                       Item:   out    Protocol_Negotiation_Packet) is

      Buffer: Ada.Streams.Stream_Element_Array(0..?);

   begin
		-- read elements and unravel bits into relevant parts of Item      
   end;

   for Protocol_Negotiation_Packet'Read use Read_PNC;

You do the same (in reverse) for Write. Strong hint: don't assume a stream
element is a byte. Either test that it is, or use Ada.Stream_Element'Size
in all your code.

The communications paths (in and out) will need wrappers to make them into
streams.

You will probably need to write a special procedure that is capable of
distinguishing which type of packet has been sent (if it cannot do this in
advance, it will have to read the packet into a stream element buffer, and
then make the buffer available to the other Read procedures as a stream),
so that it can be used to read a General_Packet'Class object (either
directly, in which it may need to be a function, or indirectly via an
access value). Suppose it's a function called Input:

   function Input (Stream: access Ada.Streams.Root_Stream_Type'Class)
         return General_Packet'Class;

You will then have a main loop that goes something like:

   loop
      Process(Input(Comm_Stream_In));
      exit when Stop_Flag;
   end loop;

The Process procedure is dynamically (polymorphically) selected according
to the type of packet returned by Input on each iteration of the loop.
(This is the essence of an object-oriented solution.)

If you are careful in writing the Read and Write routines, you can make
your code portable across different architectures. Sometimes an easier
approach is to 'factor' these off (e.g. into separate bodies) and write a
different implementation for each different architecture (if you do this,
ensure your code tests that the implementation architecture matches the
compiler's target).

Look in the Ada reference manual for details about streams and stream I/O,
as well as representation clauses. (But beware, on a portability note, that
different compilers have different levels of support for representation.)
Look in books on the subject, if you can get your hands on any.

Finally, if you have further (more detailed) questions, ask away in this
place.

Hope This Helps.

-- 
Nick Roberts
Per Ardua ad Disastra




      parent reply	other threads:[~2002-09-15 21:54 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-09-15 13:48 Handling of unfriendly data structures L. Siever
2002-09-15 20:26 ` tmoran
2002-09-15 21:54 ` Nick Roberts [this message]
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox