blob: 8149565d31ed61e90f02860f40ec30d9b8f8e7f6 [file] [log] [blame]
-- --
-- G N A T . R E W R I T E _ D A T A --
-- --
-- S p e c --
-- --
-- Copyright (C) 2014-2021, 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 --
-- --
-- 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 --
-- <>. --
-- --
-- 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.
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;