------------------------------------------------------------------------------ -- -- -- GNAT RUN-TIME COMPONENTS -- -- -- -- S Y S T E M . S T R E A M _ A T T R I B U T E S . X D R -- -- -- -- B o d y -- -- -- -- Copyright (C) 1996-2024, Free Software Foundation, Inc. -- -- -- -- GARLIC is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- -- ware Foundation; either version 3, or (at your option) any later ver- -- -- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- -- or FITNESS FOR A PARTICULAR PURPOSE. -- -- -- -- As a special exception under Section 7 of GPL version 3, you are granted -- -- additional permissions described in the GCC Runtime Library Exception, -- -- version 3.1, as published by the Free Software Foundation. -- -- -- -- You should have received a copy of the GNU General Public License and -- -- a copy of the GCC Runtime Library Exception along with this program; -- -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- -- . -- -- -- -- GNAT was originally developed by the GNAT team at New York University. -- -- Extensive contributions were provided by Ada Core Technologies Inc. -- -- -- ------------------------------------------------------------------------------ with Ada.IO_Exceptions; with Ada.Streams; use Ada.Streams; with Ada.Unchecked_Conversion; package body System.Stream_Attributes.XDR is pragma Suppress (Range_Check); pragma Suppress (Overflow_Check); use UST; Data_Error : exception renames Ada.IO_Exceptions.End_Error; -- Exception raised if insufficient data read (End_Error is mandated by -- AI95-00132). SU : constant := System.Storage_Unit; -- The code in this body assumes that SU = 8 BB : constant := 2 ** SU; -- Byte base BL : constant := 2 ** SU - 1; -- Byte last BS : constant := 2 ** (SU - 1); -- Byte sign US : constant := Unsigned'Size; -- Unsigned size UB : constant := (US - 1) / SU + 1; -- Unsigned byte UL : constant := 2 ** US - 1; -- Unsigned last subtype SE is Ada.Streams.Stream_Element; subtype SEA is Ada.Streams.Stream_Element_Array; subtype SEO is Ada.Streams.Stream_Element_Offset; type Field_Type is record E_Size : Integer; -- Exponent bit size E_Bias : Integer; -- Exponent bias F_Size : Integer; -- Fraction bit size E_Last : Integer; -- Max exponent value F_Mask : SE; -- Mask to apply on first fraction byte E_Bytes : SEO; -- N. of exponent bytes completely used F_Bytes : SEO; -- N. of fraction bytes completely used F_Bits : Integer; -- N. of bits used on first fraction word end record; type Precision is (Single, Double, Quadruple); Fields : constant array (Precision) of Field_Type := [ -- Single precision (E_Size => 8, E_Bias => 127, F_Size => 23, E_Last => 2 ** 8 - 1, F_Mask => 16#7F#, -- 2 ** 7 - 1, E_Bytes => 2, F_Bytes => 3, F_Bits => 23 mod US), -- Double precision (E_Size => 11, E_Bias => 1023, F_Size => 52, E_Last => 2 ** 11 - 1, F_Mask => 16#0F#, -- 2 ** 4 - 1, E_Bytes => 2, F_Bytes => 7, F_Bits => 52 mod US), -- Quadruple precision (E_Size => 15, E_Bias => 16383, F_Size => 112, E_Last => 2 ** 8 - 1, F_Mask => 16#FF#, -- 2 ** 8 - 1, E_Bytes => 2, F_Bytes => 14, F_Bits => 112 mod US)]; -- The representation of all items requires a multiple of four bytes -- (or 32 bits) of data. The bytes are numbered 0 through n-1. The bytes -- are read or written to some byte stream such that byte m always -- precedes byte m+1. If the n bytes needed to contain the data are not -- a multiple of four, then the n bytes are followed by enough (0 to 3) -- residual zero bytes, r, to make the total byte count a multiple of 4. -- An XDR signed integer is a 32-bit datum that encodes an integer -- in the range [-2147483648,2147483647]. The integer is represented -- in two's complement notation. The most and least significant bytes -- are 0 and 3, respectively. Integers are declared as follows: -- (MSB) (LSB) -- +-------+-------+-------+-------+ -- |byte 0 |byte 1 |byte 2 |byte 3 | -- +-------+-------+-------+-------+ -- <------------32 bits------------> SSI_L : constant := 1; SI_L : constant := 2; I24_L : constant := 3; I_L : constant := 4; LI_L : constant := 8; LLI_L : constant := 8; subtype XDR_S_SSI is SEA (1 .. SSI_L); subtype XDR_S_SI is SEA (1 .. SI_L); subtype XDR_S_I24 is SEA (1 .. I24_L); subtype XDR_S_I is SEA (1 .. I_L); subtype XDR_S_LI is SEA (1 .. LI_L); subtype XDR_S_LLI is SEA (1 .. LLI_L); function Short_Short_Integer_To_XDR_S_SSI is new Ada.Unchecked_Conversion (Short_Short_Integer, XDR_S_SSI); function XDR_S_SSI_To_Short_Short_Integer is new Ada.Unchecked_Conversion (XDR_S_SSI, Short_Short_Integer); function Short_Integer_To_XDR_S_SI is new Ada.Unchecked_Conversion (Short_Integer, XDR_S_SI); function XDR_S_SI_To_Short_Integer is new Ada.Unchecked_Conversion (XDR_S_SI, Short_Integer); function Integer_To_XDR_S_I24 is new Ada.Unchecked_Conversion (Integer_24, XDR_S_I24); function XDR_S_I24_To_Integer is new Ada.Unchecked_Conversion (XDR_S_I24, Integer_24); function Integer_To_XDR_S_I is new Ada.Unchecked_Conversion (Integer, XDR_S_I); function XDR_S_I_To_Integer is new Ada.Unchecked_Conversion (XDR_S_I, Integer); function Long_Long_Integer_To_XDR_S_LI is new Ada.Unchecked_Conversion (Long_Long_Integer, XDR_S_LI); function XDR_S_LI_To_Long_Long_Integer is new Ada.Unchecked_Conversion (XDR_S_LI, Long_Long_Integer); function Long_Long_Integer_To_XDR_S_LLI is new Ada.Unchecked_Conversion (Long_Long_Integer, XDR_S_LLI); function XDR_S_LLI_To_Long_Long_Integer is new Ada.Unchecked_Conversion (XDR_S_LLI, Long_Long_Integer); -- An XDR unsigned integer is a 32-bit datum that encodes a nonnegative -- integer in the range [0,4294967295]. It is represented by an unsigned -- binary number whose most and least significant bytes are 0 and 3, -- respectively. An unsigned integer is declared as follows: -- (MSB) (LSB) -- +-------+-------+-------+-------+ -- |byte 0 |byte 1 |byte 2 |byte 3 | -- +-------+-------+-------+-------+ -- <------------32 bits------------> SSU_L : constant := 1; SU_L : constant := 2; U24_L : constant := 3; U_L : constant := 4; LU_L : constant := 8; LLU_L : constant := 8; subtype XDR_S_SSU is SEA (1 .. SSU_L); subtype XDR_S_SU is SEA (1 .. SU_L); subtype XDR_S_U24 is SEA (1 .. U24_L); subtype XDR_S_U is SEA (1 .. U_L); subtype XDR_S_LU is SEA (1 .. LU_L); subtype XDR_S_LLU is SEA (1 .. LLU_L); type XDR_SSU is mod BB ** SSU_L; type XDR_SU is mod BB ** SU_L; type XDR_U is mod BB ** U_L; type XDR_U24 is mod BB ** U24_L; function Short_Unsigned_To_XDR_S_SU is new Ada.Unchecked_Conversion (Short_Unsigned, XDR_S_SU); function XDR_S_SU_To_Short_Unsigned is new Ada.Unchecked_Conversion (XDR_S_SU, Short_Unsigned); function Unsigned_To_XDR_S_U24 is new Ada.Unchecked_Conversion (Unsigned_24, XDR_S_U24); function XDR_S_U24_To_Unsigned is new Ada.Unchecked_Conversion (XDR_S_U24, Unsigned_24); function Unsigned_To_XDR_S_U is new Ada.Unchecked_Conversion (Unsigned, XDR_S_U); function XDR_S_U_To_Unsigned is new Ada.Unchecked_Conversion (XDR_S_U, Unsigned); function Long_Long_Unsigned_To_XDR_S_LU is new Ada.Unchecked_Conversion (Long_Long_Unsigned, XDR_S_LU); function XDR_S_LU_To_Long_Long_Unsigned is new Ada.Unchecked_Conversion (XDR_S_LU, Long_Long_Unsigned); function Long_Long_Unsigned_To_XDR_S_LLU is new Ada.Unchecked_Conversion (Long_Long_Unsigned, XDR_S_LLU); function XDR_S_LLU_To_Long_Long_Unsigned is new Ada.Unchecked_Conversion (XDR_S_LLU, Long_Long_Unsigned); -- The standard defines the floating-point data type "float" (32 bits -- or 4 bytes). The encoding used is the IEEE standard for normalized -- single-precision floating-point numbers. -- The standard defines the encoding used for the double-precision -- floating-point data type "double" (64 bits or 8 bytes). The encoding -- used is the IEEE standard for normalized double-precision floating-point -- numbers. SF_L : constant := 4; -- Single precision F_L : constant := 4; -- Single precision LF_L : constant := 8; -- Double precision LLF_L : constant := 16; -- Quadruple precision TM_L : constant := 8; subtype XDR_S_TM is SEA (1 .. TM_L); type XDR_TM is mod BB ** TM_L; type XDR_SA is mod 2 ** Standard'Address_Size; function To_XDR_SA is new Ada.Unchecked_Conversion (System.Address, XDR_SA); function To_XDR_SA is new Ada.Unchecked_Conversion (XDR_SA, System.Address); -- Enumerations have the same representation as signed integers. -- Enumerations are handy for describing subsets of the integers. -- Booleans are important enough and occur frequently enough to warrant -- their own explicit type in the standard. Booleans are declared as -- an enumeration, with FALSE = 0 and TRUE = 1. -- The standard defines a string of n (numbered 0 through n-1) ASCII -- bytes to be the number n encoded as an unsigned integer (as described -- above), and followed by the n bytes of the string. Byte m of the string -- always precedes byte m+1 of the string, and byte 0 of the string always -- follows the string's length. If n is not a multiple of four, then the -- n bytes are followed by enough (0 to 3) residual zero bytes, r, to make -- the total byte count a multiple of four. -- To fit with XDR string, do not consider character as an enumeration -- type. C_L : constant := 1; subtype XDR_S_C is SEA (1 .. C_L); -- Consider Wide_Character as an enumeration type WC_L : constant := 4; subtype XDR_S_WC is SEA (1 .. WC_L); type XDR_WC is mod BB ** WC_L; -- Consider Wide_Wide_Character as an enumeration type WWC_L : constant := 8; subtype XDR_S_WWC is SEA (1 .. WWC_L); type XDR_WWC is mod BB ** WWC_L; -- Optimization: if we already have the correct Bit_Order, then some -- computations can be avoided since the source and the target will be -- identical anyway. They will be replaced by direct unchecked -- conversions. Optimize_Integers : constant Boolean := Default_Bit_Order = High_Order_First; ---------- -- I_AD -- ---------- function I_AD (Stream : not null access RST) return Fat_Pointer is FP : Fat_Pointer; begin FP.P1 := I_AS (Stream); FP.P2 := I_AS (Stream); return FP; end I_AD; ---------- -- I_AS -- ---------- function I_AS (Stream : not null access RST) return Thin_Pointer is S : XDR_S_TM; L : SEO; U : XDR_TM := 0; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; else for N in S'Range loop U := U * BB + XDR_TM (S (N)); end loop; return To_XDR_SA (XDR_SA (U)); end if; end I_AS; --------- -- I_B -- --------- function I_B (Stream : not null access RST) return Boolean is begin case I_SSU (Stream) is when 0 => return False; when 1 => return True; when others => raise Data_Error; end case; end I_B; --------- -- I_C -- --------- function I_C (Stream : not null access RST) return Character is S : XDR_S_C; L : SEO; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; else -- Use Ada requirements on Character representation clause return Character'Val (S (1)); end if; end I_C; --------- -- I_F -- --------- function I_F (Stream : not null access RST) return Float is I : constant Precision := Single; E_Size : Integer renames Fields (I).E_Size; E_Bias : Integer renames Fields (I).E_Bias; E_Last : Integer renames Fields (I).E_Last; F_Mask : SE renames Fields (I).F_Mask; E_Bytes : SEO renames Fields (I).E_Bytes; F_Bytes : SEO renames Fields (I).F_Bytes; F_Size : Integer renames Fields (I).F_Size; Is_Positive : Boolean; Exponent : Long_Unsigned; Fraction : Long_Unsigned; Result : Float; S : SEA (1 .. F_L); L : SEO; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; end if; -- Extract Fraction, Sign and Exponent Fraction := Long_Unsigned (S (F_L + 1 - F_Bytes) and F_Mask); for N in F_L + 2 - F_Bytes .. F_L loop Fraction := Fraction * BB + Long_Unsigned (S (N)); end loop; Result := Float'Scaling (Float (Fraction), -F_Size); if BS <= S (1) then Is_Positive := False; Exponent := Long_Unsigned (S (1) - BS); else Is_Positive := True; Exponent := Long_Unsigned (S (1)); end if; for N in 2 .. E_Bytes loop Exponent := Exponent * BB + Long_Unsigned (S (N)); end loop; Exponent := Shift_Right (Exponent, Integer (E_Bytes) * SU - E_Size - 1); -- NaN or Infinities if Integer (Exponent) = E_Last then raise Constraint_Error; elsif Exponent = 0 then -- Signed zeros if Fraction = 0 then null; -- Denormalized float else Result := Float'Scaling (Result, 1 - E_Bias); end if; -- Normalized float else Result := Float'Scaling (1.0 + Result, Integer (Exponent) - E_Bias); end if; if not Is_Positive then Result := -Result; end if; return Result; end I_F; --------- -- I_I -- --------- function I_I (Stream : not null access RST) return Integer is S : XDR_S_I; L : SEO; U : XDR_U := 0; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; elsif Optimize_Integers then return XDR_S_I_To_Integer (S); else for N in S'Range loop U := U * BB + XDR_U (S (N)); end loop; -- Test sign and apply two complement notation if S (1) < BL then return Integer (U); else return Integer (-((XDR_U'Last xor U) + 1)); end if; end if; end I_I; ----------- -- I_I24 -- ----------- function I_I24 (Stream : not null access RST) return Integer_24 is S : XDR_S_I24; L : SEO; U : XDR_U24 := 0; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; elsif Optimize_Integers then return XDR_S_I24_To_Integer (S); else for N in S'Range loop U := U * BB + XDR_U24 (S (N)); end loop; -- Test sign and apply two complement notation if S (1) < BL then return Integer_24 (U); else return Integer_24 (-((XDR_U24'Last xor U) + 1)); end if; end if; end I_I24; ---------- -- I_LF -- ---------- function I_LF (Stream : not null access RST) return Long_Float is I : constant Precision := Double; E_Size : Integer renames Fields (I).E_Size; E_Bias : Integer renames Fields (I).E_Bias; E_Last : Integer renames Fields (I).E_Last; F_Mask : SE renames Fields (I).F_Mask; E_Bytes : SEO renames Fields (I).E_Bytes; F_Bytes : SEO renames Fields (I).F_Bytes; F_Size : Integer renames Fields (I).F_Size; Is_Positive : Boolean; Exponent : Long_Unsigned; Fraction : Long_Long_Unsigned; Result : Long_Float; S : SEA (1 .. LF_L); L : SEO; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; end if; -- Extract Fraction, Sign and Exponent Fraction := Long_Long_Unsigned (S (LF_L + 1 - F_Bytes) and F_Mask); for N in LF_L + 2 - F_Bytes .. LF_L loop Fraction := Fraction * BB + Long_Long_Unsigned (S (N)); end loop; Result := Long_Float'Scaling (Long_Float (Fraction), -F_Size); if BS <= S (1) then Is_Positive := False; Exponent := Long_Unsigned (S (1) - BS); else Is_Positive := True; Exponent := Long_Unsigned (S (1)); end if; for N in 2 .. E_Bytes loop Exponent := Exponent * BB + Long_Unsigned (S (N)); end loop; Exponent := Shift_Right (Exponent, Integer (E_Bytes) * SU - E_Size - 1); -- NaN or Infinities if Integer (Exponent) = E_Last then raise Constraint_Error; elsif Exponent = 0 then -- Signed zeros if Fraction = 0 then null; -- Denormalized float else Result := Long_Float'Scaling (Result, 1 - E_Bias); end if; -- Normalized float else Result := Long_Float'Scaling (1.0 + Result, Integer (Exponent) - E_Bias); end if; if not Is_Positive then Result := -Result; end if; return Result; end I_LF; ---------- -- I_LI -- ---------- function I_LI (Stream : not null access RST) return Long_Integer is S : XDR_S_LI; L : SEO; U : Unsigned := 0; X : Long_Unsigned := 0; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; elsif Optimize_Integers then return Long_Integer (XDR_S_LI_To_Long_Long_Integer (S)); else -- Compute using machine unsigned -- rather than long_long_unsigned for N in S'Range loop U := U * BB + Unsigned (S (N)); -- We have filled an unsigned if N mod UB = 0 then X := Shift_Left (X, US) + Long_Unsigned (U); U := 0; end if; end loop; -- Test sign and apply two complement notation if S (1) < BL then return Long_Integer (X); else return Long_Integer (-((Long_Unsigned'Last xor X) + 1)); end if; end if; end I_LI; ----------- -- I_LLF -- ----------- function I_LLF (Stream : not null access RST) return Long_Long_Float is I : constant Precision := Quadruple; E_Size : Integer renames Fields (I).E_Size; E_Bias : Integer renames Fields (I).E_Bias; E_Last : Integer renames Fields (I).E_Last; E_Bytes : SEO renames Fields (I).E_Bytes; F_Bytes : SEO renames Fields (I).F_Bytes; F_Size : Integer renames Fields (I).F_Size; Is_Positive : Boolean; Exponent : Long_Unsigned; Fraction_1 : Long_Long_Unsigned := 0; Fraction_2 : Long_Long_Unsigned := 0; Result : Long_Long_Float; HF : constant Natural := F_Size / 2; S : SEA (1 .. LLF_L); L : SEO; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; end if; -- Extract Fraction, Sign and Exponent for I in LLF_L - F_Bytes + 1 .. LLF_L - 7 loop Fraction_1 := Fraction_1 * BB + Long_Long_Unsigned (S (I)); end loop; for I in SEO (LLF_L - 6) .. SEO (LLF_L) loop Fraction_2 := Fraction_2 * BB + Long_Long_Unsigned (S (I)); end loop; Result := Long_Long_Float'Scaling (Long_Long_Float (Fraction_2), -HF); Result := Long_Long_Float (Fraction_1) + Result; Result := Long_Long_Float'Scaling (Result, HF - F_Size); if BS <= S (1) then Is_Positive := False; Exponent := Long_Unsigned (S (1) - BS); else Is_Positive := True; Exponent := Long_Unsigned (S (1)); end if; for N in 2 .. E_Bytes loop Exponent := Exponent * BB + Long_Unsigned (S (N)); end loop; Exponent := Shift_Right (Exponent, Integer (E_Bytes) * SU - E_Size - 1); -- NaN or Infinities if Integer (Exponent) = E_Last then raise Constraint_Error; elsif Exponent = 0 then -- Signed zeros if Fraction_1 = 0 and then Fraction_2 = 0 then null; -- Denormalized float else Result := Long_Long_Float'Scaling (Result, 1 - E_Bias); end if; -- Normalized float else Result := Long_Long_Float'Scaling (1.0 + Result, Integer (Exponent) - E_Bias); end if; if not Is_Positive then Result := -Result; end if; return Result; end I_LLF; ----------- -- I_LLI -- ----------- function I_LLI (Stream : not null access RST) return Long_Long_Integer is S : XDR_S_LLI; L : SEO; U : Unsigned := 0; X : Long_Long_Unsigned := 0; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; elsif Optimize_Integers then return XDR_S_LLI_To_Long_Long_Integer (S); else -- Compute using machine unsigned for computing -- rather than long_long_unsigned. for N in S'Range loop U := U * BB + Unsigned (S (N)); -- We have filled an unsigned if N mod UB = 0 then X := Shift_Left (X, US) + Long_Long_Unsigned (U); U := 0; end if; end loop; -- Test sign and apply two complement notation if S (1) < BL then return Long_Long_Integer (X); else return Long_Long_Integer (-((Long_Long_Unsigned'Last xor X) + 1)); end if; end if; end I_LLI; ----------- -- I_LLU -- ----------- function I_LLU (Stream : not null access RST) return Long_Long_Unsigned is S : XDR_S_LLU; L : SEO; U : Unsigned := 0; X : Long_Long_Unsigned := 0; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; elsif Optimize_Integers then return XDR_S_LLU_To_Long_Long_Unsigned (S); else -- Compute using machine unsigned -- rather than long_long_unsigned. for N in S'Range loop U := U * BB + Unsigned (S (N)); -- We have filled an unsigned if N mod UB = 0 then X := Shift_Left (X, US) + Long_Long_Unsigned (U); U := 0; end if; end loop; return X; end if; end I_LLU; ---------- -- I_LU -- ---------- function I_LU (Stream : not null access RST) return Long_Unsigned is S : XDR_S_LU; L : SEO; U : Unsigned := 0; X : Long_Unsigned := 0; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; elsif Optimize_Integers then return Long_Unsigned (XDR_S_LU_To_Long_Long_Unsigned (S)); else -- Compute using machine unsigned -- rather than long_unsigned. for N in S'Range loop U := U * BB + Unsigned (S (N)); -- We have filled an unsigned if N mod UB = 0 then X := Shift_Left (X, US) + Long_Unsigned (U); U := 0; end if; end loop; return X; end if; end I_LU; ---------- -- I_SF -- ---------- function I_SF (Stream : not null access RST) return Short_Float is I : constant Precision := Single; E_Size : Integer renames Fields (I).E_Size; E_Bias : Integer renames Fields (I).E_Bias; E_Last : Integer renames Fields (I).E_Last; F_Mask : SE renames Fields (I).F_Mask; E_Bytes : SEO renames Fields (I).E_Bytes; F_Bytes : SEO renames Fields (I).F_Bytes; F_Size : Integer renames Fields (I).F_Size; Exponent : Long_Unsigned; Fraction : Long_Unsigned; Is_Positive : Boolean; Result : Short_Float; S : SEA (1 .. SF_L); L : SEO; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; end if; -- Extract Fraction, Sign and Exponent Fraction := Long_Unsigned (S (SF_L + 1 - F_Bytes) and F_Mask); for N in SF_L + 2 - F_Bytes .. SF_L loop Fraction := Fraction * BB + Long_Unsigned (S (N)); end loop; Result := Short_Float'Scaling (Short_Float (Fraction), -F_Size); if BS <= S (1) then Is_Positive := False; Exponent := Long_Unsigned (S (1) - BS); else Is_Positive := True; Exponent := Long_Unsigned (S (1)); end if; for N in 2 .. E_Bytes loop Exponent := Exponent * BB + Long_Unsigned (S (N)); end loop; Exponent := Shift_Right (Exponent, Integer (E_Bytes) * SU - E_Size - 1); -- NaN or Infinities if Integer (Exponent) = E_Last then raise Constraint_Error; elsif Exponent = 0 then -- Signed zeros if Fraction = 0 then null; -- Denormalized float else Result := Short_Float'Scaling (Result, 1 - E_Bias); end if; -- Normalized float else Result := Short_Float'Scaling (1.0 + Result, Integer (Exponent) - E_Bias); end if; if not Is_Positive then Result := -Result; end if; return Result; end I_SF; ---------- -- I_SI -- ---------- function I_SI (Stream : not null access RST) return Short_Integer is S : XDR_S_SI; L : SEO; U : XDR_SU := 0; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; elsif Optimize_Integers then return XDR_S_SI_To_Short_Integer (S); else for N in S'Range loop U := U * BB + XDR_SU (S (N)); end loop; -- Test sign and apply two complement notation if S (1) < BL then return Short_Integer (U); else return Short_Integer (-((XDR_SU'Last xor U) + 1)); end if; end if; end I_SI; ----------- -- I_SSI -- ----------- function I_SSI (Stream : not null access RST) return Short_Short_Integer is S : XDR_S_SSI; L : SEO; U : XDR_SSU; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; elsif Optimize_Integers then return XDR_S_SSI_To_Short_Short_Integer (S); else U := XDR_SSU (S (1)); -- Test sign and apply two complement notation if S (1) < BL then return Short_Short_Integer (U); else return Short_Short_Integer (-((XDR_SSU'Last xor U) + 1)); end if; end if; end I_SSI; ----------- -- I_SSU -- ----------- function I_SSU (Stream : not null access RST) return Short_Short_Unsigned is S : XDR_S_SSU; L : SEO; U : XDR_SSU := 0; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; else U := XDR_SSU (S (1)); return Short_Short_Unsigned (U); end if; end I_SSU; ---------- -- I_SU -- ---------- function I_SU (Stream : not null access RST) return Short_Unsigned is S : XDR_S_SU; L : SEO; U : XDR_SU := 0; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; elsif Optimize_Integers then return XDR_S_SU_To_Short_Unsigned (S); else for N in S'Range loop U := U * BB + XDR_SU (S (N)); end loop; return Short_Unsigned (U); end if; end I_SU; --------- -- I_U -- --------- function I_U (Stream : not null access RST) return Unsigned is S : XDR_S_U; L : SEO; U : XDR_U := 0; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; elsif Optimize_Integers then return XDR_S_U_To_Unsigned (S); else for N in S'Range loop U := U * BB + XDR_U (S (N)); end loop; return Unsigned (U); end if; end I_U; ----------- -- I_U24 -- ----------- function I_U24 (Stream : not null access RST) return Unsigned_24 is S : XDR_S_U24; L : SEO; U : XDR_U24 := 0; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; elsif Optimize_Integers then return XDR_S_U24_To_Unsigned (S); else for N in S'Range loop U := U * BB + XDR_U24 (S (N)); end loop; return Unsigned_24 (U); end if; end I_U24; ---------- -- I_WC -- ---------- function I_WC (Stream : not null access RST) return Wide_Character is S : XDR_S_WC; L : SEO; U : XDR_WC := 0; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; else for N in S'Range loop U := U * BB + XDR_WC (S (N)); end loop; -- Use Ada requirements on Wide_Character representation clause return Wide_Character'Val (U); end if; end I_WC; ----------- -- I_WWC -- ----------- function I_WWC (Stream : not null access RST) return Wide_Wide_Character is S : XDR_S_WWC; L : SEO; U : XDR_WWC := 0; begin Ada.Streams.Read (Stream.all, S, L); if L /= S'Last then raise Data_Error; else for N in S'Range loop U := U * BB + XDR_WWC (S (N)); end loop; -- Use Ada requirements on Wide_Wide_Character representation clause return Wide_Wide_Character'Val (U); end if; end I_WWC; ---------- -- W_AD -- ---------- procedure W_AD (Stream : not null access RST; Item : Fat_Pointer) is S : XDR_S_TM; U : XDR_TM; begin U := XDR_TM (To_XDR_SA (Item.P1)); for N in reverse S'Range loop S (N) := SE (U mod BB); U := U / BB; end loop; Ada.Streams.Write (Stream.all, S); U := XDR_TM (To_XDR_SA (Item.P2)); for N in reverse S'Range loop S (N) := SE (U mod BB); U := U / BB; end loop; Ada.Streams.Write (Stream.all, S); if U /= 0 then raise Data_Error; end if; end W_AD; ---------- -- W_AS -- ---------- procedure W_AS (Stream : not null access RST; Item : Thin_Pointer) is S : XDR_S_TM; U : XDR_TM := XDR_TM (To_XDR_SA (Item)); begin for N in reverse S'Range loop S (N) := SE (U mod BB); U := U / BB; end loop; Ada.Streams.Write (Stream.all, S); if U /= 0 then raise Data_Error; end if; end W_AS; --------- -- W_B -- --------- procedure W_B (Stream : not null access RST; Item : Boolean) is begin if Item then W_SSU (Stream, 1); else W_SSU (Stream, 0); end if; end W_B; --------- -- W_C -- --------- procedure W_C (Stream : not null access RST; Item : Character) is S : XDR_S_C; pragma Assert (C_L = 1); begin -- Use Ada requirements on Character representation clause S (1) := SE (Character'Pos (Item)); Ada.Streams.Write (Stream.all, S); end W_C; --------- -- W_F -- --------- procedure W_F (Stream : not null access RST; Item : Float) is I : constant Precision := Single; E_Size : Integer renames Fields (I).E_Size; E_Bias : Integer renames Fields (I).E_Bias; E_Bytes : SEO renames Fields (I).E_Bytes; F_Bytes : SEO renames Fields (I).F_Bytes; F_Size : Integer renames Fields (I).F_Size; F_Mask : SE renames Fields (I).F_Mask; Exponent : Long_Unsigned; Fraction : Long_Unsigned; Is_Positive : Boolean; E : Integer; F : Float; S : SEA (1 .. F_L) := [others => 0]; begin if not Item'Valid then raise Constraint_Error; end if; -- Compute Sign Is_Positive := (0.0 <= Item); F := abs (Item); -- Signed zero if F = 0.0 then Exponent := 0; Fraction := 0; else E := Float'Exponent (F) - 1; -- Denormalized float if E <= -E_Bias then F := Float'Scaling (F, F_Size + E_Bias - 1); E := -E_Bias; else F := Float'Scaling (Float'Fraction (F), F_Size + 1); end if; -- Compute Exponent and Fraction Exponent := Long_Unsigned (E + E_Bias); Fraction := Long_Unsigned (F * 2.0) / 2; end if; -- Store Fraction for I in reverse F_L - F_Bytes + 1 .. F_L loop S (I) := SE (Fraction mod BB); Fraction := Fraction / BB; end loop; -- Remove implicit bit S (F_L - F_Bytes + 1) := S (F_L - F_Bytes + 1) and F_Mask; -- Store Exponent (not always at the beginning of a byte) Exponent := Shift_Left (Exponent, Integer (E_Bytes) * SU - E_Size - 1); for N in reverse 1 .. E_Bytes loop S (N) := SE (Exponent mod BB) + S (N); Exponent := Exponent / BB; end loop; -- Store Sign if not Is_Positive then S (1) := S (1) + BS; end if; Ada.Streams.Write (Stream.all, S); end W_F; --------- -- W_I -- --------- procedure W_I (Stream : not null access RST; Item : Integer) is S : XDR_S_I; U : XDR_U; begin if Optimize_Integers then S := Integer_To_XDR_S_I (Item); else -- Test sign and apply two complement notation U := (if Item < 0 then XDR_U'Last xor XDR_U (-(Item + 1)) else XDR_U (Item)); for N in reverse S'Range loop S (N) := SE (U mod BB); U := U / BB; end loop; if U /= 0 then raise Data_Error; end if; end if; Ada.Streams.Write (Stream.all, S); end W_I; ----------- -- W_I24 -- ----------- procedure W_I24 (Stream : not null access RST; Item : Integer_24) is S : XDR_S_I24; U : XDR_U24; begin if Optimize_Integers then S := Integer_To_XDR_S_I24 (Item); else -- Test sign and apply two complement notation U := (if Item < 0 then XDR_U24'Last xor XDR_U24 (-(Item + 1)) else XDR_U24 (Item)); for N in reverse S'Range loop S (N) := SE (U mod BB); U := U / BB; end loop; if U /= 0 then raise Data_Error; end if; end if; Ada.Streams.Write (Stream.all, S); end W_I24; ---------- -- W_LF -- ---------- procedure W_LF (Stream : not null access RST; Item : Long_Float) is I : constant Precision := Double; E_Size : Integer renames Fields (I).E_Size; E_Bias : Integer renames Fields (I).E_Bias; E_Bytes : SEO renames Fields (I).E_Bytes; F_Bytes : SEO renames Fields (I).F_Bytes; F_Size : Integer renames Fields (I).F_Size; F_Mask : SE renames Fields (I).F_Mask; Exponent : Long_Unsigned; Fraction : Long_Long_Unsigned; Is_Positive : Boolean; E : Integer; F : Long_Float; S : SEA (1 .. LF_L) := [others => 0]; begin if not Item'Valid then raise Constraint_Error; end if; -- Compute Sign Is_Positive := (0.0 <= Item); F := abs (Item); -- Signed zero if F = 0.0 then Exponent := 0; Fraction := 0; else E := Long_Float'Exponent (F) - 1; -- Denormalized float if E <= -E_Bias then E := -E_Bias; F := Long_Float'Scaling (F, F_Size + E_Bias - 1); else F := Long_Float'Scaling (F, F_Size - E); end if; -- Compute Exponent and Fraction Exponent := Long_Unsigned (E + E_Bias); Fraction := Long_Long_Unsigned (F * 2.0) / 2; end if; -- Store Fraction for I in reverse LF_L - F_Bytes + 1 .. LF_L loop S (I) := SE (Fraction mod BB); Fraction := Fraction / BB; end loop; -- Remove implicit bit S (LF_L - F_Bytes + 1) := S (LF_L - F_Bytes + 1) and F_Mask; -- Store Exponent (not always at the beginning of a byte) Exponent := Shift_Left (Exponent, Integer (E_Bytes) * SU - E_Size - 1); for N in reverse 1 .. E_Bytes loop S (N) := SE (Exponent mod BB) + S (N); Exponent := Exponent / BB; end loop; -- Store Sign if not Is_Positive then S (1) := S (1) + BS; end if; Ada.Streams.Write (Stream.all, S); end W_LF; ---------- -- W_LI -- ---------- procedure W_LI (Stream : not null access RST; Item : Long_Integer) is S : XDR_S_LI; U : Unsigned := 0; X : Long_Unsigned; begin if Optimize_Integers then S := Long_Long_Integer_To_XDR_S_LI (Long_Long_Integer (Item)); else -- Test sign and apply two complement notation if Item < 0 then X := Long_Unsigned'Last xor Long_Unsigned (-(Item + 1)); else X := Long_Unsigned (Item); end if; -- Compute using machine unsigned rather than long_unsigned for N in reverse S'Range loop -- We have filled an unsigned if (LU_L - N) mod UB = 0 then U := Unsigned (X and UL); X := Shift_Right (X, US); end if; S (N) := SE (U mod BB); U := U / BB; end loop; if U /= 0 then raise Data_Error; end if; end if; Ada.Streams.Write (Stream.all, S); end W_LI; ----------- -- W_LLF -- ----------- procedure W_LLF (Stream : not null access RST; Item : Long_Long_Float) is I : constant Precision := Quadruple; E_Size : Integer renames Fields (I).E_Size; E_Bias : Integer renames Fields (I).E_Bias; E_Bytes : SEO renames Fields (I).E_Bytes; F_Bytes : SEO renames Fields (I).F_Bytes; F_Size : Integer renames Fields (I).F_Size; HFS : constant Integer := F_Size / 2; Exponent : Long_Unsigned; Fraction_1 : Long_Long_Unsigned; Fraction_2 : Long_Long_Unsigned; Is_Positive : Boolean; E : Integer; F : Long_Long_Float := Item; S : SEA (1 .. LLF_L) := [others => 0]; begin if not Item'Valid then raise Constraint_Error; end if; -- Compute Sign Is_Positive := (0.0 <= Item); if F < 0.0 then F := -Item; end if; -- Signed zero if F = 0.0 then Exponent := 0; Fraction_1 := 0; Fraction_2 := 0; else E := Long_Long_Float'Exponent (F) - 1; -- Denormalized float if E <= -E_Bias then F := Long_Long_Float'Scaling (F, E_Bias - 1); E := -E_Bias; else F := Long_Long_Float'Scaling (Long_Long_Float'Fraction (F), 1); end if; -- Compute Exponent and Fraction Exponent := Long_Unsigned (E + E_Bias); F := Long_Long_Float'Scaling (F, F_Size - HFS); Fraction_1 := Long_Long_Unsigned (Long_Long_Float'Floor (F)); F := F - Long_Long_Float (Fraction_1); F := Long_Long_Float'Scaling (F, HFS); Fraction_2 := Long_Long_Unsigned (Long_Long_Float'Floor (F)); end if; -- Store Fraction_1 for I in reverse LLF_L - F_Bytes + 1 .. LLF_L - 7 loop S (I) := SE (Fraction_1 mod BB); Fraction_1 := Fraction_1 / BB; end loop; -- Store Fraction_2 for I in reverse LLF_L - 6 .. LLF_L loop S (SEO (I)) := SE (Fraction_2 mod BB); Fraction_2 := Fraction_2 / BB; end loop; -- Store Exponent (not always at the beginning of a byte) Exponent := Shift_Left (Exponent, Integer (E_Bytes) * SU - E_Size - 1); for N in reverse 1 .. E_Bytes loop S (N) := SE (Exponent mod BB) + S (N); Exponent := Exponent / BB; end loop; -- Store Sign if not Is_Positive then S (1) := S (1) + BS; end if; Ada.Streams.Write (Stream.all, S); end W_LLF; ----------- -- W_LLI -- ----------- procedure W_LLI (Stream : not null access RST; Item : Long_Long_Integer) is S : XDR_S_LLI; U : Unsigned := 0; X : Long_Long_Unsigned; begin if Optimize_Integers then S := Long_Long_Integer_To_XDR_S_LLI (Item); else -- Test sign and apply two complement notation if Item < 0 then X := Long_Long_Unsigned'Last xor Long_Long_Unsigned (-(Item + 1)); else X := Long_Long_Unsigned (Item); end if; -- Compute using machine unsigned rather than long_long_unsigned for N in reverse S'Range loop -- We have filled an unsigned if (LLU_L - N) mod UB = 0 then U := Unsigned (X and UL); X := Shift_Right (X, US); end if; S (N) := SE (U mod BB); U := U / BB; end loop; if U /= 0 then raise Data_Error; end if; end if; Ada.Streams.Write (Stream.all, S); end W_LLI; ----------- -- W_LLU -- ----------- procedure W_LLU (Stream : not null access RST; Item : Long_Long_Unsigned) is S : XDR_S_LLU; U : Unsigned := 0; X : Long_Long_Unsigned := Item; begin if Optimize_Integers then S := Long_Long_Unsigned_To_XDR_S_LLU (Item); else -- Compute using machine unsigned rather than long_long_unsigned for N in reverse S'Range loop -- We have filled an unsigned if (LLU_L - N) mod UB = 0 then U := Unsigned (X and UL); X := Shift_Right (X, US); end if; S (N) := SE (U mod BB); U := U / BB; end loop; if U /= 0 then raise Data_Error; end if; end if; Ada.Streams.Write (Stream.all, S); end W_LLU; ---------- -- W_LU -- ---------- procedure W_LU (Stream : not null access RST; Item : Long_Unsigned) is S : XDR_S_LU; U : Unsigned := 0; X : Long_Unsigned := Item; begin if Optimize_Integers then S := Long_Long_Unsigned_To_XDR_S_LU (Long_Long_Unsigned (Item)); else -- Compute using machine unsigned rather than long_unsigned for N in reverse S'Range loop -- We have filled an unsigned if (LU_L - N) mod UB = 0 then U := Unsigned (X and UL); X := Shift_Right (X, US); end if; S (N) := SE (U mod BB); U := U / BB; end loop; if U /= 0 then raise Data_Error; end if; end if; Ada.Streams.Write (Stream.all, S); end W_LU; ---------- -- W_SF -- ---------- procedure W_SF (Stream : not null access RST; Item : Short_Float) is I : constant Precision := Single; E_Size : Integer renames Fields (I).E_Size; E_Bias : Integer renames Fields (I).E_Bias; E_Bytes : SEO renames Fields (I).E_Bytes; F_Bytes : SEO renames Fields (I).F_Bytes; F_Size : Integer renames Fields (I).F_Size; F_Mask : SE renames Fields (I).F_Mask; Exponent : Long_Unsigned; Fraction : Long_Unsigned; Is_Positive : Boolean; E : Integer; F : Short_Float; S : SEA (1 .. SF_L) := [others => 0]; begin if not Item'Valid then raise Constraint_Error; end if; -- Compute Sign Is_Positive := (0.0 <= Item); F := abs (Item); -- Signed zero if F = 0.0 then Exponent := 0; Fraction := 0; else E := Short_Float'Exponent (F) - 1; -- Denormalized float if E <= -E_Bias then E := -E_Bias; F := Short_Float'Scaling (F, F_Size + E_Bias - 1); else F := Short_Float'Scaling (F, F_Size - E); end if; -- Compute Exponent and Fraction Exponent := Long_Unsigned (E + E_Bias); Fraction := Long_Unsigned (F * 2.0) / 2; end if; -- Store Fraction for I in reverse SF_L - F_Bytes + 1 .. SF_L loop S (I) := SE (Fraction mod BB); Fraction := Fraction / BB; end loop; -- Remove implicit bit S (SF_L - F_Bytes + 1) := S (SF_L - F_Bytes + 1) and F_Mask; -- Store Exponent (not always at the beginning of a byte) Exponent := Shift_Left (Exponent, Integer (E_Bytes) * SU - E_Size - 1); for N in reverse 1 .. E_Bytes loop S (N) := SE (Exponent mod BB) + S (N); Exponent := Exponent / BB; end loop; -- Store Sign if not Is_Positive then S (1) := S (1) + BS; end if; Ada.Streams.Write (Stream.all, S); end W_SF; ---------- -- W_SI -- ---------- procedure W_SI (Stream : not null access RST; Item : Short_Integer) is S : XDR_S_SI; U : XDR_SU; begin if Optimize_Integers then S := Short_Integer_To_XDR_S_SI (Item); else -- Test sign and apply two complement's notation U := (if Item < 0 then XDR_SU'Last xor XDR_SU (-(Item + 1)) else XDR_SU (Item)); for N in reverse S'Range loop S (N) := SE (U mod BB); U := U / BB; end loop; if U /= 0 then raise Data_Error; end if; end if; Ada.Streams.Write (Stream.all, S); end W_SI; ----------- -- W_SSI -- ----------- procedure W_SSI (Stream : not null access RST; Item : Short_Short_Integer) is S : XDR_S_SSI; U : XDR_SSU; begin if Optimize_Integers then S := Short_Short_Integer_To_XDR_S_SSI (Item); else -- Test sign and apply two complement's notation U := (if Item < 0 then XDR_SSU'Last xor XDR_SSU (-(Item + 1)) else XDR_SSU (Item)); S (1) := SE (U); end if; Ada.Streams.Write (Stream.all, S); end W_SSI; ----------- -- W_SSU -- ----------- procedure W_SSU (Stream : not null access RST; Item : Short_Short_Unsigned) is U : constant XDR_SSU := XDR_SSU (Item); S : XDR_S_SSU; begin S (1) := SE (U); Ada.Streams.Write (Stream.all, S); end W_SSU; ---------- -- W_SU -- ---------- procedure W_SU (Stream : not null access RST; Item : Short_Unsigned) is S : XDR_S_SU; U : XDR_SU := XDR_SU (Item); begin if Optimize_Integers then S := Short_Unsigned_To_XDR_S_SU (Item); else for N in reverse S'Range loop S (N) := SE (U mod BB); U := U / BB; end loop; if U /= 0 then raise Data_Error; end if; end if; Ada.Streams.Write (Stream.all, S); end W_SU; --------- -- W_U -- --------- procedure W_U (Stream : not null access RST; Item : Unsigned) is S : XDR_S_U; U : XDR_U := XDR_U (Item); begin if Optimize_Integers then S := Unsigned_To_XDR_S_U (Item); else for N in reverse S'Range loop S (N) := SE (U mod BB); U := U / BB; end loop; if U /= 0 then raise Data_Error; end if; end if; Ada.Streams.Write (Stream.all, S); end W_U; ----------- -- W_U24 -- ----------- procedure W_U24 (Stream : not null access RST; Item : Unsigned_24) is S : XDR_S_U24; U : XDR_U24 := XDR_U24 (Item); begin if Optimize_Integers then S := Unsigned_To_XDR_S_U24 (Item); else for N in reverse S'Range loop S (N) := SE (U mod BB); U := U / BB; end loop; if U /= 0 then raise Data_Error; end if; end if; Ada.Streams.Write (Stream.all, S); end W_U24; ---------- -- W_WC -- ---------- procedure W_WC (Stream : not null access RST; Item : Wide_Character) is S : XDR_S_WC; U : XDR_WC; begin -- Use Ada requirements on Wide_Character representation clause U := XDR_WC (Wide_Character'Pos (Item)); for N in reverse S'Range loop S (N) := SE (U mod BB); U := U / BB; end loop; Ada.Streams.Write (Stream.all, S); if U /= 0 then raise Data_Error; end if; end W_WC; ----------- -- W_WWC -- ----------- procedure W_WWC (Stream : not null access RST; Item : Wide_Wide_Character) is S : XDR_S_WWC; U : XDR_WWC; begin -- Use Ada requirements on Wide_Wide_Character representation clause U := XDR_WWC (Wide_Wide_Character'Pos (Item)); for N in reverse S'Range loop S (N) := SE (U mod BB); U := U / BB; end loop; Ada.Streams.Write (Stream.all, S); if U /= 0 then raise Data_Error; end if; end W_WWC; end System.Stream_Attributes.XDR;