1 ------------------------------------------------------------------------------
3 -- GNAT RUNTIME COMPONENTS --
5 -- A D A . S T R I N G S . W I D E _ U N B O U N D E D --
9 -- Copyright (C) 1992-2002 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, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, 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
.Strings
.Wide_Fixed
;
35 with Ada
.Strings
.Wide_Search
;
36 with Ada
.Unchecked_Deallocation
;
38 package body Ada
.Strings
.Wide_Unbounded
is
42 procedure Realloc_For_Chunk
43 (Source
: in out Unbounded_Wide_String
;
44 Chunk_Size
: Natural);
45 pragma Inline
(Realloc_For_Chunk
);
46 -- Adjust the size allocated for the string. Add at least Chunk_Size so it
47 -- is safe to add a string of this size at the end of the current
48 -- content. The real size allocated for the string is Chunk_Size + x %
49 -- of the current string size. This buffered handling makes the Append
50 -- unbounded wide string routines very fast.
57 (Left
: Unbounded_Wide_String
;
58 Right
: Unbounded_Wide_String
)
59 return Unbounded_Wide_String
61 L_Length
: constant Natural := Left
.Last
;
62 R_Length
: constant Natural := Right
.Last
;
63 Result
: Unbounded_Wide_String
;
66 Result
.Last
:= L_Length
+ R_Length
;
68 Result
.Reference
:= new Wide_String (1 .. Result
.Last
);
70 Result
.Reference
(1 .. L_Length
) :=
71 Left
.Reference
(1 .. Left
.Last
);
72 Result
.Reference
(L_Length
+ 1 .. Result
.Last
) :=
73 Right
.Reference
(1 .. Right
.Last
);
79 (Left
: Unbounded_Wide_String
;
81 return Unbounded_Wide_String
83 L_Length
: constant Natural := Left
.Last
;
84 Result
: Unbounded_Wide_String
;
87 Result
.Last
:= L_Length
+ Right
'Length;
89 Result
.Reference
:= new Wide_String (1 .. Result
.Last
);
91 Result
.Reference
(1 .. L_Length
) := Left
.Reference
(1 .. Left
.Last
);
92 Result
.Reference
(L_Length
+ 1 .. Result
.Last
) := Right
;
99 Right
: Unbounded_Wide_String
)
100 return Unbounded_Wide_String
102 R_Length
: constant Natural := Right
.Last
;
103 Result
: Unbounded_Wide_String
;
106 Result
.Last
:= Left
'Length + R_Length
;
108 Result
.Reference
:= new Wide_String (1 .. Result
.Last
);
110 Result
.Reference
(1 .. Left
'Length) := Left
;
111 Result
.Reference
(Left
'Length + 1 .. Result
.Last
) :=
112 Right
.Reference
(1 .. Right
.Last
);
118 (Left
: Unbounded_Wide_String
;
119 Right
: Wide_Character)
120 return Unbounded_Wide_String
122 Result
: Unbounded_Wide_String
;
125 Result
.Last
:= Left
.Last
+ 1;
127 Result
.Reference
:= new Wide_String (1 .. Result
.Last
);
129 Result
.Reference
(1 .. Result
.Last
- 1) :=
130 Left
.Reference
(1 .. Left
.Last
);
131 Result
.Reference
(Result
.Last
) := Right
;
137 (Left
: Wide_Character;
138 Right
: Unbounded_Wide_String
)
139 return Unbounded_Wide_String
141 Result
: Unbounded_Wide_String
;
144 Result
.Last
:= Right
.Last
+ 1;
146 Result
.Reference
:= new Wide_String (1 .. Result
.Last
);
147 Result
.Reference
(1) := Left
;
148 Result
.Reference
(2 .. Result
.Last
) :=
149 Right
.Reference
(1 .. Right
.Last
);
160 Right
: Wide_Character)
161 return Unbounded_Wide_String
163 Result
: Unbounded_Wide_String
;
168 Result
.Reference
:= new Wide_String (1 .. Left
);
169 for J
in Result
.Reference
'Range loop
170 Result
.Reference
(J
) := Right
;
179 return Unbounded_Wide_String
181 Len
: constant Natural := Right
'Length;
183 Result
: Unbounded_Wide_String
;
186 Result
.Last
:= Left
* Len
;
188 Result
.Reference
:= new Wide_String (1 .. Result
.Last
);
191 for J
in 1 .. Left
loop
192 Result
.Reference
(K
.. K
+ Len
- 1) := Right
;
201 Right
: Unbounded_Wide_String
)
202 return Unbounded_Wide_String
204 Len
: constant Natural := Right
.Last
;
206 Result
: Unbounded_Wide_String
;
209 Result
.Last
:= Left
* Len
;
211 Result
.Reference
:= new Wide_String (1 .. Result
.Last
);
214 for I
in 1 .. Left
loop
215 Result
.Reference
(K
.. K
+ Len
- 1) :=
216 Right
.Reference
(1 .. Right
.Last
);
228 (Left
: Unbounded_Wide_String
;
229 Right
: Unbounded_Wide_String
)
234 Left
.Reference
(1 .. Left
.Last
) < Right
.Reference
(1 .. Right
.Last
);
238 (Left
: Unbounded_Wide_String
;
243 return Left
.Reference
(1 .. Left
.Last
) < Right
;
248 Right
: Unbounded_Wide_String
)
252 return Left
< Right
.Reference
(1 .. Right
.Last
);
260 (Left
: Unbounded_Wide_String
;
261 Right
: Unbounded_Wide_String
)
266 Left
.Reference
(1 .. Left
.Last
) <= Right
.Reference
(1 .. Right
.Last
);
270 (Left
: Unbounded_Wide_String
;
275 return Left
.Reference
(1 .. Left
.Last
) <= Right
;
280 Right
: Unbounded_Wide_String
)
284 return Left
<= Right
.Reference
(1 .. Right
.Last
);
292 (Left
: Unbounded_Wide_String
;
293 Right
: Unbounded_Wide_String
)
298 Left
.Reference
(1 .. Left
.Last
) = Right
.Reference
(1 .. Right
.Last
);
302 (Left
: Unbounded_Wide_String
;
307 return Left
.Reference
(1 .. Left
.Last
) = Right
;
312 Right
: Unbounded_Wide_String
)
316 return Left
= Right
.Reference
(1 .. Right
.Last
);
324 (Left
: Unbounded_Wide_String
;
325 Right
: Unbounded_Wide_String
)
330 Left
.Reference
(1 .. Left
.Last
) > Right
.Reference
(1 .. Right
.Last
);
334 (Left
: Unbounded_Wide_String
;
339 return Left
.Reference
(1 .. Left
.Last
) > Right
;
344 Right
: Unbounded_Wide_String
)
348 return Left
> Right
.Reference
(1 .. Right
.Last
);
356 (Left
: Unbounded_Wide_String
;
357 Right
: Unbounded_Wide_String
)
362 Left
.Reference
(1 .. Left
.Last
) >= Right
.Reference
(1 .. Right
.Last
);
366 (Left
: Unbounded_Wide_String
;
371 return Left
.Reference
(1 .. Left
.Last
) >= Right
;
376 Right
: Unbounded_Wide_String
)
380 return Left
>= Right
.Reference
(1 .. Right
.Last
);
387 procedure Adjust
(Object
: in out Unbounded_Wide_String
) is
389 -- Copy string, except we do not copy the statically allocated
390 -- null string, since it can never be deallocated.
391 -- Note that we do not copy extra string room here to avoid dragging
392 -- unused allocated memory.
394 if Object
.Reference
/= Null_Wide_String
'Access then
396 new Wide_String'(Object.Reference (1 .. Object.Last));
405 (Source : in out Unbounded_Wide_String;
406 New_Item : Unbounded_Wide_String)
409 Realloc_For_Chunk (Source, New_Item.Last);
410 Source.Reference (Source.Last + 1 .. Source.Last + New_Item.Last) :=
411 New_Item.Reference (1 .. New_Item.Last);
412 Source.Last := Source.Last + New_Item.Last;
416 (Source : in out Unbounded_Wide_String;
417 New_Item : Wide_String)
420 Realloc_For_Chunk (Source, New_Item'Length);
421 Source.Reference (Source.Last + 1 .. Source.Last + New_Item'Length) :=
423 Source.Last := Source.Last + New_Item'Length;
427 (Source : in out Unbounded_Wide_String;
428 New_Item : Wide_Character)
431 Realloc_For_Chunk (Source, 1);
432 Source.Reference (Source.Last + 1) := New_Item;
433 Source.Last := Source.Last + 1;
441 (Source : Unbounded_Wide_String;
442 Pattern : Wide_String;
443 Mapping : Wide_Maps.Wide_Character_Mapping :=
448 return Wide_Search.Count
449 (Source.Reference (1 .. Source.Last), Pattern, Mapping);
453 (Source : Unbounded_Wide_String;
454 Pattern : Wide_String;
455 Mapping : Wide_Maps.Wide_Character_Mapping_Function)
459 return Wide_Search.Count
460 (Source.Reference (1 .. Source.Last), Pattern, Mapping);
464 (Source : Unbounded_Wide_String;
465 Set : Wide_Maps.Wide_Character_Set)
469 return Wide_Search.Count (Source.Reference (1 .. Source.Last), Set);
477 (Source : Unbounded_Wide_String;
480 return Unbounded_Wide_String
483 return To_Unbounded_Wide_String
485 (Source.Reference (1 .. Source.Last), From, Through));
489 (Source : in out Unbounded_Wide_String;
494 if From > Through then
497 elsif From < Source.Reference'First or else Through > Source.Last then
502 Len : constant Natural := Through - From + 1;
505 Source.Reference (From .. Source.Last - Len) :=
506 Source.Reference (Through + 1 .. Source.Last);
507 Source.Last := Source.Last - Len;
517 (Source : Unbounded_Wide_String;
519 return Wide_Character
522 if Index <= Source.Last then
523 return Source.Reference (Index);
525 raise Strings.Index_Error;
533 procedure Finalize (Object : in out Unbounded_Wide_String) is
534 procedure Deallocate is
535 new Ada.Unchecked_Deallocation (Wide_String, Wide_String_Access);
538 -- Note: Don't try to free statically allocated null string
540 if Object.Reference /= Null_Wide_String'Access then
541 Deallocate (Object.Reference);
542 Object.Reference := Null_Unbounded_Wide_String.Reference;
551 (Source : Unbounded_Wide_String;
552 Set : Wide_Maps.Wide_Character_Set;
553 Test : Strings.Membership;
554 First : out Positive;
558 Wide_Search.Find_Token
559 (Source.Reference (1 .. Source.Last), Set, Test, First, Last);
566 procedure Free (X : in out Wide_String_Access) is
567 procedure Deallocate is
568 new Ada.Unchecked_Deallocation (Wide_String, Wide_String_Access);
570 -- Note: Do not try to free statically allocated null string
572 if X /= Null_Unbounded_Wide_String.Reference then
582 (Source : Unbounded_Wide_String;
584 Pad : Wide_Character := Wide_Space)
585 return Unbounded_Wide_String
589 To_Unbounded_Wide_String
590 (Wide_Fixed.Head (Source.Reference (1 .. Source.Last), Count, Pad));
594 (Source : in out Unbounded_Wide_String;
596 Pad : Wide_Character := Wide_Space)
598 Old : Wide_String_Access := Source.Reference;
601 Source.Reference := new Wide_String'
602 (Wide_Fixed
.Head
(Source
.Reference
(1 .. Source
.Last
), Count
, Pad
));
603 Source
.Last
:= Source
.Reference
'Length;
612 (Source
: Unbounded_Wide_String
;
613 Pattern
: Wide_String;
614 Going
: Strings
.Direction
:= Strings
.Forward
;
615 Mapping
: Wide_Maps
.Wide_Character_Mapping
:=
620 return Wide_Search
.Index
621 (Source
.Reference
(1 .. Source
.Last
), Pattern
, Going
, Mapping
);
625 (Source
: Unbounded_Wide_String
;
626 Pattern
: Wide_String;
627 Going
: Direction
:= Forward
;
628 Mapping
: Wide_Maps
.Wide_Character_Mapping_Function
)
632 return Wide_Search
.Index
633 (Source
.Reference
(1 .. Source
.Last
), Pattern
, Going
, Mapping
);
637 (Source
: Unbounded_Wide_String
;
638 Set
: Wide_Maps
.Wide_Character_Set
;
639 Test
: Strings
.Membership
:= Strings
.Inside
;
640 Going
: Strings
.Direction
:= Strings
.Forward
)
644 return Wide_Search
.Index
645 (Source
.Reference
(1 .. Source
.Last
), Set
, Test
, Going
);
648 function Index_Non_Blank
649 (Source
: Unbounded_Wide_String
;
650 Going
: Strings
.Direction
:= Strings
.Forward
)
654 return Wide_Search
.Index_Non_Blank
655 (Source
.Reference
(1 .. Source
.Last
), Going
);
662 procedure Initialize
(Object
: in out Unbounded_Wide_String
) is
664 Object
.Reference
:= Null_Unbounded_Wide_String
.Reference
;
673 (Source
: Unbounded_Wide_String
;
675 New_Item
: Wide_String)
676 return Unbounded_Wide_String
679 return To_Unbounded_Wide_String
681 (Source
.Reference
(1 .. Source
.Last
), Before
, New_Item
));
685 (Source
: in out Unbounded_Wide_String
;
687 New_Item
: Wide_String)
690 if Before
not in Source
.Reference
'First .. Source
.Last
+ 1 then
694 Realloc_For_Chunk
(Source
, New_Item
'Size);
697 (Before
+ New_Item
'Length .. Source
.Last
+ New_Item
'Length) :=
698 Source
.Reference
(Before
.. Source
.Last
);
700 Source
.Reference
(Before
.. Before
+ New_Item
'Length - 1) := New_Item
;
701 Source
.Last
:= Source
.Last
+ New_Item
'Length;
708 function Length
(Source
: Unbounded_Wide_String
) return Natural is
718 (Source
: Unbounded_Wide_String
;
720 New_Item
: Wide_String)
721 return Unbounded_Wide_String
is
724 return To_Unbounded_Wide_String
725 (Wide_Fixed
.Overwrite
726 (Source
.Reference
(1 .. Source
.Last
), Position
, New_Item
));
730 (Source
: in out Unbounded_Wide_String
;
732 New_Item
: Wide_String)
734 NL
: constant Natural := New_Item
'Length;
737 if Position
<= Source
.Last
- NL
+ 1 then
738 Source
.Reference
(Position
.. Position
+ NL
- 1) := New_Item
;
742 Old
: Wide_String_Access
:= Source
.Reference
;
745 Source
.Reference
:= new Wide_String'
746 (Wide_Fixed.Overwrite
747 (Source.Reference (1 .. Source.Last), Position, New_Item));
748 Source.Last := Source.Reference'Length;
754 -----------------------
755 -- Realloc_For_Chunk --
756 -----------------------
758 procedure Realloc_For_Chunk
759 (Source : in out Unbounded_Wide_String;
760 Chunk_Size : Natural)
762 Growth_Factor : constant := 50;
763 S_Length : constant Natural := Source.Reference'Length;
766 if Chunk_Size > S_Length - Source.Last then
768 Alloc_Chunk_Size : constant Positive :=
769 Chunk_Size + (S_Length / Growth_Factor);
770 Tmp : Wide_String_Access;
773 Tmp := new Wide_String (1 .. S_Length + Alloc_Chunk_Size);
774 Tmp (1 .. Source.Last) := Source.Reference (1 .. Source.Last);
775 Free (Source.Reference);
776 Source.Reference := Tmp;
779 end Realloc_For_Chunk;
781 ---------------------
782 -- Replace_Element --
783 ---------------------
785 procedure Replace_Element
786 (Source : in out Unbounded_Wide_String;
791 if Index <= Source.Last then
792 Source.Reference (Index) := By;
794 raise Strings.Index_Error;
802 function Replace_Slice
803 (Source : Unbounded_Wide_String;
807 return Unbounded_Wide_String
811 To_Unbounded_Wide_String
812 (Wide_Fixed.Replace_Slice
813 (Source.Reference (1 .. Source.Last), Low, High, By));
816 procedure Replace_Slice
817 (Source : in out Unbounded_Wide_String;
822 Old : Wide_String_Access := Source.Reference;
825 Source.Reference := new Wide_String'
826 (Wide_Fixed
.Replace_Slice
827 (Source
.Reference
(1 .. Source
.Last
), Low
, High
, By
));
828 Source
.Last
:= Source
.Reference
'Length;
837 (Source
: Unbounded_Wide_String
;
843 -- Note: test of High > Length is in accordance with AI95-00128
845 if Low
> Source
.Last
+ 1 or else High
> Source
.Last
then
849 return Source
.Reference
(Low
.. High
);
858 (Source
: Unbounded_Wide_String
;
860 Pad
: Wide_Character := Wide_Space
)
861 return Unbounded_Wide_String
is
864 return To_Unbounded_Wide_String
865 (Wide_Fixed
.Tail
(Source
.Reference
(1 .. Source
.Last
), Count
, Pad
));
869 (Source
: in out Unbounded_Wide_String
;
871 Pad
: Wide_Character := Wide_Space
)
873 Old
: Wide_String_Access
:= Source
.Reference
;
876 Source
.Reference
:= new Wide_String'
877 (Wide_Fixed.Tail (Source.Reference (1 .. Source.Last), Count, Pad));
878 Source.Last := Source.Reference'Length;
882 ------------------------------
883 -- To_Unbounded_Wide_String --
884 ------------------------------
886 function To_Unbounded_Wide_String
887 (Source : Wide_String)
888 return Unbounded_Wide_String
890 Result : Unbounded_Wide_String;
893 Result.Last := Source'Length;
894 Result.Reference := new Wide_String (1 .. Source'Length);
895 Result.Reference.all := Source;
897 end To_Unbounded_Wide_String;
899 function To_Unbounded_Wide_String (Length : Natural)
900 return Unbounded_Wide_String
902 Result : Unbounded_Wide_String;
905 Result.Last := Length;
906 Result.Reference := new Wide_String (1 .. Length);
908 end To_Unbounded_Wide_String;
914 function To_Wide_String
915 (Source : Unbounded_Wide_String)
919 return Source.Reference (1 .. Source.Last);
927 (Source : Unbounded_Wide_String;
928 Mapping : Wide_Maps.Wide_Character_Mapping)
929 return Unbounded_Wide_String
932 return To_Unbounded_Wide_String
933 (Wide_Fixed.Translate (Source.Reference (1 .. Source.Last), Mapping));
937 (Source : in out Unbounded_Wide_String;
938 Mapping : Wide_Maps.Wide_Character_Mapping)
941 Wide_Fixed.Translate (Source.Reference (1 .. Source.Last), Mapping);
945 (Source : Unbounded_Wide_String;
946 Mapping : Wide_Maps.Wide_Character_Mapping_Function)
947 return Unbounded_Wide_String
950 return To_Unbounded_Wide_String
951 (Wide_Fixed.Translate (Source.Reference (1 .. Source.Last), Mapping));
955 (Source : in out Unbounded_Wide_String;
956 Mapping : Wide_Maps.Wide_Character_Mapping_Function)
959 Wide_Fixed.Translate (Source.Reference (1 .. Source.Last), Mapping);
967 (Source : Unbounded_Wide_String;
969 return Unbounded_Wide_String
972 return To_Unbounded_Wide_String
973 (Wide_Fixed.Trim (Source.Reference (1 .. Source.Last), Side));
977 (Source : in out Unbounded_Wide_String;
980 Old : Wide_String_Access := Source.Reference;
982 Source.Reference := new Wide_String'
983 (Wide_Fixed
.Trim
(Source
.Reference
(1 .. Source
.Last
), Side
));
984 Source
.Last
:= Source
.Reference
'Length;
989 (Source
: Unbounded_Wide_String
;
990 Left
: Wide_Maps
.Wide_Character_Set
;
991 Right
: Wide_Maps
.Wide_Character_Set
)
992 return Unbounded_Wide_String
995 return To_Unbounded_Wide_String
996 (Wide_Fixed
.Trim
(Source
.Reference
(1 .. Source
.Last
), Left
, Right
));
1000 (Source
: in out Unbounded_Wide_String
;
1001 Left
: Wide_Maps
.Wide_Character_Set
;
1002 Right
: Wide_Maps
.Wide_Character_Set
)
1004 Old
: Wide_String_Access
:= Source
.Reference
;
1007 Source
.Reference
:= new Wide_String'
1008 (Wide_Fixed.Trim (Source.Reference (1 .. Source.Last), Left, Right));
1009 Source.Last := Source.Reference'Length;
1013 end Ada.Strings.Wide_Unbounded;