comp.lang.ada
 help / color / mirror / Atom feed
From: Simon Wright <simon@pushface.org>
Subject: Re: AI12-0218: What is the portable representation clause for processing IETF packets on little-endian machines?
Date: Fri, 11 May 2018 08:55:25 +0100
Date: 2018-05-11T08:55:25+01:00	[thread overview]
Message-ID: <lypo22fwya.fsf@pushface.org> (raw)
In-Reply-To: 5c9b9f90-884f-4de7-8663-d39a67949f4f@googlegroups.com

"Dan'l Miller" <optikos@verizon.net> writes:

> Still, standard Ada has no good Ada-esque solution to heterogenous
> endianness at the perimeter of a system, other than writing C-esque
> pointer-arithmetic code with the various unchecked_ constructs (which
> even C programmers don't generally do; they utilize
> conditionally-compiled macros that correctly type-cast
> meticulously*-laid-out structs-of-bitfields onto that packet's header
> or IC register's word.

I've used (effectively) conditionally-compiled sections of code for
this.

From an SNTP implementation: in BE, the first 32 bits of a packet are

   --   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   --  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   --  |LI | VN  |Mode |    Stratum    |     Poll      |   Precision   |
   --  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

and looking just at the top (first) byte, the package spec contains

   type Leap_Indicator is (No_Warning,
                           Last_Minute_Has_61_Seconds,
                           Last_Minute_Has_59_Seconds,
                           Alarm_Condition);

   type Version is range 3 .. 4;

   type Mode is (Reserved,
                 Symmetric_Active,
                 Symmetric_Passive,
                 Client,
                 Server,
                 Broadcast,
                 Reserved_For_NTP_Control_Message,
                 Reserved_For_Private_Use);

   type Status is record
      LI : Leap_Indicator;
      VN : Version;
      M : Mode;
   end record;

in native layout (nowadays I'd be a lot more specific about
sizes). Conversions:

   function To_Stream_Element (S : Status) return Ada.Streams.Stream_Element;

   function To_Status (S : Ada.Streams.Stream_Element) return Status;

In the body,

   Big_Endian : constant Boolean
     := System."=" (System.Default_Bit_Order, System.High_Order_First);

and

   function To_Status (S : Ada.Streams.Stream_Element) return Status is
   begin
      --  these two sections are conditionally compiled (by GNAT,
      --  anyway) because Big_Endian is constant.
      if Big_Endian then
         declare
            --  create a BE type with BE representation
            type Host_Status is record
               LI : Leap_Indicator;
               VN : Version;
               M : Mode;
            end record;
            for Host_Status use record
               LI at 0 range 0 .. 1;
               VN at 0 range 2 .. 4;
               M  at 0 range 5 .. 7;
            end record;
            for Host_Status'Size use 8;
            function Convert
            is new Ada.Unchecked_Conversion (Ada.Streams.Stream_Element,
                                             Host_Status);
            V : constant Host_Status := Convert (S);
         begin
            --  let the compiler convert from BE representation to host
            return (LI => V.LI, VN => V.VN, M => V.M);
         end;
      else
         declare
            --  create an LE type with LE representation
            type Host_Status is record
               LI : Leap_Indicator;
               VN : Version;
               M : Mode;
            end record;
            for Host_Status use record
               LI at 0 range 6 .. 7;
               VN at 0 range 3 .. 5;
               M  at 0 range 0 .. 2;
            end record;
            for Host_Status'Size use 8;
            function Convert
            is new Ada.Unchecked_Conversion (Ada.Streams.Stream_Element,
                                             Host_Status);
            V : constant Host_Status := Convert (S);
         begin
            --  let the compiler convert from LE representation to host
            return (LI => V.LI, VN => V.VN, M => V.M);
         end;
      end if;
   end To_Status;

No denying it's a lot of work. Much easier for 2-, 4-, 8-byte objects:

   type SNTP_Timestamp is delta 2.0 ** (-32) range -2.0 ** 31 .. 2.0 ** 31;
   for SNTP_Timestamp'Size use 64;

   subtype Timestamp_Slice is Ada.Streams.Stream_Element_Array (1 .. 8);

   function To_SNTP_Timestamp (T : Timestamp_Slice) return SNTP_Timestamp is
      function Convert is new Ada.Unchecked_Conversion (Timestamp_Slice,
                                                        SNTP_Timestamp);
   begin
      if Big_Endian then
         return Convert (T);
      else
         return Convert ((1 => T (8),
                          2 => T (7),
                          3 => T (6),
                          4 => T (5),
                          5 => T (4),
                          6 => T (3),
                          7 => T (2),
                          8 => T (1)));
      end if;
   end To_SNTP_Timestamp;


  reply	other threads:[~2018-05-11  7:55 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-10 17:45 AI12-0218: What is the portable representation clause for processing IETF packets on little-endian machines? Dan'l Miller
2018-05-10 19:24 ` Dan'l Miller
2018-05-10 20:32   ` Paul Rubin
2018-05-10 22:24     ` Dan'l Miller
2018-05-10 22:44       ` Niklas Holsti
2018-05-10 23:14         ` Paul Rubin
2018-05-11  2:38         ` Dan'l Miller
2018-05-11  7:55           ` Simon Wright [this message]
2018-05-11 12:11             ` Lucretia
2018-05-11 13:49               ` Simon Wright
2018-05-11 16:11                 ` Jeffrey R. Carter
2018-05-11 16:48                   ` Simon Wright
2018-05-11 19:08                     ` Jeffrey R. Carter
2018-05-11 21:39                       ` Simon Wright
2018-05-11 21:56                         ` Jeffrey R. Carter
2018-05-12  7:08                           ` Simon Wright
2018-05-12  7:53                             ` Jeffrey R. Carter
2018-05-14 22:43                             ` Randy Brukardt
2018-05-11 13:46             ` Simon Wright
2018-05-11 22:12           ` Randy Brukardt
2018-05-12 10:33             ` Björn Lundin
2018-05-12 13:08               ` Simon Wright
2018-05-12 14:21                 ` Björn Lundin
2018-05-10 23:07       ` Paul Rubin
2018-05-11  0:14         ` Dan'l Miller
2018-05-11  0:30           ` Paul Rubin
2018-05-11  0:50             ` Dan'l Miller
2018-05-11  1:34               ` Paul Rubin
2018-05-11  2:11                 ` Dan'l Miller
2018-05-11 22:32                   ` Randy Brukardt
2018-05-11  8:02         ` Simon Wright
2018-05-11 22:14         ` Randy Brukardt
2018-05-10 19:28 ` Simon Wright
2018-05-10 22:40   ` Randy Brukardt
2018-05-10 22:50     ` Dan'l Miller
2018-05-11 22:00       ` Randy Brukardt
2018-05-12  1:15         ` Paul Rubin
2018-05-14 22:54           ` Randy Brukardt
2018-05-15  0:43             ` Paul Rubin
2018-05-15 21:39               ` Randy Brukardt
2018-05-15  0:44             ` Dennis Lee Bieber
2018-05-11  8:09     ` Simon Wright
2018-05-10 19:34 ` Dmitry A. Kazakov
2018-05-10 20:06   ` Dan'l Miller
2018-05-10 22:44     ` Paul Rubin
2018-05-10 22:50     ` Randy Brukardt
2018-05-11  9:40       ` Niklas Holsti
2018-05-11 11:40         ` Dan'l Miller
2018-05-11 20:16           ` Niklas Holsti
2018-05-11  9:40     ` Dmitry A. Kazakov
2018-05-11 14:21 ` AdaMagica
2018-05-26 16:15 ` Dan'l Miller
2018-05-26 19:02   ` AdaMagica
2018-05-26 21:01     ` Dan'l Miller
2018-05-27 14:58       ` AdaMagica
2018-05-27 18:03         ` Simon Wright
2018-05-29 22:17           ` Randy Brukardt
2018-05-30  6:39             ` Simon Wright
2018-05-30  7:25               ` Dmitry A. Kazakov
2018-05-30 15:01                 ` Simon Wright
2018-05-30 15:59                   ` Dan'l Miller
2018-05-30 19:38               ` Randy Brukardt
2018-05-27 18:04         ` Dan'l Miller
replies disabled

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