PR sanitizer/80403
[official-gcc.git] / gcc / ada / g-rewdat.adb
blob855f78736adfe2ea7666a1a27708a76f412ca93b
1 -----------------------------------------------------------------------------
2 -- GNAT COMPILER COMPONENTS --
3 -- --
4 -- G N A T . R E W R I T E _ D A T A --
5 -- --
6 -- B o d y --
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 ------------------------------------------------------------------------------
31 with Ada.Unchecked_Conversion;
33 package body GNAT.Rewrite_Data is
35 use Ada;
37 subtype SEO is Stream_Element_Offset;
39 procedure Do_Output
40 (B : in out Buffer;
41 Data : Stream_Element_Array;
42 Output : not null access procedure (Data : Stream_Element_Array));
43 -- Do the actual output. This ensures that we properly send the data
44 -- through linked rewrite buffers if any.
46 ------------
47 -- Create --
48 ------------
50 function Create
51 (Pattern, Value : String;
52 Size : Stream_Element_Offset := 1_024) return Buffer
55 subtype SP is String (1 .. Pattern'Length);
56 subtype SEAP is Stream_Element_Array (1 .. Pattern'Length);
58 subtype SV is String (1 .. Value'Length);
59 subtype SEAV is Stream_Element_Array (1 .. Value'Length);
61 function To_SEAP is new Unchecked_Conversion (SP, SEAP);
62 function To_SEAV is new Unchecked_Conversion (SV, SEAV);
64 begin
65 -- Return result (can't be smaller than pattern)
67 return B : Buffer
68 (SEO'Max (Size, SEO (Pattern'Length)),
69 SEO (Pattern'Length),
70 SEO (Value'Length))
72 B.Pattern := To_SEAP (Pattern);
73 B.Value := To_SEAV (Value);
74 B.Pos_C := 0;
75 B.Pos_B := 0;
76 end return;
77 end Create;
79 ---------------
80 -- Do_Output --
81 ---------------
83 procedure Do_Output
84 (B : in out Buffer;
85 Data : Stream_Element_Array;
86 Output : not null access procedure (Data : Stream_Element_Array))
88 begin
89 if B.Next = null then
90 Output (Data);
91 else
92 Write (B.Next.all, Data, Output);
93 end if;
94 end Do_Output;
96 -----------
97 -- Flush --
98 -----------
100 procedure Flush
101 (B : in out Buffer;
102 Output : not null access procedure (Data : Stream_Element_Array))
104 begin
105 -- Flush output buffer
107 if B.Pos_B > 0 then
108 Do_Output (B, B.Buffer (1 .. B.Pos_B), Output);
109 end if;
111 -- Flush current buffer
113 if B.Pos_C > 0 then
114 Do_Output (B, B.Current (1 .. B.Pos_C), Output);
115 end if;
117 -- Flush linked buffer if any
119 if B.Next /= null then
120 Flush (B.Next.all, Output);
121 end if;
123 Reset (B);
124 end Flush;
126 ----------
127 -- Link --
128 ----------
130 procedure Link (From : in out Buffer; To : Buffer_Ref) is
131 begin
132 From.Next := To;
133 end Link;
135 -----------
136 -- Reset --
137 -----------
139 procedure Reset (B : in out Buffer) is
140 begin
141 B.Pos_B := 0;
142 B.Pos_C := 0;
144 if B.Next /= null then
145 Reset (B.Next.all);
146 end if;
147 end Reset;
149 -------------
150 -- Rewrite --
151 -------------
153 procedure Rewrite
154 (B : in out Buffer;
155 Input : not null access procedure
156 (Buffer : out Stream_Element_Array;
157 Last : out Stream_Element_Offset);
158 Output : not null access procedure (Data : Stream_Element_Array))
160 Buffer : Stream_Element_Array (1 .. B.Size);
161 Last : Stream_Element_Offset;
163 begin
164 Rewrite_All : loop
165 Input (Buffer, Last);
166 exit Rewrite_All when Last = 0;
167 Write (B, Buffer (1 .. Last), Output);
168 end loop Rewrite_All;
170 Flush (B, Output);
171 end Rewrite;
173 ----------
174 -- Size --
175 ----------
177 function Size (B : Buffer) return Natural is
178 begin
179 return Natural (B.Pos_B + B.Pos_C);
180 end Size;
182 -----------
183 -- Write --
184 -----------
186 procedure Write
187 (B : in out Buffer;
188 Data : Stream_Element_Array;
189 Output : not null access procedure (Data : Stream_Element_Array))
191 procedure Need_Space (Size : Stream_Element_Offset);
192 pragma Inline (Need_Space);
194 ----------------
195 -- Need_Space --
196 ----------------
198 procedure Need_Space (Size : Stream_Element_Offset) is
199 begin
200 if B.Pos_B + Size > B.Size then
201 Do_Output (B, B.Buffer (1 .. B.Pos_B), Output);
202 B.Pos_B := 0;
203 end if;
204 end Need_Space;
206 -- Start of processing for Write
208 begin
209 if B.Size_Pattern = 0 then
210 Do_Output (B, Data, Output);
212 else
213 for K in Data'Range loop
214 if Data (K) = B.Pattern (B.Pos_C + 1) then
216 -- Store possible start of a match
218 B.Pos_C := B.Pos_C + 1;
219 B.Current (B.Pos_C) := Data (K);
221 else
222 -- Not part of pattern, if a start of a match was found,
223 -- remove it.
225 if B.Pos_C /= 0 then
226 Need_Space (B.Pos_C);
228 B.Buffer (B.Pos_B + 1 .. B.Pos_B + B.Pos_C) :=
229 B.Current (1 .. B.Pos_C);
230 B.Pos_B := B.Pos_B + B.Pos_C;
231 B.Pos_C := 0;
232 end if;
234 Need_Space (1);
235 B.Pos_B := B.Pos_B + 1;
236 B.Buffer (B.Pos_B) := Data (K);
237 end if;
239 if B.Pos_C = B.Size_Pattern then
241 -- The pattern is found
243 Need_Space (B.Size_Value);
245 B.Buffer (B.Pos_B + 1 .. B.Pos_B + B.Size_Value) := B.Value;
246 B.Pos_C := 0;
247 B.Pos_B := B.Pos_B + B.Size_Value;
248 end if;
249 end loop;
250 end if;
251 end Write;
253 end GNAT.Rewrite_Data;