1------------------------------------------------------------------------------ 2-- -- 3-- GNAT RUN-TIME COMPONENTS -- 4-- -- 5-- A D A . W I D E _ T E X T _ I O . F I X E D _ I O -- 6-- -- 7-- B o d y -- 8-- -- 9-- Copyright (C) 1992-2021, Free Software Foundation, Inc. -- 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 32with Interfaces; 33with Ada.Wide_Text_IO.Fixed_Aux; 34with Ada.Wide_Text_IO.Float_Aux; 35with System.Img_Fixed_32; use System.Img_Fixed_32; 36with System.Img_Fixed_64; use System.Img_Fixed_64; 37with System.Img_LFlt; use System.Img_LFlt; 38with System.Val_Fixed_32; use System.Val_Fixed_32; 39with System.Val_Fixed_64; use System.Val_Fixed_64; 40with System.Val_LFlt; use System.Val_LFlt; 41with System.WCh_Con; use System.WCh_Con; 42with System.WCh_WtS; use System.WCh_WtS; 43 44package body Ada.Wide_Text_IO.Fixed_IO is 45 46 -- Note: we still use the floating-point I/O routines for types whose small 47 -- is not the ratio of two sufficiently small integers. This will result in 48 -- inaccuracies for fixed point types that require more precision than is 49 -- available in Long_Float. 50 51 subtype Int32 is Interfaces.Integer_32; use type Int32; 52 subtype Int64 is Interfaces.Integer_64; use type Int64; 53 54 package Aux32 is new 55 Ada.Wide_Text_IO.Fixed_Aux (Int32, Scan_Fixed32, Set_Image_Fixed32); 56 57 package Aux64 is new 58 Ada.Wide_Text_IO.Fixed_Aux (Int64, Scan_Fixed64, Set_Image_Fixed64); 59 60 package Aux_Long_Float is new 61 Ada.Wide_Text_IO.Float_Aux 62 (Long_Float, Scan_Long_Float, Set_Image_Long_Float); 63 64 -- Throughout this generic body, we distinguish between the case where type 65 -- Int32 is OK and where type Int64 is OK. These boolean constants are used 66 -- to test for this, such that only code for the relevant case is included 67 -- in the instance; that's why the computation of their value must be fully 68 -- static (although it is not a static expressions in the RM sense). 69 70 OK_Get_32 : constant Boolean := 71 Num'Base'Object_Size <= 32 72 and then 73 ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**31) 74 or else 75 (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**31) 76 or else 77 (Num'Small_Numerator <= 2**27 78 and then Num'Small_Denominator <= 2**27)); 79 -- These conditions are derived from the prerequisites of System.Value_F 80 81 OK_Put_32 : constant Boolean := 82 Num'Base'Object_Size <= 32 83 and then 84 ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**31) 85 or else 86 (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**31) 87 or else 88 (Num'Small_Numerator < Num'Small_Denominator 89 and then Num'Small_Denominator <= 2**27) 90 or else 91 (Num'Small_Denominator < Num'Small_Numerator 92 and then Num'Small_Numerator <= 2**25)); 93 -- These conditions are derived from the prerequisites of System.Image_F 94 95 OK_Get_64 : constant Boolean := 96 Num'Base'Object_Size <= 64 97 and then 98 ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**63) 99 or else 100 (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**63) 101 or else 102 (Num'Small_Numerator <= 2**59 103 and then Num'Small_Denominator <= 2**59)); 104 -- These conditions are derived from the prerequisites of System.Value_F 105 106 OK_Put_64 : constant Boolean := 107 Num'Base'Object_Size <= 64 108 and then 109 ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**63) 110 or else 111 (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**63) 112 or else 113 (Num'Small_Numerator < Num'Small_Denominator 114 and then Num'Small_Denominator <= 2**59) 115 or else 116 (Num'Small_Denominator < Num'Small_Numerator 117 and then Num'Small_Numerator <= 2**53)); 118 -- These conditions are derived from the prerequisites of System.Image_F 119 120 E : constant Natural := 63 - 32 * Boolean'Pos (OK_Put_32); 121 -- T'Size - 1 for the selected Int{32,64} 122 123 F0 : constant Natural := 0; 124 F1 : constant Natural := 125 F0 + 18 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F0) >= 1.0E+18); 126 F2 : constant Natural := 127 F1 + 9 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F1) >= 1.0E+9); 128 F3 : constant Natural := 129 F2 + 5 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F2) >= 1.0E+5); 130 F4 : constant Natural := 131 F3 + 3 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F3) >= 1.0E+3); 132 F5 : constant Natural := 133 F4 + 2 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F4) >= 1.0E+2); 134 F6 : constant Natural := 135 F5 + 1 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F5) >= 1.0E+1); 136 -- Binary search for the number of digits - 1 before the decimal point of 137 -- the product 2.0**E * Num'Small. 138 139 For0 : constant Natural := 2 + F6; 140 -- Fore value for the fixed point type whose mantissa is Int{32,64} and 141 -- whose small is Num'Small. 142 143 --------- 144 -- Get -- 145 --------- 146 147 procedure Get 148 (File : File_Type; 149 Item : out Num; 150 Width : Field := 0) 151 is 152 pragma Unsuppress (Range_Check); 153 154 begin 155 if OK_Get_32 then 156 Item := Num'Fixed_Value 157 (Aux32.Get (File, Width, 158 -Num'Small_Numerator, 159 -Num'Small_Denominator)); 160 elsif OK_Get_64 then 161 Item := Num'Fixed_Value 162 (Aux64.Get (File, Width, 163 -Num'Small_Numerator, 164 -Num'Small_Denominator)); 165 else 166 Aux_Long_Float.Get (File, Long_Float (Item), Width); 167 end if; 168 169 exception 170 when Constraint_Error => raise Data_Error; 171 end Get; 172 173 procedure Get 174 (Item : out Num; 175 Width : Field := 0) 176 is 177 begin 178 Get (Current_In, Item, Width); 179 end Get; 180 181 procedure Get 182 (From : Wide_String; 183 Item : out Num; 184 Last : out Positive) 185 is 186 pragma Unsuppress (Range_Check); 187 188 S : constant String := Wide_String_To_String (From, WCEM_Upper); 189 -- String on which we do the actual conversion. Note that the method 190 -- used for wide character encoding is irrelevant, since if there is 191 -- a character outside the Standard.Character range then the call to 192 -- Aux.Gets will raise Data_Error in any case. 193 194 begin 195 if OK_Get_32 then 196 Item := Num'Fixed_Value 197 (Aux32.Gets (S, Last, 198 -Num'Small_Numerator, 199 -Num'Small_Denominator)); 200 elsif OK_Get_64 then 201 Item := Num'Fixed_Value 202 (Aux64.Gets (S, Last, 203 -Num'Small_Numerator, 204 -Num'Small_Denominator)); 205 else 206 Aux_Long_Float.Gets (S, Long_Float (Item), Last); 207 end if; 208 209 exception 210 when Constraint_Error => raise Data_Error; 211 end Get; 212 213 --------- 214 -- Put -- 215 --------- 216 217 procedure Put 218 (File : File_Type; 219 Item : Num; 220 Fore : Field := Default_Fore; 221 Aft : Field := Default_Aft; 222 Exp : Field := Default_Exp) 223 is 224 begin 225 if OK_Put_32 then 226 Aux32.Put (File, Int32'Integer_Value (Item), Fore, Aft, Exp, 227 -Num'Small_Numerator, -Num'Small_Denominator, 228 For0, Num'Aft); 229 elsif OK_Put_64 then 230 Aux64.Put (File, Int64'Integer_Value (Item), Fore, Aft, Exp, 231 -Num'Small_Numerator, -Num'Small_Denominator, 232 For0, Num'Aft); 233 else 234 Aux_Long_Float.Put (File, Long_Float (Item), Fore, Aft, Exp); 235 end if; 236 end Put; 237 238 procedure Put 239 (Item : Num; 240 Fore : Field := Default_Fore; 241 Aft : Field := Default_Aft; 242 Exp : Field := Default_Exp) 243 is 244 begin 245 Put (Current_Out, Item, Fore, Aft, Exp); 246 end Put; 247 248 procedure Put 249 (To : out Wide_String; 250 Item : Num; 251 Aft : Field := Default_Aft; 252 Exp : Field := Default_Exp) 253 is 254 S : String (To'First .. To'Last); 255 256 begin 257 if OK_Put_32 then 258 Aux32.Puts (S, Int32'Integer_Value (Item), Aft, Exp, 259 -Num'Small_Numerator, -Num'Small_Denominator, 260 For0, Num'Aft); 261 elsif OK_Put_64 then 262 Aux64.Puts (S, Int64'Integer_Value (Item), Aft, Exp, 263 -Num'Small_Numerator, -Num'Small_Denominator, 264 For0, Num'Aft); 265 else 266 Aux_Long_Float.Puts (S, Long_Float (Item), Aft, Exp); 267 end if; 268 269 for J in S'Range loop 270 To (J) := Wide_Character'Val (Character'Pos (S (J))); 271 end loop; 272 end Put; 273 274end Ada.Wide_Text_IO.Fixed_IO; 275