1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- G N A T . A R R A Y _ S P L I T --
9 -- Copyright (C) 2002-2005, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
34 with Ada
.Unchecked_Deallocation
;
36 package body GNAT
.Array_Split
is
39 new Ada
.Unchecked_Deallocation
(Slices_Indexes
, Slices_Access
);
42 new Ada
.Unchecked_Deallocation
(Separators_Indexes
, Indexes_Access
);
45 (Source
: Element_Sequence
;
46 Pattern
: Element_Set
) return Natural;
47 -- Returns the number of occurences of Pattern elements in Source, 0 is
48 -- returned if no occurence is found in Source.
54 procedure Adjust
(S
: in out Slice_Set
) is
56 S
.Ref_Counter
.all := S
.Ref_Counter
.all + 1;
65 From
: Element_Sequence
;
66 Separators
: Element_Sequence
;
67 Mode
: Separator_Mode
:= Single
)
70 Create
(S
, From
, To_Set
(Separators
), Mode
);
79 From
: Element_Sequence
;
80 Separators
: Element_Set
;
81 Mode
: Separator_Mode
:= Single
)
84 S
.Source
:= new Element_Sequence
'(From);
85 Set (S, Separators, Mode);
93 (Source : Element_Sequence;
94 Pattern : Element_Set) return Natural
98 for K in Source'Range loop
99 if Is_In (Source (K), Pattern) then
111 procedure Finalize (S : in out Slice_Set) is
114 new Ada.Unchecked_Deallocation (Element_Sequence, Element_Access);
117 new Ada.Unchecked_Deallocation (Natural, Counter);
120 S.Ref_Counter.all := S.Ref_Counter.all - 1;
122 if S.Ref_Counter.all = 0 then
126 Free (S.Ref_Counter);
134 procedure Initialize (S : in out Slice_Set) is
136 S.Ref_Counter := new Natural'(1);
145 Index
: Slice_Number
) return Slice_Separators
148 if Index
> S
.N_Slice
then
152 or else (Index
= 1 and then S
.N_Slice
= 1)
154 -- Whole string, or no separator used
156 return (Before
=> Array_End
,
160 return (Before
=> Array_End
,
161 After
=> S
.Source
(S
.Slices
(Index
).Stop
+ 1));
163 elsif Index
= S
.N_Slice
then
164 return (Before
=> S
.Source
(S
.Slices
(Index
).Start
- 1),
168 return (Before
=> S
.Source
(S
.Slices
(Index
).Start
- 1),
169 After
=> S
.Source
(S
.Slices
(Index
).Stop
+ 1));
177 function Separators
(S
: Slice_Set
) return Separators_Indexes
is
179 return S
.Indexes
.all;
187 (S
: in out Slice_Set
;
188 Separators
: Element_Sequence
;
189 Mode
: Separator_Mode
:= Single
)
192 Set
(S
, To_Set
(Separators
), Mode
);
200 (S
: in out Slice_Set
;
201 Separators
: Element_Set
;
202 Mode
: Separator_Mode
:= Single
)
204 Count_Sep
: constant Natural := Count
(S
.Source
.all, Separators
);
207 -- Free old structure
211 -- Compute all separator's indexes
213 S
.Indexes
:= new Separators_Indexes
(1 .. Count_Sep
);
214 J
:= S
.Indexes
'First;
216 for K
in S
.Source
'Range loop
217 if Is_In
(S
.Source
(K
), Separators
) then
223 -- Compute slice info for fast slice access
226 S_Info
: Slices_Indexes
(1 .. Slice_Number
(Count_Sep
) + 1);
228 Start
, Stop
: Natural;
233 Start
:= S
.Source
'First;
237 if K
> Count_Sep
then
239 -- No more separators, last slice ends at the end of the source
242 Stop
:= S
.Source
'Last;
244 Stop
:= S
.Indexes
(K
) - 1;
247 -- Add slice to the table
249 S
.N_Slice
:= S
.N_Slice
+ 1;
250 S_Info
(S
.N_Slice
) := (Start
, Stop
);
252 exit when K
> Count_Sep
;
258 -- In this mode just set start to character next to the
259 -- current separator, advance the separator index.
261 Start
:= S
.Indexes
(K
) + 1;
266 -- In this mode skip separators following each other
269 Start
:= S
.Indexes
(K
) + 1;
271 exit when K
> Count_Sep
272 or else S
.Indexes
(K
) > S
.Indexes
(K
- 1) + 1;
278 S
.Slices
:= new Slices_Indexes
'(S_Info (1 .. S.N_Slice));
288 Index : Slice_Number) return Element_Sequence
294 elsif Index > S.N_Slice then
298 return S.Source (S.Slices (Index).Start .. S.Slices (Index).Stop);
306 function Slice_Count (S : Slice_Set) return Slice_Number is
311 end GNAT.Array_Split;