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-- As a special exception under Section 7 of GPL version 3, you are granted -- 19-- additional permissions described in the GCC Runtime Library Exception, -- 20-- version 3.1, as published by the Free Software Foundation. -- 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 160with System; 161 162package 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 206end GNAT.Byte_Swapping; 207