1------------------------------------------------------------------------------
2--                         GNAT COMPILER COMPONENTS                         --
3--                                                                          --
4--                     G N A T . R E W R I T E _ D A T A                    --
5--                                                                          --
6--                                 S p e c                                  --
7--                                                                          --
8--            Copyright (C) 2014, Free Software Foundation, Inc.            --
9--                                                                          --
10-- GNAT is free software;  you can  redistribute it  and/or modify it under --
11-- terms of the  GNU General Public License as published  by the Free Soft- --
12-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
13-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
14-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
15-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
16--                                                                          --
17-- As a special exception under Section 7 of GPL version 3, you are granted --
18-- additional permissions described in the GCC Runtime Library Exception,   --
19-- version 3.1, as published by the Free Software Foundation.               --
20--                                                                          --
21-- You should have received a copy of the GNU General Public License and    --
22-- a copy of the GCC Runtime Library Exception along with this program;     --
23-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
24-- <http://www.gnu.org/licenses/>.                                          --
25--                                                                          --
26-- GNAT was originally developed  by the GNAT team at  New York University. --
27-- Extensive contributions were provided by Ada Core Technologies Inc.      --
28--                                                                          --
29------------------------------------------------------------------------------
30
31--  This package can be used to rewrite data on the fly. All occurrences of a
32--  string (named pattern) will be replaced by another string.
33
34--  It is not necessary to load all data in memory and so this package can be
35--  used for large data chunks like disk files for example. The pattern is
36--  a standard string and not a regular expression.
37
38--  There is no dynamic allocation in the implementation.
39
40--  For example, to replace all occurrences of "Gnat" with "GNAT":
41
42--    Rewriter : Buffer := Create (Pattern => "Gnat", Value => "GNAT");
43
44--  The output procedure that will receive the rewritten data:
45
46--    procedure Do (Data : Stream_Element_Array) is
47--    begin
48--       <implementation to handle Data>
49--    end Do;
50
51--  Then:
52
53--    Write (Rewriter, "Let's talk about Gnat compiler", Do'Access);
54--    Write (Rewriter, "Gnat is an Ada compiler", Do'Access);
55--    Flush (Rewriter, Do'Access);
56
57--  Another possible usage is to specify a method to get the input data:
58
59--    procedure Get
60--      (Buffer : out Stream_Element_Array;
61--       Last   : out Stream_Element_Offset)
62--    is
63--    begin
64--       <get some data from a file, a socket, etc...>
65--       Last := ...
66--       Buffer := ...
67--    end Get;
68
69--  Then we can rewrite the whole file with:
70
71--    Rewrite (Rewriter, Input => Get'Access, Output => Do'Access);
72
73with Ada.Streams; use Ada.Streams;
74
75package GNAT.Rewrite_Data is
76
77   type Buffer (<>) is limited private;
78   type Buffer_Ref is access all Buffer;
79
80   function Create
81     (Pattern, Value : String;
82      Size           : Stream_Element_Offset := 1_024) return Buffer;
83   --  Create a rewrite buffer. Pattern is the string to be rewritten as Value.
84   --  Size represents the size of the internal buffer used to store the data
85   --  ready to be output. A larger buffer may improve the performance, as the
86   --  Output routine (see Write, Rewrite below) will be called only when this
87   --  buffer is full. Note that Size cannot be lower than Pattern'Length, and
88   --  if this is the case, then Size value is set to Pattern'Length.
89
90   function Size (B : Buffer) return Natural;
91   --  Returns the current size of the buffer (count of Stream_Array_Element)
92
93   procedure Flush
94     (B      : in out Buffer;
95      Output : not null access procedure (Data : Stream_Element_Array));
96   --  Call Output for all remaining data in the buffer. The buffer is
97   --  reset and ready for another use after this call.
98
99   procedure Reset (B : in out Buffer);
100   pragma Inline (Reset);
101   --  Clear all data in buffer, B is ready for another use. Note that this is
102   --  not needed after a Flush. Note: all data remaining in Buffer is lost.
103
104   procedure Write
105     (B      : in out Buffer;
106      Data   : Stream_Element_Array;
107      Output : not null access procedure (Data : Stream_Element_Array));
108   --  Write Data into the buffer, call Output for any prepared data. Flush
109   --  must be called when the last piece of Data as been sent in the Buffer.
110
111   procedure Rewrite
112     (B      : in out Buffer;
113      Input  : not null access procedure
114                          (Buffer : out Stream_Element_Array;
115                           Last   : out Stream_Element_Offset);
116      Output : not null access procedure (Data : Stream_Element_Array));
117   --  Read data from Input, rewrite it, and then call Output. When there is
118   --  no more data to be read from Input, Last must be set to 0. Before
119   --  leaving this routine, call Flush above to send all remaining data to
120   --  Output.
121
122   procedure Link (From : in out Buffer; To : Buffer_Ref);
123   --  Link two rewrite buffers. That is, all data sent to From buffer will be
124   --  rewritten and then passed to the To rewrite buffer.
125
126private
127
128   type Buffer
129     (Size, Size_Pattern, Size_Value : Stream_Element_Offset) is
130   limited record
131      Buffer : Stream_Element_Array (1 .. Size);
132      --  Fully prepared/rewritten data waiting to be output
133
134      Current : Stream_Element_Array (1 .. Size_Pattern);
135      --  Current data checked, this buffer contains every piece of data
136      --  starting with the pattern. It means that at any point:
137      --  Current (1 .. Pos_C) = Pattern (1 .. Pos_C).
138
139      Pattern : Stream_Element_Array (1 .. Size_Pattern);
140      --  The pattern to look for
141
142      Value : Stream_Element_Array (1 .. Size_Value);
143      --  The value the pattern is replaced by
144
145      Pos_C : Stream_Element_Offset; -- last valid element in Current
146      Pos_B : Stream_Element_Offset; -- last valid element in Buffer
147
148      Next  : Buffer_Ref;
149      --  A link to another rewriter if any
150   end record;
151
152end GNAT.Rewrite_Data;
153