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;
|