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