comp.lang.ada
 help / color / mirror / Atom feed
* Byte Swapping Constrained Data Types
@ 2003-10-20 16:52 Brian Barker
  2003-10-21  1:00 ` Jeffrey Carter
  0 siblings, 1 reply; 5+ messages in thread
From: Brian Barker @ 2003-10-20 16:52 UTC (permalink / raw)


ObjectAda for Windows 7.2.2 Native
 
This is more of an Ada specific question if someone could help me.
 
I have declared an enumerated type like so:
 
     type Terminal is ( Null_Terminal, Primary, Secondary, Console  );
 
     for Terminal use
         ( Null_Terminal => 0,
           Primary    => 1,
           Secondary  => 2,
           Console      => 3);
 
     for Terminal'Size use 32;
 
 
I also have created a procedure based off of a generic byte-swap
routine:
 
     procedure Swap is new Endian.Generic_Swap(Terminal);
 
I receive a record over TCP/IP and it is in Big Endian format, so I
must byte swap it.  I have already copied the raw network data into my
structure that contains the Terminal type.  When I try to byte swap it
I receive a constraint error, because the big endian value of Terminal
is out of range.
 
     Swap(My_Record.Sending_Terminal); -- <- Sending_Terminal is of
type Terminal
 
I want to keep the generic swap, because I have so many abstract data
types.  I just want to get around this constraint range check when I
try to pass the value into the swap routine.  Does anyone have a
better suggestion?



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

* RE: Byte Swapping Constrained Data Types
@ 2003-10-20 18:25 Beard, Frank Randolph CIV
  2003-10-20 19:21 ` Brian Barker
  0 siblings, 1 reply; 5+ messages in thread
From: Beard, Frank Randolph CIV @ 2003-10-20 18:25 UTC (permalink / raw)
  To: Brian Barker, comp.lang.ada

As soon as you reference the Terminal variable, range checking
occurs.  You are going to have to swap the bytes before you
reference it.

For instance:

procedure Some_Routine is

   type Intermediate_Type is mod 2**32;

   procedure Swap is new Endian.Generic_Swap(Intermediate_Type);

   function To_Terminal is
      Ada.Unchecked_Conversion(Intermediate_Type, Terminal);

begin

   --+ Copying your raw network data into the intermediate.

   --+ Swap.
   Swap(My_Intermediate);

   --+ Convert it.
   My_Terminal := To_Terminal(My_Intermediate);


We had a case similar to yours but we used a rep clause instead.
Ours about 72 bits of data into a record structure.  We used
the rep clause to lay it out from the data stream.  The Swap
is more flexible, because we had different rep clauses depending
on what system we were running.

Frank


-----Original Message-----
From: Brian Barker [mailto:bbarker@ball.com]
Sent: Monday, October 20, 2003 12:52
To: comp.lang.ada@ada-france.org
Subject: Byte Swapping Constrained Data Types


ObjectAda for Windows 7.2.2 Native
 
This is more of an Ada specific question if someone could help me.
 
I have declared an enumerated type like so:
 
     type Terminal is ( Null_Terminal, Primary, Secondary, Console  );
 
     for Terminal use
         ( Null_Terminal => 0,
           Primary    => 1,
           Secondary  => 2,
           Console      => 3);
 
     for Terminal'Size use 32;
 
 
I also have created a procedure based off of a generic byte-swap
routine:
 
     procedure Swap is new Endian.Generic_Swap(Terminal);
 
I receive a record over TCP/IP and it is in Big Endian format, so I
must byte swap it.  I have already copied the raw network data into my
structure that contains the Terminal type.  When I try to byte swap it
I receive a constraint error, because the big endian value of Terminal
is out of range.
 
     Swap(My_Record.Sending_Terminal); -- <- Sending_Terminal is of
type Terminal
 
I want to keep the generic swap, because I have so many abstract data
types.  I just want to get around this constraint range check when I
try to pass the value into the swap routine.  Does anyone have a
better suggestion?
_______________________________________________
comp.lang.ada mailing list
comp.lang.ada@ada-france.org
http://www.ada-france.org/mailman/listinfo/comp.lang.ada



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

* Re: Byte Swapping Constrained Data Types
  2003-10-20 18:25 Beard, Frank Randolph CIV
@ 2003-10-20 19:21 ` Brian Barker
  0 siblings, 0 replies; 5+ messages in thread
From: Brian Barker @ 2003-10-20 19:21 UTC (permalink / raw)


Since I couldn't use the generic function to swap my original type
(Terminal).  I created some other swap functions called swap_2, swap_4,
swap_8.  They each take in a system.address as the only argument.  So now I
have,

Swap_4(My_Record.Sending_Terminal'ADDRESS); -- <- Sending_Terminal is of
type Terminal

This works, but I don't like it because I could accidently call Swap_4 on a
16 bit value and cause problems.

I've tried to avoid Unchecked_Conversion in the past, but it looks to
provide a safer solution to the problem.

Is Unchecked_Conversion an expensive operation? I will be converting a good
bit of data over a periodic rate.

Also, will the compiler generate an error on the following line if the size
of Terminal changes (say from 32 bits down to 16), but not
Intermediate_Type?

   function To_Terminal is
      Ada.Unchecked_Conversion(Intermediate_Type, Terminal);

Brian

-- 


----------------------------------------------------
This mailbox protected from junk email by Matador
from MailFrontier, Inc. http://info.mailfrontier.com

"Beard, Frank Randolph CIV" <frank.beard@navy.mil> wrote in message
news:mailman.123.1066674379.25614.comp.lang.ada@ada-france.org...
As soon as you reference the Terminal variable, range checking
occurs.  You are going to have to swap the bytes before you
reference it.

For instance:

procedure Some_Routine is

   type Intermediate_Type is mod 2**32;

   procedure Swap is new Endian.Generic_Swap(Intermediate_Type);

   function To_Terminal is
      Ada.Unchecked_Conversion(Intermediate_Type, Terminal);

begin

   --+ Copying your raw network data into the intermediate.

   --+ Swap.
   Swap(My_Intermediate);

   --+ Convert it.
   My_Terminal := To_Terminal(My_Intermediate);


We had a case similar to yours but we used a rep clause instead.
Ours about 72 bits of data into a record structure.  We used
the rep clause to lay it out from the data stream.  The Swap
is more flexible, because we had different rep clauses depending
on what system we were running.

Frank


-----Original Message-----
From: Brian Barker [mailto:bbarker@ball.com]
Sent: Monday, October 20, 2003 12:52
To: comp.lang.ada@ada-france.org
Subject: Byte Swapping Constrained Data Types


ObjectAda for Windows 7.2.2 Native

This is more of an Ada specific question if someone could help me.

I have declared an enumerated type like so:

     type Terminal is ( Null_Terminal, Primary, Secondary, Console  );

     for Terminal use
         ( Null_Terminal => 0,
           Primary    => 1,
           Secondary  => 2,
           Console      => 3);

     for Terminal'Size use 32;


I also have created a procedure based off of a generic byte-swap
routine:

     procedure Swap is new Endian.Generic_Swap(Terminal);

I receive a record over TCP/IP and it is in Big Endian format, so I
must byte swap it.  I have already copied the raw network data into my
structure that contains the Terminal type.  When I try to byte swap it
I receive a constraint error, because the big endian value of Terminal
is out of range.

     Swap(My_Record.Sending_Terminal); -- <- Sending_Terminal is of
type Terminal

I want to keep the generic swap, because I have so many abstract data
types.  I just want to get around this constraint range check when I
try to pass the value into the swap routine.  Does anyone have a
better suggestion?
_______________________________________________
comp.lang.ada mailing list
comp.lang.ada@ada-france.org
http://www.ada-france.org/mailman/listinfo/comp.lang.ada





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

* RE: Byte Swapping Constrained Data Types
@ 2003-10-20 21:01 Beard, Frank Randolph CIV
  0 siblings, 0 replies; 5+ messages in thread
From: Beard, Frank Randolph CIV @ 2003-10-20 21:01 UTC (permalink / raw)
  To: comp.lang.ada

-----Original Message-----
From: Brian Barker [mailto:bbarker@ball.com]

> Is Unchecked_Conversion an expensive operation? I will be converting a good
> bit of data over a periodic rate.

Unchecked_Conversion is typically very fast.  We've never had it impact
our performance that we've noticed.  You could create some timing tests
just to check, but I wouldn't worry about it unless you are not meeting
some reasonable performance criteria.

> Also, will the compiler generate an error on the following line if the size
> of Terminal changes (say from 32 bits down to 16), but not
> Intermediate_Type?

The VAX Ada compiler would let you get away with differing sizes for
Unchecked_Conversion.  IIRC, you could convert a smaller size into a
larger size, but not the other way around.

Currently, I can only address the Aonix OA compiler, but that just happens
to be the one you're working with.  I haven't tried it since OA v7.1.2a and
we're currently on OA v7.2.2.  Assuming it still works the same, you will
get a compiler error that tells you they must be the same size.

Someone else would have to tell you about GNAT, if you're interested.

Frank



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

* Re: Byte Swapping Constrained Data Types
  2003-10-20 16:52 Byte Swapping Constrained Data Types Brian Barker
@ 2003-10-21  1:00 ` Jeffrey Carter
  0 siblings, 0 replies; 5+ messages in thread
From: Jeffrey Carter @ 2003-10-21  1:00 UTC (permalink / raw)


Brian Barker wrote:

>      type Terminal is ( Null_Terminal, Primary, Secondary, Console  );
>  
>      for Terminal use
>          ( Null_Terminal => 0,
>            Primary    => 1,
>            Secondary  => 2,
>            Console      => 3);

Get rid of this. It buys you nothing, and may cost you something. Some 
compilers generate extra code for enumeration types with a 
representation clause to deal with the possibility that the codes have 
holes and are used for indexing or for loop counters.

>      for Terminal'Size use 32;
>  
> I also have created a procedure based off of a generic byte-swap
> routine:
>  
>      procedure Swap is new Endian.Generic_Swap(Terminal);
>  
> I receive a record over TCP/IP and it is in Big Endian format, so I
> must byte swap it.  I have already copied the raw network data into my
> structure that contains the Terminal type.  When I try to byte swap it
> I receive a constraint error, because the big endian value of Terminal
> is out of range.

What you're receiving over the network is not of type Terminal. You need 
to receive it into a type that corresponds to all the possible values 
you can receive, and their byte-swapped equivalents (probably 
Unsigned_32), swap that, then unchecked convert it to your Terminal type.

Concerning the "efficiency" of Unchecked_Conversion, why are you 
worrying about a problem you have no evidence even exists? 
Unchecked_Conversion is the correct idiom to use. Use it. Measure the 
result. Only if that reveals efficiency problems directly related to the 
use of Unchecked_Conversion should you worry about.

Unchecked_Conversion usually does nothing. Given

type A is ...;
type B is ...;

pragma Assert (A'Size = B'Size);

function To_B is new Unchecked_Conversion (Target => B, Source => A);

X : A;
Y : B;
...
Y := To_B (X);

The assignment typically simply copies the bits of X into Y. The whole 
point of this being unchecked is that it AVOIDS the checks that the type 
system would usually require.

-- 
Jeff Carter
"Brave Sir Robin ran away."
Monty Python and the Holy Grail
59




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

end of thread, other threads:[~2003-10-21  1:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-10-20 16:52 Byte Swapping Constrained Data Types Brian Barker
2003-10-21  1:00 ` Jeffrey Carter
  -- strict thread matches above, loose matches on Subject: below --
2003-10-20 18:25 Beard, Frank Randolph CIV
2003-10-20 19:21 ` Brian Barker
2003-10-20 21:01 Beard, Frank Randolph CIV

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