Только в стандартном стандарте ISO Ada, как пункт «Представление записи» + любая другая языковая функция (и) может быть переносима на процессоры с прямым и прямым порядком байтов? - PullRequest
0 голосов
/ 16 мая 2018

Без использования нестандартного предложения ‡ Scalar_Storage_Order в последних выпусках GNAT, как, скажем, заголовок IPv4 может быть переносимым образом представлен через предложение (я) представления записи в сочетании с любой комбинацией любых других языковых функцийтак, чтобы «один и тот же» код работал как на процессорах с прямым порядком байтов, так и на процессорах с прямым порядком байтов, но передавался по проводам (например, через, скажем, полезную нагрузку кадра Ethernet) в том, что IETF называет сетевым байтовым порядком (то есть IETFпричудливое название для big-endian).В C «тот же» код может использовать макросы препроцессора для выполнения замены байтов на процессорах с прямым порядком байтов, но не должен использоваться на процессорах с прямым порядком байтов, но стандартный Ada не имеет препроцессора.В C ++ «тот же» код может использовать мета-шаблонное программирование (MTP) для выполнения перестановки байтов на процессорах с прямым порядком байтов, но не должен использоваться на процессорах с прямым порядком байтов, но в стандартном Ada отсутствует MTP.

(Кстати, почти такая же проблема возникает в драйвере устройства, когда процессор с прямым порядком байтов взаимодействует с регистром отображения памяти периферийной ИС с прямым порядком байтов или наоборот: процессор с прямым порядком байтов взаимодействует с памятью ИС с прямым порядком байтов.сопоставленный регистр.)

    BytesPerWord : constant := 4;
    BitsPerByte : constant := 8;
    PowerOf2Highest : constant := BytesPerWord*BitsPerByte - 1; -- part #1 of byte-swap
    type Header_IPv4 is record
          Version   : integer range 0 ..    F#16;
          IHL       : integer range 0 ..    F#16;
          TOS       : integer range 0 ..   FF#16;
          Length    : integer range 0 ..   FF#16;
          Ident     : integer range 0 .. FFFF#16;
          Flags     : integer range 0 ..    7#16;
          Frag_Offs : integer range 0 .. 1FFF#16;
    end record;
    type Header_IPv4_Homogenous is new Header_IPv4;
    for Header_IPv4_Homogenous use record  -- Good-to-go for big-endian processors
          Version   at 0*BytesPerWord range  0 ..  3;
          IHL       at 0*BytesPerWord range  4 ..  7;
          TOS       at 0*BytesPerWord range  8 .. 15;
          Length    at 0*BytesPerWord range 16 .. 31;
          Ident     at 1*BytesPerWord range  0 .. 15;
          Flags     at 1*BytesPerWord range 16 .. 18;
          Frag_Offs at 1*BytesPerWord range 19 .. 31;
    end record;
    for Header_IPv4_Homogenous'Alignment use 4;
    for Header_IPv4_Homogenous'Bit_Order use High_Order_First;
    type Header_IPv4_Heterogenous is new Header_IPv4;
    for Header_IPv4_Heterogenous use record  -- Good-to-go??? for little-endian processors?
          Version   at 0*BytesPerWord range PowerOf2Highest-  3 .. PowerOf2Highest-  0; -- p
          IHL       at 0*BytesPerWord range PowerOf2Highest-  7 .. PowerOf2Highest-  4; -- a
          TOS       at 0*BytesPerWord range PowerOf2Highest- 15 .. PowerOf2Highest-  8; -- r
          Length    at 0*BytesPerWord range PowerOf2Highest- 31 .. PowerOf2Highest- 16; -- t
          Ident     at 1*BytesPerWord range PowerOf2Highest- 15 .. PowerOf2Highest-  0; --
          Flags     at 1*BytesPerWord range PowerOf2Highest- 18 .. PowerOf2Highest- 16; -- #
          Frag_Offs at 1*BytesPerWord range PowerOf2Highest- 31 .. PowerOf2Highest- 19; -- 2
    end record;
    for Header_IPv4_Heterogenous'Alignment use 4;
    for Header_IPv4_Heterogenous'Bit_Order use Low_Order_First; -- part #3 of byte-swap

Обратите внимание на то, как «PowerOf2Highest минус» и «инвертирует» битовые идентификаторы с прямым порядком байтов от (от, к) к порядку [визуально, арифметически не реально] (к, от)используются во второй части байт-свопа в качестве грубого эквивалента спада VHDL, который является ключевой частью того, как VHDL решит эту проблему гетерогенной последовательности.(VHDL является родственным языком для Ada83.)

Но теперь, как скрыть, какой член набора {Header_IPv4_Homogenous, Header_IPv4_Heterogenous} был выбран в качестве имени типа Header_IPv4_Portable в app-domain-code?Использовать дочерние пакеты?

‡ Scalar_Storage_Order было предложено в качестве потенциальной функции для следующего издания стандарта ISO Ada, но пока что нет официального спонсора, выступающего за предложение в ISOкомитет по стандартизации, так что предложение по стандартизации может куда-то уйти и умереть на корню.Кроме того, я буду использовать не-GNAT-компилятор Ada, поэтому использование функции, специфичной для GNAT, для меня недоступно.

1 Ответ

0 голосов
/ 30 апреля 2019

Часть решения, описанного выше, была предложена Норманом Коэном в ada-auth.org/ai-files/grab_bag/bitorder.pdf почти 20 лет назад, но здесь и в его документе не хватаетспособ замены правильного предложения представления записи, скажем, через различные дочерние пакеты в различных компиляторах Ada.Как сделать эту условную связь дочернего пакета во всех компиляторах Ada, я сейчас ищу.

Традиционный способ сделать это - использовать несколько файлов, а менеджер проекта предоставит правильныеодин, когда компиляция завершена.

Возможно, есть альтернативный метод, который мы можем использовать;Я думаю, что должно работать следующее, я скомпилировал его, но не тестировал:

Package IPv4 is
  Type Header_IPv4 is private;
  Function Version      ( Object : Header_IPv4 ) return Integer;
  Function IHL          ( Object : Header_IPv4 ) return Integer;
  Function TOS          ( Object : Header_IPv4 ) return Integer;
  Function Length       ( Object : Header_IPv4 ) return Integer;
  Function Ident        ( Object : Header_IPv4 ) return Integer;
  Function Flags        ( Object : Header_IPv4 ) return Integer;
  Function Frag_Offs    ( Object : Header_IPv4 ) return Integer;
  -- If you need to write fields, use:
  --   Procedure Field  ( Object : in out Header_IPv4; Value : Integer );

Private
  Header_Size : Constant := 7 * (4*8); -- 7 Integers of 4-bytes.
  type Base_IPv4 is record
     Version   : integer range 0 ..    16#F#;
     IHL       : integer range 0 ..    16#F#;
     TOS       : integer range 0 ..   16#FF#;
     Length    : integer range 0 ..   16#FF#;
     Ident     : integer range 0 .. 16#FFFF#;
     Flags     : integer range 0 ..    16#7#;
     Frag_Offs : integer range 0 .. 16#1FFF#;
  end record
  with Size => Header_Size, Object_Size => Header_Size;

  type Header_IPv4 is null record
  with Size => Header_Size, Object_Size => Header_Size;
End IPv4;


Package Body IPv4 is
  Package Internal is
     Use System;

     BytesPerWord    : constant := 4;
     BitsPerByte     : constant := 8;
     PowerOf2Highest : constant := BytesPerWord*BitsPerByte - 1; -- part #1 of byte-swap

     type Header_IPv4_Homogenous is new Base_IPv4;
     for Header_IPv4_Homogenous use record  -- Good-to-go for big-endian processors
        Version   at 0*BytesPerWord range  0 ..  3;
        IHL       at 0*BytesPerWord range  4 ..  7;
        TOS       at 0*BytesPerWord range  8 .. 15;
        Length    at 0*BytesPerWord range 16 .. 31;
        Ident     at 1*BytesPerWord range  0 .. 15;
        Flags     at 1*BytesPerWord range 16 .. 18;
        Frag_Offs at 1*BytesPerWord range 19 .. 31;
     end record;
     for Header_IPv4_Homogenous'Alignment use 4;
     for Header_IPv4_Homogenous'Bit_Order use High_Order_First;
     type Header_IPv4_Heterogenous is new Base_IPv4;
     for Header_IPv4_Heterogenous use record  -- Good-to-go??? for little-endian processors?
        Version   at 0*BytesPerWord range PowerOf2Highest-  3 .. PowerOf2Highest-  0; -- p
        IHL       at 0*BytesPerWord range PowerOf2Highest-  7 .. PowerOf2Highest-  4; -- a
        TOS       at 0*BytesPerWord range PowerOf2Highest- 15 .. PowerOf2Highest-  8; -- r
        Length    at 0*BytesPerWord range PowerOf2Highest- 31 .. PowerOf2Highest- 16; -- t
        Ident     at 1*BytesPerWord range PowerOf2Highest- 15 .. PowerOf2Highest-  0; --
        Flags     at 1*BytesPerWord range PowerOf2Highest- 18 .. PowerOf2Highest- 16; -- #
        Frag_Offs at 1*BytesPerWord range PowerOf2Highest- 31 .. PowerOf2Highest- 19; -- 2
     end record;
     for Header_IPv4_Heterogenous'Alignment use 4;
     for Header_IPv4_Heterogenous'Bit_Order use Low_Order_First; -- part #3 of byte-swap

     Function Convert_Heterogenous is new Ada.Unchecked_Conversion(
        Source => Header_IPv4,
        Target => Header_IPv4_Heterogenous
       );
     Function Convert_Homogenous is new Ada.Unchecked_Conversion(
        Source => Header_IPv4,
        Target => Header_IPv4_Homogenous
       );
     Function Convert_Heterogenous is new Ada.Unchecked_Conversion(
        Source => Header_IPv4_Heterogenous,
        Target => Header_IPv4
       );
     Function Convert_Homogenous is new Ada.Unchecked_Conversion(
        Source => Header_IPv4_Homogenous,
        Target => Header_IPv4
       );

  End Internal;

  Function Convert( Object : Header_IPv4 ) return Base_IPv4 is
     use Internal, System;
  Begin
     if Default_Bit_Order = High_Order_First then
        Return Base_IPv4( Convert_Homogenous(Object) );
     else
        Return Base_IPv4( Convert_Heterogenous(Object) );
     end if;
  End Convert;


  Function Version      ( Object : Header_IPv4 ) return Integer is
     (Convert(Object).Version);
  Function IHL      ( Object : Header_IPv4 ) return Integer is
     (Convert(Object).IHL);
  Function TOS      ( Object : Header_IPv4 ) return Integer is
     (Convert(Object).TOS);
  Function Length       ( Object : Header_IPv4 ) return Integer is
     (Convert(Object).Length);
  Function Ident        ( Object : Header_IPv4 ) return Integer is
     (Convert(Object).Ident);
  Function Flags        ( Object : Header_IPv4 ) return Integer is
     (Convert(Object).Flags);
  Function Frag_Offs    ( Object : Header_IPv4 ) return Integer is
     (Convert(Object).Frag_Offs);

End IPv4;

Другая альтернатива может быть найдена при использовании атрибутов read / write, хотя эта форма не будетразрешить отображение в памяти переменной с типом IPv4 и ее правильное чтение, этого должно быть достаточно для потоковой обработки и намного проще, чем здесь.

...