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-2018, 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 Pos_C : Stream_Element_Offset; -- last valid element in Current 132 Pos_B : Stream_Element_Offset; -- last valid element in Buffer 133 134 Next : Buffer_Ref; 135 -- A link to another rewriter if any 136 137 Buffer : Stream_Element_Array (1 .. Size); 138 -- Fully prepared/rewritten data waiting to be output 139 140 Current : Stream_Element_Array (1 .. Size_Pattern); 141 -- Current data checked, this buffer contains every piece of data 142 -- starting with the pattern. It means that at any point: 143 -- Current (1 .. Pos_C) = Pattern (1 .. Pos_C). 144 145 Pattern : Stream_Element_Array (1 .. Size_Pattern); 146 -- The pattern to look for 147 148 Value : Stream_Element_Array (1 .. Size_Value); 149 -- The value the pattern is replaced by 150 end record; 151 152end GNAT.Rewrite_Data; 153