summaryrefslogtreecommitdiff
path: root/gcc/ada/g-arrspl.ads
blob: d35059c1b6433ca7a7d8ad875dcd1ca411570bfc (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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
------------------------------------------------------------------------------
--                                                                          --
--                         GNAT COMPILER COMPONENTS                         --
--                                                                          --
--                     G N A T . A R R A Y _ S P L I T                      --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--          Copyright (C) 2002-2005, 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 2,  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.  See the GNU General Public License --
-- for  more details.  You should have  received  a copy of the GNU General --
-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
-- Boston, MA 02110-1301, USA.                                              --
--                                                                          --
-- As a special exception,  if other files  instantiate  generics from this --
-- unit, or you link  this unit with other files  to produce an executable, --
-- this  unit  does not  by itself cause  the resulting  executable  to  be --
-- covered  by the  GNU  General  Public  License.  This exception does not --
-- however invalidate  any other reasons why  the executable file  might be --
-- covered by the  GNU Public License.                                      --
--                                                                          --
-- GNAT was originally developed  by the GNAT team at  New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
--                                                                          --
------------------------------------------------------------------------------

--  Useful array-manipulation routines: given a set of separators, split
--  an array wherever the separators appear, and provide direct access
--  to the resulting slices.

with Ada.Finalization;

generic
   type Element is (<>);
   --  Element of the array, this must be a discrete type

   type Element_Sequence is array (Positive range <>) of Element;
   --  The array which is a sequence of element

   type Element_Set is private;
   --  This type represent a set of elements. This set does not defined a
   --  specific order of the elements. The conversion of a sequence to a
   --  set and membership tests in the set is performed using the routines
   --  To_Set and Is_In defined below.

   with function To_Set (Sequence : Element_Sequence) return Element_Set;
   --  Returns an Element_Set given an Element_Sequence. Duplicate elements
   --  can be ignored during this conversion.

   with function Is_In (Item : Element; Set : Element_Set) return Boolean;
   --  Returns True if Item is found in Set, False otherwise

package GNAT.Array_Split is

   Index_Error : exception;
   --  Raised by all operations below if Index > Field_Count (S)

   type Separator_Mode is
     (Single,
      --  In this mode the array is cut at each element in the separator
      --  set. If two separators are contiguous the result at that position
      --  is an empty slice.

      Multiple
      --  In this mode contiguous separators are handled as a single
      --  separator and no empty slice is created.
     );

   type Slice_Set is private;
   --  This type uses by-reference semantics. This is a set of slices as
   --  returned by Create or Set routines below. The abstraction represents
   --  a set of items. Each item is a part of the original string named a
   --  Slice. It is possible to access individual slices by using the Slice
   --  routine below. The first slice in the Set is at the position/index
   --  1. The total number of slices in the set is returned by Slice_Count.

   procedure Create
     (S          : out Slice_Set;
      From       : Element_Sequence;
      Separators : Element_Sequence;
      Mode       : Separator_Mode := Single);
   --  Create a cut array object. From is the source array, and Separators
   --  is a sequence of Element along which to split the array. The source
   --  array is sliced at separator boundaries. The separators are not
   --  included as part of the resulting slices.

   procedure Create
     (S          : out Slice_Set;
      From       : Element_Sequence;
      Separators : Element_Set;
      Mode       : Separator_Mode := Single);
   --  Same as above but using a Element_Set

   procedure Set
     (S          : in out Slice_Set;
      Separators : Element_Sequence;
      Mode       : Separator_Mode := Single);
   --  Change the set of separators. The source array will be split according
   --  to this new set of separators.

   procedure Set
     (S          : in out Slice_Set;
      Separators : Element_Set;
      Mode       : Separator_Mode := Single);
   --  Same as above but using a Element_Set

   type Slice_Number is new Natural;
   --  Type used to count number of slices

   function Slice_Count (S : Slice_Set) return Slice_Number;
   pragma Inline (Slice_Count);
   --  Returns the number of slices (fields) in S

   function Slice
     (S     : Slice_Set;
      Index : Slice_Number) return Element_Sequence;
   pragma Inline (Slice);
   --  Returns the slice at position Index. First slice is 1. If Index is 0
   --  the whole array is returned including the separators (this is the
   --  original source array).

   type Position is (Before, After);
   --  Used to designate position of separator

   type Slice_Separators is array (Position) of Element;
   --  Separators found before and after the slice

   Array_End : constant Element;
   --  This is the separator returned for the start or the end of the array

   function Separators
     (S     : Slice_Set;
      Index : Slice_Number) return Slice_Separators;
   --  Returns the separators used to slice (front and back) the slice at
   --  position Index. For slices at start and end of the original array, the
   --  Array_End value is returned for the corresponding outer bound. In
   --  Multiple mode only the element closest to the slice is returned.
   --  if Index = 0, returns (Array_End, Array_End).

   type Separators_Indexes is array (Positive range <>) of Positive;

   function Separators (S : Slice_Set) return Separators_Indexes;
   --  Returns indexes of all separators used to slice original source array S

private

   Array_End : constant Element := Element'First;

   type Element_Access is access Element_Sequence;

   type Counter is access Natural;

   type Indexes_Access is access Separators_Indexes;

   type Slice_Info is record
      Start : Positive;
      Stop  : Natural;
   end record;
   --  Starting/Ending position of a slice. This does not include separators

   type Slices_Indexes is array (Slice_Number range <>) of Slice_Info;
   type Slices_Access is access Slices_Indexes;
   --  All indexes for fast access to slices. In the Slice_Set we keep only
   --  the original array and the indexes where each slice start and stop.

   type Slice_Set is new Ada.Finalization.Controlled with record
      Ref_Counter : Counter;            -- Reference counter, by-address sem
      Source      : Element_Access;
      N_Slice     : Slice_Number := 0;  -- Number of slices found
      Indexes     : Indexes_Access;
      Slices      : Slices_Access;
   end record;

   procedure Initialize (S : in out Slice_Set);
   procedure Adjust     (S : in out Slice_Set);
   procedure Finalize   (S : in out Slice_Set);

end GNAT.Array_Split;