155714Skris------------------------------------------------------------------------------ 255714Skris-- -- 355714Skris-- GNAT RUN-TIME COMPONENTS -- 455714Skris-- -- 555714Skris-- G N A T . B Y T E _ S W A P P I N G -- 655714Skris-- -- 755714Skris-- S p e c -- 855714Skris-- -- 955714Skris-- Copyright (C) 2006-2012, AdaCore -- 1055714Skris-- -- 1155714Skris-- GNAT is free software; you can redistribute it and/or modify it under -- 1255714Skris-- terms of the GNU General Public License as published by the Free Soft- -- 1355714Skris-- ware Foundation; either version 3, or (at your option) any later ver- -- 1455714Skris-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- 1555714Skris-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- 1655714Skris-- or FITNESS FOR A PARTICULAR PURPOSE. -- 1755714Skris-- -- 1855714Skris-- As a special exception under Section 7 of GPL version 3, you are granted -- 1955714Skris-- additional permissions described in the GCC Runtime Library Exception, -- 2055714Skris-- version 3.1, as published by the Free Software Foundation. -- 2155714Skris-- -- 2255714Skris-- You should have received a copy of the GNU General Public License and -- 2355714Skris-- a copy of the GCC Runtime Library Exception along with this program; -- 2455714Skris-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- 2555714Skris-- <http://www.gnu.org/licenses/>. -- 2655714Skris-- -- 2755714Skris-- GNAT was originally developed by the GNAT team at New York University. -- 2855714Skris-- Extensive contributions were provided by Ada Core Technologies Inc. -- 2955714Skris-- -- 3055714Skris------------------------------------------------------------------------------ 3155714Skris 3255714Skris-- Simple routines for swapping the bytes of 16-, 32-, and 64-bit objects 3355714Skris 3455714Skris-- The generic functions should be instantiated with types that are of a size 3555714Skris-- in bytes corresponding to the name of the generic. For example, a 2-byte 3655714Skris-- integer type would be compatible with Swapped2, 4-byte integer with 3755714Skris-- Swapped4, and so on. Failure to do so will result in a warning when 3855714Skris-- compiling the instantiation; this warning should be heeded. Ignoring this 3955714Skris-- warning can result in unexpected results. 4055714Skris 4155714Skris-- An example of proper usage follows: 4255714Skris 4355714Skris-- declare 4455714Skris-- type Short_Integer is range -32768 .. 32767; 4555714Skris-- for Short_Integer'Size use 16; -- for confirmation 4655714Skris 4755714Skris-- X : Short_Integer := 16#7FFF#; 4855714Skris 4955714Skris-- function Swapped is new Byte_Swapping.Swapped2 (Short_Integer); 5055714Skris 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