comp.lang.ada
 help / color / mirror / Atom feed
* Handling of unfriendly data structures
@ 2002-09-15 13:48 L. Siever
  2002-09-15 20:26 ` tmoran
  2002-09-15 21:54 ` Nick Roberts
  0 siblings, 2 replies; 3+ messages in thread
From: L. Siever @ 2002-09-15 13:48 UTC (permalink / raw)


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;
type part_a is  record
  a_byte                    : U8;
  b_byte                    : U14;
...
many more bits of many differnt types 
...   
  size                      : U8;
end record;

type part_b is  record
  a_byte                    : U8;
  b_byte                    : U8;
...
many more bits of many differnt types
...
  size                      : U8;
end record;

...

type part_y is  record
..


The layout of a block looks like this:
part_a
text string  -- size is stored in part_a
part_b
text string  -- size is stored in part_b
..
..
part_y
text string  -- size is stored in part_y

next block:
part_a



And finaly my question is:

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)





Linda



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Handling of unfriendly data structures
  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
  1 sibling, 0 replies; 3+ messages in thread
From: tmoran @ 2002-09-15 20:26 UTC (permalink / raw)


> What would be the "Ada-way" to implement this, considering that
That depends somewhat on how to will want to access the data after
reading a block.  You seem to have declarations for part_? and
you could declare
  type string_access is access string;
  type block_type is new ada.finalization.limited_controlled with record
    a : part_a;
    a_text : string_access;
    b : part_b;
    b_text : string_access;
    ...
    y : part_y;
    y_text : string_access;
  end record;
  procedure read_a_block(block : out block_type);
private
  procedure finalize(block : in out block_type); -- free allocated ?_text's

If your program wants to access things sequentially, ie, the things in
a_part, then a_text, then the items in b_part, then b_text, etc, then you
might instead want to write a routine that reads a
part_a, doing endianness conversion as needed and returning a part_a to
its caller, and similar routines for part_b etc.  and finally a text
reader that uses its output size to read the right number of characters.
Using Ada.Streams, for instance, you could then write something like:
  part_a'read(stream, a);
  declare
    a_text : string(1 .. a.size);
  begin
    text'read(stream, a_text);
    -- process the part_a and a_text stuff
  end;
  part_b'read(stream, b);
  declare
    b_text : string(1 .. b.size);
  begin
    text'read(stream, b_text);
    -- process the part_b and b_text stuff
  end;
  ...



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Handling of unfriendly data structures
  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
  1 sibling, 0 replies; 3+ messages in thread
From: Nick Roberts @ 2002-09-15 21:54 UTC (permalink / raw)


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




^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2002-09-15 21:54 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox