1------------------------------------------------------------------------------
2--                                                                          --
3--                         GNAT COMPILER COMPONENTS                         --
4--                                                                          --
5--                G N A T . F O R M A T T E D _ S T R I N G                 --
6--                                                                          --
7--                                 S p e c                                  --
8--                                                                          --
9--             Copyright (C) 2014, 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
32--  This package add support for formatted string as supported by C printf().
33
34--  A simple usage is:
35
36--     declare
37--        F : Formatted_String := +"['%c' ; %10d]";
38--        C : Character := 'v';
39--        I : Integer := 98;
40--     begin
41--        F := F & C & I;
42--        Put_Line (-F);
43--     end;
44
45--  Which will display:
46
47--     ['v' ;         98]
48
49--  Each format specifier is: %[flags][width][.precision][length]specifier
50
51--  Specifiers:
52--    d or i    Signed decimal integer
53--    u         Unsigned decimal integer
54--    o         Unsigned octal
55--    x         Unsigned hexadecimal integer
56--    X         Unsigned hexadecimal integer (uppercase)
57--    f         Decimal floating point, lowercase
58--    F         Decimal floating point, uppercase
59--    e         Scientific notation (mantissa/exponent), lowercase
60--    E         Scientific notation (mantissa/exponent), uppercase
61--    g         Use the shortest representation: %e or %f
62--    G         Use the shortest representation: %E or %F
63--    c         Character
64--    s         String of characters
65--    p         Pointer address
66--    %         A % followed by another % character will write a single %
67
68--  Flags:
69
70--    -         Left-justify within the given field width;
71--              Right justification is the default.
72
73--    +         Forces to preceed the result with a plus or minus sign (+ or -)
74--              even for positive numbers. By default, only negative numbers
75--              are preceded with a - sign.
76
77--    (space)   If no sign is going to be written, a blank space is inserted
78--              before the value.
79
80--    #         Used with o, x or X specifiers the value is preceeded with
81--              0, 0x or 0X respectively for values different than zero.
82--              Used with a, A, e, E, f, F, g or G it forces the written
83--              output to contain a decimal point even if no more digits
84--              follow. By default, if no digits follow, no decimal point is
85--              written.
86
87--    ~         As above, but using Ada style based <base>#<number>#
88
89--    0         Left-pads the number with zeroes (0) instead of spaces when
90--              padding is specified.
91
92--  Width:
93--    number    Minimum number of characters to be printed. If the value to
94--              be printed is shorter than this number, the result is padded
95--              with blank spaces. The value is not truncated even if the
96--              result is larger.
97
98--    *         The width is not specified in the format string, but as an
99--              additional integer value argument preceding the argument that
100--              has to be formatted.
101--  Precision:
102--    number    For integer specifiers (d, i, o, u, x, X): precision specifies
103--              the minimum number of digits to be written. If the value to be
104--              written is shorter than this number, the result is padded with
105--              leading zeros. The value is not truncated even if the result
106--              is longer. A precision of 0 means that no character is written
107--              for the value 0.
108
109--              For e, E, f and F specifiers: this is the number of digits to
110--              be printed after the decimal point (by default, this is 6).
111--              For g and G specifiers: This is the maximum number of
112--              significant digits to be printed.
113
114--              For s: this is the maximum number of characters to be printed.
115--              By default all characters are printed until the ending null
116--              character is encountered.
117
118--              If the period is specified without an explicit value for
119--              precision, 0 is assumed.
120
121--    .*        The precision is not specified in the format string, but as an
122--              additional integer value argument preceding the argument that
123--              has to be formatted.
124
125with Ada.Text_IO;
126with System;
127
128private with Ada.Finalization;
129private with Ada.Strings.Unbounded;
130
131package GNAT.Formatted_String is
132   use Ada;
133
134   type Formatted_String (<>) is private;
135   --  A format string as defined for printf routine
136
137   Format_Error : exception;
138   --  Raised for every mismatch between the parameter and the expected format
139   --  and for malformed format.
140
141   function "+" (Format : String) return Formatted_String;
142   --  Create the format string
143
144   function "-" (Format : Formatted_String) return String;
145   --  Get the result of the formatted string corresponding to the current
146   --  rendering (up to the last parameter formated).
147
148   function "&"
149     (Format : Formatted_String;
150      Var    : Character) return Formatted_String;
151   --  A character, expect a %c
152
153   function "&"
154     (Format : Formatted_String;
155      Var    : String) return Formatted_String;
156   --  A string, expect a %s
157
158   function "&"
159     (Format : Formatted_String;
160      Var    : Boolean) return Formatted_String;
161   --  A boolean image, expect a %s
162
163   function "&"
164     (Format : Formatted_String;
165      Var    : Integer) return Formatted_String;
166   --  An integer, expect a %d, %o, %x, %X
167
168   function "&"
169     (Format : Formatted_String;
170      Var    : Long_Integer) return Formatted_String;
171   --  As above
172
173   function "&"
174     (Format : Formatted_String;
175      Var    : System.Address) return Formatted_String;
176   --  An address, expect a %p
177
178   function "&"
179     (Format : Formatted_String;
180      Var    : Float) return Formatted_String;
181   --  A float, expect %f, %e, %F, %E, %g, %G
182
183   function "&"
184     (Format : Formatted_String;
185      Var    : Long_Float) return Formatted_String;
186   --  As above
187
188   function "&"
189     (Format : Formatted_String;
190      Var    : Duration) return Formatted_String;
191   --  As above
192
193   --  Some generics
194
195   generic
196      type Int is range <>;
197
198      with procedure Put
199        (To   : out String;
200         Item : Int;
201         Base : Text_IO.Number_Base);
202   function Int_Format
203     (Format : Formatted_String;
204      Var    : Int) return Formatted_String;
205   --  As for Integer above
206
207   generic
208      type Int is mod <>;
209
210      with procedure Put
211        (To   : out String;
212         Item : Int;
213         Base : Text_IO.Number_Base);
214   function Mod_Format
215     (Format : Formatted_String;
216      Var    : Int) return Formatted_String;
217   --  As for Integer above
218
219   generic
220      type Flt is digits <>;
221
222      with procedure Put
223        (To   : out String;
224         Item : Flt;
225         Aft  : Text_IO.Field;
226         Exp  : Text_IO.Field);
227   function Flt_Format
228     (Format : Formatted_String;
229      Var    : Flt) return Formatted_String;
230   --  As for Float above
231
232   generic
233      type Flt is delta <>;
234
235      with procedure Put
236        (To   : out String;
237         Item : Flt;
238         Aft  : Text_IO.Field;
239         Exp  : Text_IO.Field);
240   function Fixed_Format
241     (Format : Formatted_String;
242      Var    : Flt) return Formatted_String;
243   --  As for Float above
244
245   generic
246      type Flt is delta <> digits <>;
247
248      with procedure Put
249        (To   : out String;
250         Item : Flt;
251         Aft  : Text_IO.Field;
252         Exp  : Text_IO.Field);
253   function Decimal_Format
254     (Format : Formatted_String;
255      Var    : Flt) return Formatted_String;
256   --  As for Float above
257
258   generic
259      type Enum is (<>);
260   function Enum_Format
261     (Format : Formatted_String;
262      Var    : Enum) return Formatted_String;
263   --  As for String above, output the string representation of the enumeration
264
265private
266   use Ada.Strings.Unbounded;
267
268   type I_Vars is array (Positive range 1 .. 2) of Integer;
269   --  Used to keep 2 numbers for the possible * for the width and precision
270
271   type Data (Size : Natural) is record
272      Ref_Count    : Natural := 1;
273      Format       : String (1 .. Size); -- the format string
274      Index        : Positive := 1;      -- format index for next value
275      Result       : Unbounded_String;   -- current value
276      Current      : Natural;            -- the current format number
277      Stored_Value : Natural := 0;       -- number of stored values in Stack
278      Stack        : I_Vars;
279   end record;
280
281   type Data_Access is access Data;
282
283   --  The formatted string record is controlled and do not need an initialize
284   --  as it requires an explit initial value. This is given with "+" and
285   --  properly initialize the record at this point.
286
287   type Formatted_String is new Finalization.Controlled with record
288      D : Data_Access;
289   end record;
290
291   overriding procedure Adjust   (F : in out Formatted_String);
292   overriding procedure Finalize (F : in out Formatted_String);
293
294end GNAT.Formatted_String;
295