File : g-bytswa.ads


   1 ------------------------------------------------------------------------------
   2 --                                                                          --
   3 --                         GNAT RUN-TIME COMPONENTS                         --
   4 --                                                                          --
   5 --                    G N A T . B Y T E _ S W A P P I N G                   --
   6 --                                                                          --
   7 --                                 S p e c                                  --
   8 --                                                                          --
   9 --                     Copyright (C) 2006-2012, AdaCore                     --
  10 --                                                                          --
  11 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  12 -- terms of the  GNU General Public License as published  by the Free Soft- --
  13 -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
  14 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  15 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  16 -- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
  17 --                                                                          --
  18 --                                                                          --
  19 --                                                                          --
  20 --                                                                          --
  21 --                                                                          --
  22 -- You should have received a copy of the GNU General Public License and    --
  23 -- a copy of the GCC Runtime Library Exception along with this program;     --
  24 -- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
  25 -- <http://www.gnu.org/licenses/>.                                          --
  26 --                                                                          --
  27 -- GNAT was originally developed  by the GNAT team at  New York University. --
  28 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
  29 --                                                                          --
  30 ------------------------------------------------------------------------------
  31 
  32 --  Simple routines for swapping the bytes of 16-, 32-, and 64-bit objects
  33 
  34 --  The generic functions should be instantiated with types that are of a size
  35 --  in bytes corresponding to the name of the generic. For example, a 2-byte
  36 --  integer type would be compatible with Swapped2, 4-byte integer with
  37 --  Swapped4, and so on. Failure to do so will result in a warning when
  38 --  compiling the instantiation; this warning should be heeded. Ignoring this
  39 --  warning can result in unexpected results.
  40 
  41 --  An example of proper usage follows:
  42 
  43 --     declare
  44 --        type Short_Integer is range -32768 .. 32767;
  45 --        for Short_Integer'Size use 16; -- for confirmation
  46 
  47 --        X : Short_Integer := 16#7FFF#;
  48 
  49 --        function Swapped is new Byte_Swapping.Swapped2 (Short_Integer);
  50 
  51 --     begin
  52 --        Put_Line (X'Img);
  53 --        X := Swapped (X);
  54 --        Put_Line (X'Img);
  55 --     end;
  56 
  57 --  Note that the generic actual types need not be scalars, but must be
  58 --  'definite' types. They can, for example, be constrained subtypes of
  59 --  unconstrained array types as long as the size is correct. For instance,
  60 --  a subtype of String with length of 4 would be compatible with the
  61 --  Swapped4 generic:
  62 
  63 --     declare
  64 --        subtype String4 is String (1 .. 4);
  65 --        function Swapped is new Byte_Swapping.Swapped4 (String4);
  66 --        S : String4 := "ABCD";
  67 --        for S'Alignment use 4;
  68 --     begin
  69 --        Put_Line (S);
  70 --        S := Swapped (S);
  71 --        Put_Line (S);
  72 --     end;
  73 
  74 --  Similarly, a constrained array type is also acceptable:
  75 
  76 --     declare
  77 --        type Mask is array (0 .. 15) of Boolean;
  78 --        for Mask'Alignment use 2;
  79 --        for Mask'Component_Size use Boolean'Size;
  80 --        X : Mask := (0 .. 7 => True, others => False);
  81 --        function Swapped is new Byte_Swapping.Swapped2 (Mask);
  82 --     begin
  83 --        ...
  84 --        X := Swapped (X);
  85 --        ...
  86 --     end;
  87 
  88 --  A properly-sized record type will also be acceptable, and so forth
  89 
  90 --  However, as described, a size mismatch must be avoided. In the following we
  91 --  instantiate one of the generics with a type that is too large. The result
  92 --  of the function call is undefined, such that assignment to an object can
  93 --  result in garbage values.
  94 
  95 --     Wrong: declare
  96 --        subtype String16 is String (1 .. 16);
  97 
  98 --        function Swapped is new Byte_Swapping.Swapped8 (String16);
  99 --        --  Instantiation generates a compiler warning about
 100 --        --  mismatched sizes
 101 
 102 --        S : String16;
 103 
 104 --     begin
 105 --        S := "ABCDEFGHDEADBEEF";
 106 --
 107 --        Put_Line (S);
 108 --
 109 --        --  the following assignment results in garbage in S after the
 110 --        --  first 8 bytes
 111 --
 112 --        S := Swapped (S);
 113 --
 114 --        Put_Line (S);
 115 --     end Wrong;
 116 
 117 --  When the size of the type is larger than 8 bytes, the use of the non-
 118 --  generic procedures is an alternative because no function result is
 119 --  involved; manipulation of the object is direct.
 120 
 121 --  The procedures are passed the address of an object to manipulate. They will
 122 --  swap the first N bytes of that object corresponding to the name of the
 123 --  procedure.  For example:
 124 
 125 --     declare
 126 --        S2 : String := "AB";
 127 --        for S2'Alignment use 2;
 128 --        S4 : String := "ABCD";
 129 --        for S4'Alignment use 4;
 130 --        S8 : String := "ABCDEFGH";
 131 --        for S8'Alignment use 8;
 132 
 133 --     begin
 134 --        Swap2 (S2'Address);
 135 --        Put_Line (S2);
 136 
 137 --        Swap4 (S4'Address);
 138 --        Put_Line (S4);
 139 
 140 --        Swap8 (S8'Address);
 141 --        Put_Line (S8);
 142 --     end;
 143 
 144 --  If an object of a type larger than N is passed, the remaining bytes of the
 145 --  object are undisturbed. For example:
 146 
 147 --     declare
 148 --        subtype String16 is String (1 .. 16);
 149 
 150 --        S : String16;
 151 --        for S'Alignment use 8;
 152 
 153 --     begin
 154 --        S  := "ABCDEFGHDEADBEEF";
 155 --        Put_Line (S);
 156 --        Swap8 (S'Address);
 157 --        Put_Line (S);
 158 --     end;
 159 
 160 with System;
 161 
 162 package GNAT.Byte_Swapping is
 163    pragma Pure;
 164 
 165    --  NB: all the routines in this package treat the application objects as
 166    --  unsigned (modular) types of a size in bytes corresponding to the routine
 167    --  name. For example, the generic function Swapped2 manipulates the object
 168    --  passed to the formal parameter Input as a value of an unsigned type that
 169    --  is 2 bytes long. Therefore clients are responsible for the compatibility
 170    --  of application types manipulated by these routines and these modular
 171    --  types, in terms of both size and alignment. This requirement applies to
 172    --  the generic actual type passed to the generic formal type Item in the
 173    --  generic functions, as well as to the type of the object implicitly
 174    --  designated by the address passed to the non-generic procedures. Use of
 175    --  incompatible types can result in implementation- defined effects.
 176 
 177    generic
 178       type Item is limited private;
 179    function Swapped2 (Input : Item) return Item;
 180    --  Return the 2-byte value of Input with the bytes swapped
 181 
 182    generic
 183       type Item is limited private;
 184    function Swapped4 (Input : Item) return Item;
 185    --  Return the 4-byte value of Input with the bytes swapped
 186 
 187    generic
 188       type Item is limited private;
 189    function Swapped8 (Input : Item) return Item;
 190    --  Return the 8-byte value of Input with the bytes swapped
 191 
 192    procedure Swap2 (Location : System.Address);
 193    --  Swap the first 2 bytes of the object starting at the address specified
 194    --  by Location.
 195 
 196    procedure Swap4 (Location : System.Address);
 197    --  Swap the first 4 bytes of the object starting at the address specified
 198    --  by Location.
 199 
 200    procedure Swap8 (Location : System.Address);
 201    --  Swap the first 8 bytes of the object starting at the address specified
 202    --  by Location.
 203 
 204    pragma Inline (Swap2, Swap4, Swap8, Swapped2, Swapped4, Swapped8);
 205 
 206 end GNAT.Byte_Swapping;