aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/libgnat/g-rewdat.ads
blob: 47586fbc0c2ca0b2413a23388d4c8324c6463d60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
------------------------------------------------------------------------------
--                         GNAT COMPILER COMPONENTS                         --
--                                                                          --
--                     G N A T . R E W R I T E _ D A T A                    --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--           Copyright (C) 2014-2024, Free Software Foundation, Inc.        --
--                                                                          --
-- GNAT 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    --
-- <http://www.gnu.org/licenses/>.                                          --
--                                                                          --
-- GNAT was originally developed  by the GNAT team at  New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
--                                                                          --
------------------------------------------------------------------------------

--  This package can be used to rewrite data on the fly. All occurrences of a
--  string (named pattern) will be replaced by another string.

--  It is not necessary to load all data in memory and so this package can be
--  used for large data chunks like disk files for example. The pattern is
--  a standard string and not a regular expression.

--  There is no dynamic allocation in the implementation.

--  For example, to replace all occurrences of "Gnat" with "GNAT":

--    Rewriter : Buffer := Create (Pattern => "Gnat", Value => "GNAT");

--  The output procedure that will receive the rewritten data:

--    procedure Do (Data : Stream_Element_Array) is
--    begin
--       <implementation to handle Data>
--    end Do;

--  Then:

--    Write (Rewriter, "Let's talk about Gnat compiler", Do'Access);
--    Write (Rewriter, "Gnat is an Ada compiler", Do'Access);
--    Flush (Rewriter, Do'Access);

--  Another possible usage is to specify a method to get the input data:

--    procedure Get
--      (Buffer : out Stream_Element_Array;
--       Last   : out Stream_Element_Offset)
--    is
--    begin
--       <get some data from a file, a socket, etc...>
--       Last := ...
--       Buffer := ...
--    end Get;

--  Then we can rewrite the whole file with:

--    Rewrite (Rewriter, Input => Get'Access, Output => Do'Access);

with Ada.Streams; use Ada.Streams;

package GNAT.Rewrite_Data is

   type Buffer (<>) is limited private;
   type Buffer_Ref is access all Buffer;

   function Create
     (Pattern, Value : String;
      Size           : Stream_Element_Offset := 1_024) return Buffer;
   --  Create a rewrite buffer. Pattern is the string to be rewritten as Value.
   --  Size represents the size of the internal buffer used to store the data
   --  ready to be output. A larger buffer may improve the performance, as the
   --  Output routine (see Write, Rewrite below) will be called only when this
   --  buffer is full. Note that Size cannot be lower than Pattern'Length, and
   --  if this is the case, then Size value is set to Pattern'Length.

   function Size (B : Buffer) return Natural;
   --  Returns the current size of the buffer (count of Stream_Array_Element)

   procedure Flush
     (B      : in out Buffer;
      Output : not null access procedure (Data : Stream_Element_Array));
   --  Call Output for all remaining data in the buffer. The buffer is
   --  reset and ready for another use after this call.

   procedure Reset (B : in out Buffer);
   pragma Inline (Reset);
   --  Clear all data in buffer, B is ready for another use. Note that this is
   --  not needed after a Flush. Note: all data remaining in Buffer is lost.

   procedure Write
     (B      : in out Buffer;
      Data   : Stream_Element_Array;
      Output : not null access procedure (Data : Stream_Element_Array));
   --  Write Data into the buffer, call Output for any prepared data. Flush
   --  must be called when the last piece of Data as been sent in the Buffer.

   procedure Rewrite
     (B      : in out Buffer;
      Input  : not null access procedure
                          (Buffer : out Stream_Element_Array;
                           Last   : out Stream_Element_Offset);
      Output : not null access procedure (Data : Stream_Element_Array));
   --  Read data from Input, rewrite it, and then call Output. When there is
   --  no more data to be read from Input, Last must be set to 0. Before
   --  leaving this routine, call Flush above to send all remaining data to
   --  Output.

   procedure Link (From : in out Buffer; To : Buffer_Ref);
   --  Link two rewrite buffers. That is, all data sent to From buffer will be
   --  rewritten and then passed to the To rewrite buffer.

private

   type Buffer
     (Size, Size_Pattern, Size_Value : Stream_Element_Offset) is
   limited record
      Pos_C : Stream_Element_Offset; -- last valid element in Current
      Pos_B : Stream_Element_Offset; -- last valid element in Buffer

      Next  : Buffer_Ref;
      --  A link to another rewriter if any

      Buffer : Stream_Element_Array (1 .. Size);
      --  Fully prepared/rewritten data waiting to be output

      Current : Stream_Element_Array (1 .. Size_Pattern);
      --  Current data checked, this buffer contains every piece of data
      --  starting with the pattern. It means that at any point:
      --  Current (1 .. Pos_C) = Pattern (1 .. Pos_C).

      Pattern : Stream_Element_Array (1 .. Size_Pattern);
      --  The pattern to look for

      Value : Stream_Element_Array (1 .. Size_Value);
      --  The value the pattern is replaced by
   end record;

end GNAT.Rewrite_Data;