1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- G N A T . A R R A Y _ S P L I T --
9 -- Copyright (C) 2002-2006, 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 new Ada.Unchecked_Deallocation (Element_Sequence, Element_Access);
48 (Source : Element_Sequence;
49 Pattern : Element_Set) return Natural;
50 -- Returns the number of occurences of Pattern elements in Source, 0 is
51 -- returned if no occurence is found in Source.
57 procedure Adjust (S : in out Slice_Set) is
59 S.Ref_Counter.all := S.Ref_Counter.all + 1;
68 From : Element_Sequence;
69 Separators : Element_Sequence;
70 Mode : Separator_Mode := Single)
73 Create (S, From, To_Set (Separators), Mode);
82 From : Element_Sequence;
83 Separators : Element_Set;
84 Mode : Separator_Mode := Single)
88 S.Source := new Element_Sequence'(From);
89 Set (S, Separators, Mode);
97 (Source : Element_Sequence;
98 Pattern : Element_Set) return Natural
102 for K in Source'Range loop
103 if Is_In (Source (K), Pattern) then
115 procedure Finalize (S : in out Slice_Set) is
118 new Ada.Unchecked_Deallocation (Element_Sequence, Element_Access);
121 new Ada.Unchecked_Deallocation (Natural, Counter);
124 S.Ref_Counter.all := S.Ref_Counter.all - 1;
126 if S.Ref_Counter.all = 0 then
130 Free (S.Ref_Counter);
138 procedure Initialize (S : in out Slice_Set) is
140 S.Ref_Counter := new Natural'(1);
149 Index : Slice_Number) return Slice_Separators
152 if Index > S.N_Slice then
156 or else (Index = 1 and then S.N_Slice = 1)
158 -- Whole string, or no separator used
160 return (Before => Array_End,
164 return (Before => Array_End,
165 After => S.Source (S.Slices (Index).Stop + 1));
167 elsif Index = S.N_Slice then
168 return (Before => S.Source (S.Slices (Index).Start - 1),
172 return (Before => S.Source (S.Slices (Index).Start - 1),
173 After => S.Source (S.Slices (Index).Stop + 1));
181 function Separators (S : Slice_Set) return Separators_Indexes is
183 return S.Indexes.all;
191 (S : in out Slice_Set;
192 Separators : Element_Sequence;
193 Mode : Separator_Mode := Single)
196 Set (S, To_Set (Separators), Mode);
204 (S : in out Slice_Set;
205 Separators : Element_Set;
206 Mode : Separator_Mode := Single)
208 Count_Sep : constant Natural := Count (S.Source.all, Separators);
211 -- Free old structure
215 -- Compute all separator's indexes
217 S.Indexes := new Separators_Indexes (1 .. Count_Sep);
218 J := S.Indexes'First;
220 for K in S.Source'Range loop
221 if Is_In (S.Source (K), Separators) then
227 -- Compute slice info for fast slice access
230 S_Info : Slices_Indexes (1 .. Slice_Number (Count_Sep) + 1);
232 Start, Stop : Natural;
237 Start := S.Source'First;
241 if K > Count_Sep then
243 -- No more separators, last slice ends at the end of the source
246 Stop := S.Source'Last;
248 Stop := S.Indexes (K) - 1;
251 -- Add slice to the table
253 S.N_Slice := S.N_Slice + 1;
254 S_Info (S.N_Slice) := (Start, Stop);
256 exit when K > Count_Sep;
262 -- In this mode just set start to character next to the
263 -- current separator, advance the separator index.
265 Start := S.Indexes (K) + 1;
270 -- In this mode skip separators following each other
273 Start := S.Indexes (K) + 1;
275 exit when K > Count_Sep
276 or else S.Indexes (K) > S.Indexes (K - 1) + 1;
282 S.Slices := new Slices_Indexes'(S_Info (1 .. S.N_Slice));
292 Index : Slice_Number) return Element_Sequence
298 elsif Index > S.N_Slice then
302 return S.Source (S.Slices (Index).Start .. S.Slices (Index).Stop);
310 function Slice_Count (S : Slice_Set) return Slice_Number is
315 end GNAT.Array_Split;