1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- A D A . S T R I N G S . W I D E _ W I D E _ U N B O U N D E D --
9 -- Copyright (C) 1992-2011, 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 3, 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. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 with Ada.Strings.Wide_Wide_Search;
33 with Ada.Unchecked_Deallocation;
35 package body Ada.Strings.Wide_Wide_Unbounded is
37 use Ada.Strings.Wide_Wide_Maps;
39 Growth_Factor : constant := 32;
40 -- The growth factor controls how much extra space is allocated when
41 -- we have to increase the size of an allocated unbounded string. By
42 -- allocating extra space, we avoid the need to reallocate on every
43 -- append, particularly important when a string is built up by repeated
44 -- append operations of small pieces. This is expressed as a factor so
45 -- 32 means add 1/32 of the length of the string as growth space.
47 Min_Mul_Alloc : constant := Standard'Maximum_Alignment;
48 -- Allocation will be done by a multiple of Min_Mul_Alloc. This causes
49 -- no memory loss as most (all?) malloc implementations are obliged to
50 -- align the returned memory on the maximum alignment as malloc does not
51 -- know the target alignment.
53 function Aligned_Max_Length (Max_Length : Natural) return Natural;
54 -- Returns recommended length of the shared string which is greater or
55 -- equal to specified length. Calculation take in sense alignment of
56 -- the allocated memory segments to use memory effectively by
57 -- Append/Insert/etc operations.
64 (Left : Unbounded_Wide_Wide_String;
65 Right : Unbounded_Wide_Wide_String) return Unbounded_Wide_Wide_String
67 LR : constant Shared_Wide_Wide_String_Access := Left.Reference;
68 RR : constant Shared_Wide_Wide_String_Access := Right.Reference;
69 DL : constant Natural := LR.Last + RR.Last;
70 DR : Shared_Wide_Wide_String_Access;
73 -- Result is an empty string, reuse shared empty string
76 Reference (Empty_Shared_Wide_Wide_String'Access);
77 DR := Empty_Shared_Wide_Wide_String'Access;
79 -- Left string is empty, return Rigth string
81 elsif LR.Last = 0 then
85 -- Right string is empty, return Left string
87 elsif RR.Last = 0 then
91 -- Overwise, allocate new shared string and fill data
94 DR := Allocate (LR.Last + RR.Last);
95 DR.Data (1 .. LR.Last) := LR.Data (1 .. LR.Last);
96 DR.Data (LR.Last + 1 .. DL) := RR.Data (1 .. RR.Last);
100 return (AF.Controlled with Reference => DR);
104 (Left : Unbounded_Wide_Wide_String;
105 Right : Wide_Wide_String) return Unbounded_Wide_Wide_String
107 LR : constant Shared_Wide_Wide_String_Access := Left.Reference;
108 DL : constant Natural := LR.Last + Right'Length;
109 DR : Shared_Wide_Wide_String_Access;
112 -- Result is an empty string, reuse shared empty string
115 Reference (Empty_Shared_Wide_Wide_String'Access);
116 DR := Empty_Shared_Wide_Wide_String'Access;
118 -- Right is an empty string, return Left string
120 elsif Right'Length = 0 then
124 -- Otherwise, allocate new shared string and fill it
128 DR.Data (1 .. LR.Last) := LR.Data (1 .. LR.Last);
129 DR.Data (LR.Last + 1 .. DL) := Right;
133 return (AF.Controlled with Reference => DR);
137 (Left : Wide_Wide_String;
138 Right : Unbounded_Wide_Wide_String) return Unbounded_Wide_Wide_String
140 RR : constant Shared_Wide_Wide_String_Access := Right.Reference;
141 DL : constant Natural := Left'Length + RR.Last;
142 DR : Shared_Wide_Wide_String_Access;
145 -- Result is an empty string, reuse shared one
148 Reference (Empty_Shared_Wide_Wide_String'Access);
149 DR := Empty_Shared_Wide_Wide_String'Access;
151 -- Left is empty string, return Right string
153 elsif Left'Length = 0 then
157 -- Otherwise, allocate new shared string and fill it
161 DR.Data (1 .. Left'Length) := Left;
162 DR.Data (Left'Length + 1 .. DL) := RR.Data (1 .. RR.Last);
166 return (AF.Controlled with Reference => DR);
170 (Left : Unbounded_Wide_Wide_String;
171 Right : Wide_Wide_Character) return Unbounded_Wide_Wide_String
173 LR : constant Shared_Wide_Wide_String_Access := Left.Reference;
174 DL : constant Natural := LR.Last + 1;
175 DR : Shared_Wide_Wide_String_Access;
179 DR.Data (1 .. LR.Last) := LR.Data (1 .. LR.Last);
180 DR.Data (DL) := Right;
183 return (AF.Controlled with Reference => DR);
187 (Left : Wide_Wide_Character;
188 Right : Unbounded_Wide_Wide_String) return Unbounded_Wide_Wide_String
190 RR : constant Shared_Wide_Wide_String_Access := Right.Reference;
191 DL : constant Natural := 1 + RR.Last;
192 DR : Shared_Wide_Wide_String_Access;
197 DR.Data (2 .. DL) := RR.Data (1 .. RR.Last);
200 return (AF.Controlled with Reference => DR);
209 Right : Wide_Wide_Character) return Unbounded_Wide_Wide_String
211 DR : Shared_Wide_Wide_String_Access;
214 -- Result is an empty string, reuse shared empty string
217 Reference (Empty_Shared_Wide_Wide_String'Access);
218 DR := Empty_Shared_Wide_Wide_String'Access;
220 -- Otherwise, allocate new shared string and fill it
223 DR := Allocate (Left);
225 for J in 1 .. Left loop
226 DR.Data (J) := Right;
232 return (AF.Controlled with Reference => DR);
237 Right : Wide_Wide_String) return Unbounded_Wide_Wide_String
239 DL : constant Natural := Left * Right'Length;
240 DR : Shared_Wide_Wide_String_Access;
244 -- Result is an empty string, reuse shared empty string
247 Reference (Empty_Shared_Wide_Wide_String'Access);
248 DR := Empty_Shared_Wide_Wide_String'Access;
250 -- Otherwise, allocate new shared string and fill it
256 for J in 1 .. Left loop
257 DR.Data (K .. K + Right'Length - 1) := Right;
258 K := K + Right'Length;
264 return (AF.Controlled with Reference => DR);
269 Right : Unbounded_Wide_Wide_String) return Unbounded_Wide_Wide_String
271 RR : constant Shared_Wide_Wide_String_Access := Right.Reference;
272 DL : constant Natural := Left * RR.Last;
273 DR : Shared_Wide_Wide_String_Access;
277 -- Result is an empty string, reuse shared empty string
280 Reference (Empty_Shared_Wide_Wide_String'Access);
281 DR := Empty_Shared_Wide_Wide_String'Access;
283 -- Coefficient is one, just return string itself
289 -- Otherwise, allocate new shared string and fill it
295 for J in 1 .. Left loop
296 DR.Data (K .. K + RR.Last - 1) := RR.Data (1 .. RR.Last);
303 return (AF.Controlled with Reference => DR);
311 (Left : Unbounded_Wide_Wide_String;
312 Right : Unbounded_Wide_Wide_String) return Boolean
314 LR : constant Shared_Wide_Wide_String_Access := Left.Reference;
315 RR : constant Shared_Wide_Wide_String_Access := Right.Reference;
317 return LR.Data (1 .. LR.Last) < RR.Data (1 .. RR.Last);
321 (Left : Unbounded_Wide_Wide_String;
322 Right : Wide_Wide_String) return Boolean
324 LR : constant Shared_Wide_Wide_String_Access := Left.Reference;
326 return LR.Data (1 .. LR.Last) < Right;
330 (Left : Wide_Wide_String;
331 Right : Unbounded_Wide_Wide_String) return Boolean
333 RR : constant Shared_Wide_Wide_String_Access := Right.Reference;
335 return Left < RR.Data (1 .. RR.Last);
343 (Left : Unbounded_Wide_Wide_String;
344 Right : Unbounded_Wide_Wide_String) return Boolean
346 LR : constant Shared_Wide_Wide_String_Access := Left.Reference;
347 RR : constant Shared_Wide_Wide_String_Access := Right.Reference;
350 -- LR = RR means two strings shares shared string, thus they are equal
352 return LR = RR or else LR.Data (1 .. LR.Last) <= RR.Data (1 .. RR.Last);
356 (Left : Unbounded_Wide_Wide_String;
357 Right : Wide_Wide_String) return Boolean
359 LR : constant Shared_Wide_Wide_String_Access := Left.Reference;
361 return LR.Data (1 .. LR.Last) <= Right;
365 (Left : Wide_Wide_String;
366 Right : Unbounded_Wide_Wide_String) return Boolean
368 RR : constant Shared_Wide_Wide_String_Access := Right.Reference;
370 return Left <= RR.Data (1 .. RR.Last);
378 (Left : Unbounded_Wide_Wide_String;
379 Right : Unbounded_Wide_Wide_String) return Boolean
381 LR : constant Shared_Wide_Wide_String_Access := Left.Reference;
382 RR : constant Shared_Wide_Wide_String_Access := Right.Reference;
385 return LR = RR or else LR.Data (1 .. LR.Last) = RR.Data (1 .. RR.Last);
386 -- LR = RR means two strings shares shared string, thus they are equal
390 (Left : Unbounded_Wide_Wide_String;
391 Right : Wide_Wide_String) return Boolean
393 LR : constant Shared_Wide_Wide_String_Access := Left.Reference;
395 return LR.Data (1 .. LR.Last) = Right;
399 (Left : Wide_Wide_String;
400 Right : Unbounded_Wide_Wide_String) return Boolean
402 RR : constant Shared_Wide_Wide_String_Access := Right.Reference;
404 return Left = RR.Data (1 .. RR.Last);
412 (Left : Unbounded_Wide_Wide_String;
413 Right : Unbounded_Wide_Wide_String) return Boolean
415 LR : constant Shared_Wide_Wide_String_Access := Left.Reference;
416 RR : constant Shared_Wide_Wide_String_Access := Right.Reference;
418 return LR.Data (1 .. LR.Last) > RR.Data (1 .. RR.Last);
422 (Left : Unbounded_Wide_Wide_String;
423 Right : Wide_Wide_String) return Boolean
425 LR : constant Shared_Wide_Wide_String_Access := Left.Reference;
427 return LR.Data (1 .. LR.Last) > Right;
431 (Left : Wide_Wide_String;
432 Right : Unbounded_Wide_Wide_String) return Boolean
434 RR : constant Shared_Wide_Wide_String_Access := Right.Reference;
436 return Left > RR.Data (1 .. RR.Last);
444 (Left : Unbounded_Wide_Wide_String;
445 Right : Unbounded_Wide_Wide_String) return Boolean
447 LR : constant Shared_Wide_Wide_String_Access := Left.Reference;
448 RR : constant Shared_Wide_Wide_String_Access := Right.Reference;
451 -- LR = RR means two strings shares shared string, thus they are equal
453 return LR = RR or else LR.Data (1 .. LR.Last) >= RR.Data (1 .. RR.Last);
457 (Left : Unbounded_Wide_Wide_String;
458 Right : Wide_Wide_String) return Boolean
460 LR : constant Shared_Wide_Wide_String_Access := Left.Reference;
462 return LR.Data (1 .. LR.Last) >= Right;
466 (Left : Wide_Wide_String;
467 Right : Unbounded_Wide_Wide_String) return Boolean
469 RR : constant Shared_Wide_Wide_String_Access := Right.Reference;
471 return Left >= RR.Data (1 .. RR.Last);
478 procedure Adjust (Object : in out Unbounded_Wide_Wide_String) is
480 Reference (Object.Reference);
483 ------------------------
484 -- Aligned_Max_Length --
485 ------------------------
487 function Aligned_Max_Length (Max_Length : Natural) return Natural is
488 Static_Size : constant Natural :=
489 Empty_Shared_Wide_Wide_String'Size
490 / Standard'Storage_Unit;
491 -- Total size of all static components
493 Element_Size : constant Natural :=
494 Wide_Wide_Character'Size / Standard'Storage_Unit;
498 (((Static_Size + Max_Length * Element_Size - 1) / Min_Mul_Alloc + 2)
499 * Min_Mul_Alloc - Static_Size) / Element_Size;
500 end Aligned_Max_Length;
507 (Max_Length : Natural) return Shared_Wide_Wide_String_Access is
509 -- Empty string requested, return shared empty string
511 if Max_Length = 0 then
512 Reference (Empty_Shared_Wide_Wide_String'Access);
513 return Empty_Shared_Wide_Wide_String'Access;
515 -- Otherwise, allocate requested space (and probably some more room)
518 return new Shared_Wide_Wide_String (Aligned_Max_Length (Max_Length));
527 (Source : in out Unbounded_Wide_Wide_String;
528 New_Item : Unbounded_Wide_Wide_String)
530 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
531 NR : constant Shared_Wide_Wide_String_Access := New_Item.Reference;
532 DL : constant Natural := SR.Last + NR.Last;
533 DR : Shared_Wide_Wide_String_Access;
536 -- Source is an empty string, reuse New_Item data
540 Source.Reference := NR;
543 -- New_Item is empty string, nothing to do
545 elsif NR.Last = 0 then
548 -- Try to reuse existent shared string
550 elsif Can_Be_Reused (SR, DL) then
551 SR.Data (SR.Last + 1 .. DL) := NR.Data (1 .. NR.Last);
554 -- Otherwise, allocate new one and fill it
557 DR := Allocate (DL + DL / Growth_Factor);
558 DR.Data (1 .. SR.Last) := SR.Data (1 .. SR.Last);
559 DR.Data (SR.Last + 1 .. DL) := NR.Data (1 .. NR.Last);
561 Source.Reference := DR;
567 (Source : in out Unbounded_Wide_Wide_String;
568 New_Item : Wide_Wide_String)
570 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
571 DL : constant Natural := SR.Last + New_Item'Length;
572 DR : Shared_Wide_Wide_String_Access;
575 -- New_Item is an empty string, nothing to do
577 if New_Item'Length = 0 then
580 -- Try to reuse existing shared string
582 elsif Can_Be_Reused (SR, DL) then
583 SR.Data (SR.Last + 1 .. DL) := New_Item;
586 -- Otherwise, allocate new one and fill it
589 DR := Allocate (DL + DL / Growth_Factor);
590 DR.Data (1 .. SR.Last) := SR.Data (1 .. SR.Last);
591 DR.Data (SR.Last + 1 .. DL) := New_Item;
593 Source.Reference := DR;
599 (Source : in out Unbounded_Wide_Wide_String;
600 New_Item : Wide_Wide_Character)
602 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
603 DL : constant Natural := SR.Last + 1;
604 DR : Shared_Wide_Wide_String_Access;
607 -- Try to reuse existing shared string
609 if Can_Be_Reused (SR, SR.Last + 1) then
610 SR.Data (SR.Last + 1) := New_Item;
611 SR.Last := SR.Last + 1;
613 -- Otherwise, allocate new one and fill it
616 DR := Allocate (DL + DL / Growth_Factor);
617 DR.Data (1 .. SR.Last) := SR.Data (1 .. SR.Last);
618 DR.Data (DL) := New_Item;
620 Source.Reference := DR;
629 function Can_Be_Reused
630 (Item : Shared_Wide_Wide_String_Access;
631 Length : Natural) return Boolean is
634 System.Atomic_Counters.Is_One (Item.Counter)
635 and then Item.Max_Length >= Length
636 and then Item.Max_Length <=
637 Aligned_Max_Length (Length + Length / Growth_Factor);
645 (Source : Unbounded_Wide_Wide_String;
646 Pattern : Wide_Wide_String;
647 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping :=
648 Wide_Wide_Maps.Identity)
651 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
653 return Wide_Wide_Search.Count (SR.Data (1 .. SR.Last), Pattern, Mapping);
657 (Source : Unbounded_Wide_Wide_String;
658 Pattern : Wide_Wide_String;
659 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping_Function)
662 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
664 return Wide_Wide_Search.Count (SR.Data (1 .. SR.Last), Pattern, Mapping);
668 (Source : Unbounded_Wide_Wide_String;
669 Set : Wide_Wide_Maps.Wide_Wide_Character_Set) return Natural
671 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
673 return Wide_Wide_Search.Count (SR.Data (1 .. SR.Last), Set);
681 (Source : Unbounded_Wide_Wide_String;
683 Through : Natural) return Unbounded_Wide_Wide_String
685 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
687 DR : Shared_Wide_Wide_String_Access;
690 -- Empty slice is deleted, use the same shared string
692 if From > Through then
696 -- Index is out of range
698 elsif Through > SR.Last then
701 -- Compute size of the result
704 DL := SR.Last - (Through - From + 1);
706 -- Result is an empty string, reuse shared empty string
709 Reference (Empty_Shared_Wide_Wide_String'Access);
710 DR := Empty_Shared_Wide_Wide_String'Access;
712 -- Otherwise, allocate new shared string and fill it
716 DR.Data (1 .. From - 1) := SR.Data (1 .. From - 1);
717 DR.Data (From .. DL) := SR.Data (Through + 1 .. SR.Last);
722 return (AF.Controlled with Reference => DR);
726 (Source : in out Unbounded_Wide_Wide_String;
730 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
732 DR : Shared_Wide_Wide_String_Access;
735 -- Nothing changed, return
737 if From > Through then
740 -- Through is outside of the range
742 elsif Through > SR.Last then
746 DL := SR.Last - (Through - From + 1);
748 -- Result is empty, reuse shared empty string
751 Reference (Empty_Shared_Wide_Wide_String'Access);
752 Source.Reference := Empty_Shared_Wide_Wide_String'Access;
755 -- Try to reuse existent shared string
757 elsif Can_Be_Reused (SR, DL) then
758 SR.Data (From .. DL) := SR.Data (Through + 1 .. SR.Last);
761 -- Otherwise, allocate new shared string
765 DR.Data (1 .. From - 1) := SR.Data (1 .. From - 1);
766 DR.Data (From .. DL) := SR.Data (Through + 1 .. SR.Last);
768 Source.Reference := DR;
779 (Source : Unbounded_Wide_Wide_String;
780 Index : Positive) return Wide_Wide_Character
782 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
784 if Index <= SR.Last then
785 return SR.Data (Index);
795 procedure Finalize (Object : in out Unbounded_Wide_Wide_String) is
796 SR : constant Shared_Wide_Wide_String_Access := Object.Reference;
801 -- The same controlled object can be finalized several times for
802 -- some reason. As per 7.6.1(24) this should have no ill effect,
803 -- so we need to add a guard for the case of finalizing the same
806 Object.Reference := null;
816 (Source : Unbounded_Wide_Wide_String;
817 Set : Wide_Wide_Maps.Wide_Wide_Character_Set;
819 Test : Strings.Membership;
820 First : out Positive;
823 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
825 Wide_Wide_Search.Find_Token
826 (SR.Data (From .. SR.Last), Set, Test, First, Last);
830 (Source : Unbounded_Wide_Wide_String;
831 Set : Wide_Wide_Maps.Wide_Wide_Character_Set;
832 Test : Strings.Membership;
833 First : out Positive;
836 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
838 Wide_Wide_Search.Find_Token
839 (SR.Data (1 .. SR.Last), Set, Test, First, Last);
846 procedure Free (X : in out Wide_Wide_String_Access) is
847 procedure Deallocate is
848 new Ada.Unchecked_Deallocation
849 (Wide_Wide_String, Wide_Wide_String_Access);
859 (Source : Unbounded_Wide_Wide_String;
861 Pad : Wide_Wide_Character := Wide_Wide_Space)
862 return Unbounded_Wide_Wide_String
864 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
865 DR : Shared_Wide_Wide_String_Access;
868 -- Result is empty, reuse shared empty string
871 Reference (Empty_Shared_Wide_Wide_String'Access);
872 DR := Empty_Shared_Wide_Wide_String'Access;
874 -- Length of the string is the same as requested, reuse source shared
877 elsif Count = SR.Last then
881 -- Otherwise, allocate new shared string and fill it
884 DR := Allocate (Count);
886 -- Length of the source string is more than requested, copy
887 -- corresponding slice.
889 if Count < SR.Last then
890 DR.Data (1 .. Count) := SR.Data (1 .. Count);
892 -- Length of the source string is less then requested, copy all
893 -- contents and fill others by Pad character.
896 DR.Data (1 .. SR.Last) := SR.Data (1 .. SR.Last);
898 for J in SR.Last + 1 .. Count loop
906 return (AF.Controlled with Reference => DR);
910 (Source : in out Unbounded_Wide_Wide_String;
912 Pad : Wide_Wide_Character := Wide_Wide_Space)
914 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
915 DR : Shared_Wide_Wide_String_Access;
918 -- Result is empty, reuse empty shared string
921 Reference (Empty_Shared_Wide_Wide_String'Access);
922 Source.Reference := Empty_Shared_Wide_Wide_String'Access;
925 -- Result is same with source string, reuse source shared string
927 elsif Count = SR.Last then
930 -- Try to reuse existent shared string
932 elsif Can_Be_Reused (SR, Count) then
933 if Count > SR.Last then
934 for J in SR.Last + 1 .. Count loop
941 -- Otherwise, allocate new shared string and fill it
944 DR := Allocate (Count);
946 -- Length of the source string is greater then requested, copy
947 -- corresponding slice.
949 if Count < SR.Last then
950 DR.Data (1 .. Count) := SR.Data (1 .. Count);
952 -- Length of the source string is less the requested, copy all
953 -- exists data and fill others by Pad character.
956 DR.Data (1 .. SR.Last) := SR.Data (1 .. SR.Last);
958 for J in SR.Last + 1 .. Count loop
964 Source.Reference := DR;
974 (Source : Unbounded_Wide_Wide_String;
975 Pattern : Wide_Wide_String;
976 Going : Strings.Direction := Strings.Forward;
977 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping :=
978 Wide_Wide_Maps.Identity)
981 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
983 return Wide_Wide_Search.Index
984 (SR.Data (1 .. SR.Last), Pattern, Going, Mapping);
988 (Source : Unbounded_Wide_Wide_String;
989 Pattern : Wide_Wide_String;
990 Going : Direction := Forward;
991 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping_Function)
994 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
996 return Wide_Wide_Search.Index
997 (SR.Data (1 .. SR.Last), Pattern, Going, Mapping);
1001 (Source : Unbounded_Wide_Wide_String;
1002 Set : Wide_Wide_Maps.Wide_Wide_Character_Set;
1003 Test : Strings.Membership := Strings.Inside;
1004 Going : Strings.Direction := Strings.Forward) return Natural
1006 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1008 return Wide_Wide_Search.Index (SR.Data (1 .. SR.Last), Set, Test, Going);
1012 (Source : Unbounded_Wide_Wide_String;
1013 Pattern : Wide_Wide_String;
1015 Going : Direction := Forward;
1016 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping :=
1017 Wide_Wide_Maps.Identity)
1020 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1022 return Wide_Wide_Search.Index
1023 (SR.Data (1 .. SR.Last), Pattern, From, Going, Mapping);
1027 (Source : Unbounded_Wide_Wide_String;
1028 Pattern : Wide_Wide_String;
1030 Going : Direction := Forward;
1031 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping_Function)
1034 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1036 return Wide_Wide_Search.Index
1037 (SR.Data (1 .. SR.Last), Pattern, From, Going, Mapping);
1041 (Source : Unbounded_Wide_Wide_String;
1042 Set : Wide_Wide_Maps.Wide_Wide_Character_Set;
1044 Test : Membership := Inside;
1045 Going : Direction := Forward) return Natural
1047 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1049 return Wide_Wide_Search.Index
1050 (SR.Data (1 .. SR.Last), Set, From, Test, Going);
1053 ---------------------
1054 -- Index_Non_Blank --
1055 ---------------------
1057 function Index_Non_Blank
1058 (Source : Unbounded_Wide_Wide_String;
1059 Going : Strings.Direction := Strings.Forward) return Natural
1061 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1063 return Wide_Wide_Search.Index_Non_Blank (SR.Data (1 .. SR.Last), Going);
1064 end Index_Non_Blank;
1066 function Index_Non_Blank
1067 (Source : Unbounded_Wide_Wide_String;
1069 Going : Direction := Forward) return Natural
1071 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1073 return Wide_Wide_Search.Index_Non_Blank
1074 (SR.Data (1 .. SR.Last), From, Going);
1075 end Index_Non_Blank;
1081 procedure Initialize (Object : in out Unbounded_Wide_Wide_String) is
1083 Reference (Object.Reference);
1091 (Source : Unbounded_Wide_Wide_String;
1093 New_Item : Wide_Wide_String) return Unbounded_Wide_Wide_String
1095 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1096 DL : constant Natural := SR.Last + New_Item'Length;
1097 DR : Shared_Wide_Wide_String_Access;
1100 -- Check index first
1102 if Before > SR.Last + 1 then
1106 -- Result is empty, reuse empty shared string
1109 Reference (Empty_Shared_Wide_Wide_String'Access);
1110 DR := Empty_Shared_Wide_Wide_String'Access;
1112 -- Inserted string is empty, reuse source shared string
1114 elsif New_Item'Length = 0 then
1118 -- Otherwise, allocate new shared string and fill it
1121 DR := Allocate (DL + DL / Growth_Factor);
1122 DR.Data (1 .. Before - 1) := SR.Data (1 .. Before - 1);
1123 DR.Data (Before .. Before + New_Item'Length - 1) := New_Item;
1124 DR.Data (Before + New_Item'Length .. DL) :=
1125 SR.Data (Before .. SR.Last);
1129 return (AF.Controlled with Reference => DR);
1133 (Source : in out Unbounded_Wide_Wide_String;
1135 New_Item : Wide_Wide_String)
1137 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1138 DL : constant Natural := SR.Last + New_Item'Length;
1139 DR : Shared_Wide_Wide_String_Access;
1144 if Before > SR.Last + 1 then
1148 -- Result is empty string, reuse empty shared string
1151 Reference (Empty_Shared_Wide_Wide_String'Access);
1152 Source.Reference := Empty_Shared_Wide_Wide_String'Access;
1155 -- Inserted string is empty, nothing to do
1157 elsif New_Item'Length = 0 then
1160 -- Try to reuse existent shared string first
1162 elsif Can_Be_Reused (SR, DL) then
1163 SR.Data (Before + New_Item'Length .. DL) :=
1164 SR.Data (Before .. SR.Last);
1165 SR.Data (Before .. Before + New_Item'Length - 1) := New_Item;
1168 -- Otherwise, allocate new shared string and fill it
1171 DR := Allocate (DL + DL / Growth_Factor);
1172 DR.Data (1 .. Before - 1) := SR.Data (1 .. Before - 1);
1173 DR.Data (Before .. Before + New_Item'Length - 1) := New_Item;
1174 DR.Data (Before + New_Item'Length .. DL) :=
1175 SR.Data (Before .. SR.Last);
1177 Source.Reference := DR;
1186 function Length (Source : Unbounded_Wide_Wide_String) return Natural is
1188 return Source.Reference.Last;
1196 (Source : Unbounded_Wide_Wide_String;
1197 Position : Positive;
1198 New_Item : Wide_Wide_String) return Unbounded_Wide_Wide_String
1200 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1202 DR : Shared_Wide_Wide_String_Access;
1207 if Position > SR.Last + 1 then
1211 DL := Integer'Max (SR.Last, Position + New_Item'Length - 1);
1213 -- Result is empty string, reuse empty shared string
1216 Reference (Empty_Shared_Wide_Wide_String'Access);
1217 DR := Empty_Shared_Wide_Wide_String'Access;
1219 -- Result is same with source string, reuse source shared string
1221 elsif New_Item'Length = 0 then
1225 -- Otherwise, allocate new shared string and fill it
1228 DR := Allocate (DL);
1229 DR.Data (1 .. Position - 1) := SR.Data (1 .. Position - 1);
1230 DR.Data (Position .. Position + New_Item'Length - 1) := New_Item;
1231 DR.Data (Position + New_Item'Length .. DL) :=
1232 SR.Data (Position + New_Item'Length .. SR.Last);
1236 return (AF.Controlled with Reference => DR);
1240 (Source : in out Unbounded_Wide_Wide_String;
1241 Position : Positive;
1242 New_Item : Wide_Wide_String)
1244 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1246 DR : Shared_Wide_Wide_String_Access;
1251 if Position > SR.Last + 1 then
1255 DL := Integer'Max (SR.Last, Position + New_Item'Length - 1);
1257 -- Result is empty string, reuse empty shared string
1260 Reference (Empty_Shared_Wide_Wide_String'Access);
1261 Source.Reference := Empty_Shared_Wide_Wide_String'Access;
1264 -- String unchanged, nothing to do
1266 elsif New_Item'Length = 0 then
1269 -- Try to reuse existent shared string
1271 elsif Can_Be_Reused (SR, DL) then
1272 SR.Data (Position .. Position + New_Item'Length - 1) := New_Item;
1275 -- Otherwise allocate new shared string and fill it
1278 DR := Allocate (DL);
1279 DR.Data (1 .. Position - 1) := SR.Data (1 .. Position - 1);
1280 DR.Data (Position .. Position + New_Item'Length - 1) := New_Item;
1281 DR.Data (Position + New_Item'Length .. DL) :=
1282 SR.Data (Position + New_Item'Length .. SR.Last);
1284 Source.Reference := DR;
1293 procedure Reference (Item : not null Shared_Wide_Wide_String_Access) is
1295 System.Atomic_Counters.Increment (Item.Counter);
1298 ---------------------
1299 -- Replace_Element --
1300 ---------------------
1302 procedure Replace_Element
1303 (Source : in out Unbounded_Wide_Wide_String;
1305 By : Wide_Wide_Character)
1307 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1308 DR : Shared_Wide_Wide_String_Access;
1313 if Index <= SR.Last then
1315 -- Try to reuse existent shared string
1317 if Can_Be_Reused (SR, SR.Last) then
1318 SR.Data (Index) := By;
1320 -- Otherwise allocate new shared string and fill it
1323 DR := Allocate (SR.Last);
1324 DR.Data (1 .. SR.Last) := SR.Data (1 .. SR.Last);
1325 DR.Data (Index) := By;
1327 Source.Reference := DR;
1334 end Replace_Element;
1340 function Replace_Slice
1341 (Source : Unbounded_Wide_Wide_String;
1344 By : Wide_Wide_String) return Unbounded_Wide_Wide_String
1346 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1348 DR : Shared_Wide_Wide_String_Access;
1353 if Low > SR.Last + 1 then
1357 -- Do replace operation when removed slice is not empty
1360 DL := By'Length + SR.Last + Low - Integer'Min (High, SR.Last) - 1;
1361 -- This is the number of characters remaining in the string after
1362 -- replacing the slice.
1364 -- Result is empty string, reuse empty shared string
1367 Reference (Empty_Shared_Wide_Wide_String'Access);
1368 DR := Empty_Shared_Wide_Wide_String'Access;
1370 -- Otherwise allocate new shared string and fill it
1373 DR := Allocate (DL);
1374 DR.Data (1 .. Low - 1) := SR.Data (1 .. Low - 1);
1375 DR.Data (Low .. Low + By'Length - 1) := By;
1376 DR.Data (Low + By'Length .. DL) := SR.Data (High + 1 .. SR.Last);
1380 return (AF.Controlled with Reference => DR);
1382 -- Otherwise just insert string
1385 return Insert (Source, Low, By);
1389 procedure Replace_Slice
1390 (Source : in out Unbounded_Wide_Wide_String;
1393 By : Wide_Wide_String)
1395 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1397 DR : Shared_Wide_Wide_String_Access;
1402 if Low > SR.Last + 1 then
1406 -- Do replace operation only when replaced slice is not empty
1409 DL := By'Length + SR.Last + Low - Integer'Min (High, SR.Last) - 1;
1410 -- This is the number of characters remaining in the string after
1411 -- replacing the slice.
1413 -- Result is empty string, reuse empty shared string
1416 Reference (Empty_Shared_Wide_Wide_String'Access);
1417 Source.Reference := Empty_Shared_Wide_Wide_String'Access;
1420 -- Try to reuse existent shared string
1422 elsif Can_Be_Reused (SR, DL) then
1423 SR.Data (Low + By'Length .. DL) := SR.Data (High + 1 .. SR.Last);
1424 SR.Data (Low .. Low + By'Length - 1) := By;
1427 -- Otherwise allocate new shared string and fill it
1430 DR := Allocate (DL);
1431 DR.Data (1 .. Low - 1) := SR.Data (1 .. Low - 1);
1432 DR.Data (Low .. Low + By'Length - 1) := By;
1433 DR.Data (Low + By'Length .. DL) := SR.Data (High + 1 .. SR.Last);
1435 Source.Reference := DR;
1439 -- Otherwise just insert item
1442 Insert (Source, Low, By);
1446 -------------------------------
1447 -- Set_Unbounded_Wide_Wide_String --
1448 -------------------------------
1450 procedure Set_Unbounded_Wide_Wide_String
1451 (Target : out Unbounded_Wide_Wide_String;
1452 Source : Wide_Wide_String)
1454 TR : constant Shared_Wide_Wide_String_Access := Target.Reference;
1455 DR : Shared_Wide_Wide_String_Access;
1458 -- In case of empty string, reuse empty shared string
1460 if Source'Length = 0 then
1461 Reference (Empty_Shared_Wide_Wide_String'Access);
1462 Target.Reference := Empty_Shared_Wide_Wide_String'Access;
1465 -- Try to reuse existent shared string
1467 if Can_Be_Reused (TR, Source'Length) then
1471 -- Otherwise allocate new shared string
1474 DR := Allocate (Source'Length);
1475 Target.Reference := DR;
1478 DR.Data (1 .. Source'Length) := Source;
1479 DR.Last := Source'Length;
1483 end Set_Unbounded_Wide_Wide_String;
1490 (Source : Unbounded_Wide_Wide_String;
1492 High : Natural) return Wide_Wide_String
1494 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1497 -- Note: test of High > Length is in accordance with AI95-00128
1499 if Low > SR.Last + 1 or else High > SR.Last then
1503 return SR.Data (Low .. High);
1512 (Source : Unbounded_Wide_Wide_String;
1514 Pad : Wide_Wide_Character := Wide_Wide_Space)
1515 return Unbounded_Wide_Wide_String
1517 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1518 DR : Shared_Wide_Wide_String_Access;
1521 -- For empty result reuse empty shared string
1524 Reference (Empty_Shared_Wide_Wide_String'Access);
1525 DR := Empty_Shared_Wide_Wide_String'Access;
1527 -- Result is hole source string, reuse source shared string
1529 elsif Count = SR.Last then
1533 -- Otherwise allocate new shared string and fill it
1536 DR := Allocate (Count);
1538 if Count < SR.Last then
1539 DR.Data (1 .. Count) := SR.Data (SR.Last - Count + 1 .. SR.Last);
1542 for J in 1 .. Count - SR.Last loop
1546 DR.Data (Count - SR.Last + 1 .. Count) := SR.Data (1 .. SR.Last);
1552 return (AF.Controlled with Reference => DR);
1556 (Source : in out Unbounded_Wide_Wide_String;
1558 Pad : Wide_Wide_Character := Wide_Wide_Space)
1560 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1561 DR : Shared_Wide_Wide_String_Access;
1564 (SR : Shared_Wide_Wide_String_Access;
1565 DR : Shared_Wide_Wide_String_Access;
1567 -- Common code of tail computation. SR/DR can point to the same object
1574 (SR : Shared_Wide_Wide_String_Access;
1575 DR : Shared_Wide_Wide_String_Access;
1578 if Count < SR.Last then
1579 DR.Data (1 .. Count) := SR.Data (SR.Last - Count + 1 .. SR.Last);
1582 DR.Data (Count - SR.Last + 1 .. Count) := SR.Data (1 .. SR.Last);
1584 for J in 1 .. Count - SR.Last loop
1593 -- Result is empty string, reuse empty shared string
1596 Reference (Empty_Shared_Wide_Wide_String'Access);
1597 Source.Reference := Empty_Shared_Wide_Wide_String'Access;
1600 -- Length of the result is the same with length of the source string,
1601 -- reuse source shared string.
1603 elsif Count = SR.Last then
1606 -- Try to reuse existent shared string
1608 elsif Can_Be_Reused (SR, Count) then
1609 Common (SR, SR, Count);
1611 -- Otherwise allocate new shared string and fill it
1614 DR := Allocate (Count);
1615 Common (SR, DR, Count);
1616 Source.Reference := DR;
1621 --------------------
1622 -- To_Wide_Wide_String --
1623 --------------------
1625 function To_Wide_Wide_String
1626 (Source : Unbounded_Wide_Wide_String) return Wide_Wide_String is
1628 return Source.Reference.Data (1 .. Source.Reference.Last);
1629 end To_Wide_Wide_String;
1631 ------------------------------
1632 -- To_Unbounded_Wide_Wide_String --
1633 ------------------------------
1635 function To_Unbounded_Wide_Wide_String
1636 (Source : Wide_Wide_String) return Unbounded_Wide_Wide_String
1638 DR : constant Shared_Wide_Wide_String_Access := Allocate (Source'Length);
1640 DR.Data (1 .. Source'Length) := Source;
1641 DR.Last := Source'Length;
1642 return (AF.Controlled with Reference => DR);
1643 end To_Unbounded_Wide_Wide_String;
1645 function To_Unbounded_Wide_Wide_String
1646 (Length : Natural) return Unbounded_Wide_Wide_String
1648 DR : constant Shared_Wide_Wide_String_Access := Allocate (Length);
1651 return (AF.Controlled with Reference => DR);
1652 end To_Unbounded_Wide_Wide_String;
1659 (Source : Unbounded_Wide_Wide_String;
1660 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping)
1661 return Unbounded_Wide_Wide_String
1663 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1664 DR : Shared_Wide_Wide_String_Access;
1667 -- Nothing to translate, reuse empty shared string
1670 Reference (Empty_Shared_Wide_Wide_String'Access);
1671 DR := Empty_Shared_Wide_Wide_String'Access;
1673 -- Otherwise, allocate new shared string and fill it
1676 DR := Allocate (SR.Last);
1678 for J in 1 .. SR.Last loop
1679 DR.Data (J) := Value (Mapping, SR.Data (J));
1685 return (AF.Controlled with Reference => DR);
1689 (Source : in out Unbounded_Wide_Wide_String;
1690 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping)
1692 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1693 DR : Shared_Wide_Wide_String_Access;
1696 -- Nothing to translate
1701 -- Try to reuse shared string
1703 elsif Can_Be_Reused (SR, SR.Last) then
1704 for J in 1 .. SR.Last loop
1705 SR.Data (J) := Value (Mapping, SR.Data (J));
1708 -- Otherwise, allocate new shared string
1711 DR := Allocate (SR.Last);
1713 for J in 1 .. SR.Last loop
1714 DR.Data (J) := Value (Mapping, SR.Data (J));
1718 Source.Reference := DR;
1724 (Source : Unbounded_Wide_Wide_String;
1725 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping_Function)
1726 return Unbounded_Wide_Wide_String
1728 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1729 DR : Shared_Wide_Wide_String_Access;
1732 -- Nothing to translate, reuse empty shared string
1735 Reference (Empty_Shared_Wide_Wide_String'Access);
1736 DR := Empty_Shared_Wide_Wide_String'Access;
1738 -- Otherwise, allocate new shared string and fill it
1741 DR := Allocate (SR.Last);
1743 for J in 1 .. SR.Last loop
1744 DR.Data (J) := Mapping.all (SR.Data (J));
1750 return (AF.Controlled with Reference => DR);
1760 (Source : in out Unbounded_Wide_Wide_String;
1761 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping_Function)
1763 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1764 DR : Shared_Wide_Wide_String_Access;
1767 -- Nothing to translate
1772 -- Try to reuse shared string
1774 elsif Can_Be_Reused (SR, SR.Last) then
1775 for J in 1 .. SR.Last loop
1776 SR.Data (J) := Mapping.all (SR.Data (J));
1779 -- Otherwise allocate new shared string and fill it
1782 DR := Allocate (SR.Last);
1784 for J in 1 .. SR.Last loop
1785 DR.Data (J) := Mapping.all (SR.Data (J));
1789 Source.Reference := DR;
1807 (Source : Unbounded_Wide_Wide_String;
1808 Side : Trim_End) return Unbounded_Wide_Wide_String
1810 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1812 DR : Shared_Wide_Wide_String_Access;
1817 Low := Index_Non_Blank (Source, Forward);
1819 -- All blanks, reuse empty shared string
1822 Reference (Empty_Shared_Wide_Wide_String'Access);
1823 DR := Empty_Shared_Wide_Wide_String'Access;
1829 DL := SR.Last - Low + 1;
1833 High := Index_Non_Blank (Source, Backward);
1837 High := Index_Non_Blank (Source, Backward);
1838 DL := High - Low + 1;
1841 -- Length of the result is the same as length of the source string,
1842 -- reuse source shared string.
1844 if DL = SR.Last then
1848 -- Otherwise, allocate new shared string
1851 DR := Allocate (DL);
1852 DR.Data (1 .. DL) := SR.Data (Low .. High);
1857 return (AF.Controlled with Reference => DR);
1861 (Source : in out Unbounded_Wide_Wide_String;
1864 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1866 DR : Shared_Wide_Wide_String_Access;
1871 Low := Index_Non_Blank (Source, Forward);
1873 -- All blanks, reuse empty shared string
1876 Reference (Empty_Shared_Wide_Wide_String'Access);
1877 Source.Reference := Empty_Shared_Wide_Wide_String'Access;
1884 DL := SR.Last - Low + 1;
1888 High := Index_Non_Blank (Source, Backward);
1892 High := Index_Non_Blank (Source, Backward);
1893 DL := High - Low + 1;
1896 -- Length of the result is the same as length of the source string,
1899 if DL = SR.Last then
1902 -- Try to reuse existent shared string
1904 elsif Can_Be_Reused (SR, DL) then
1905 SR.Data (1 .. DL) := SR.Data (Low .. High);
1908 -- Otherwise, allocate new shared string
1911 DR := Allocate (DL);
1912 DR.Data (1 .. DL) := SR.Data (Low .. High);
1914 Source.Reference := DR;
1921 (Source : Unbounded_Wide_Wide_String;
1922 Left : Wide_Wide_Maps.Wide_Wide_Character_Set;
1923 Right : Wide_Wide_Maps.Wide_Wide_Character_Set)
1924 return Unbounded_Wide_Wide_String
1926 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1928 DR : Shared_Wide_Wide_String_Access;
1933 Low := Index (Source, Left, Outside, Forward);
1935 -- Source includes only characters from Left set, reuse empty shared
1939 Reference (Empty_Shared_Wide_Wide_String'Access);
1940 DR := Empty_Shared_Wide_Wide_String'Access;
1943 High := Index (Source, Right, Outside, Backward);
1944 DL := Integer'Max (0, High - Low + 1);
1946 -- Source includes only characters from Right set or result string
1947 -- is empty, reuse empty shared string.
1949 if High = 0 or else DL = 0 then
1950 Reference (Empty_Shared_Wide_Wide_String'Access);
1951 DR := Empty_Shared_Wide_Wide_String'Access;
1953 -- Otherwise, allocate new shared string and fill it
1956 DR := Allocate (DL);
1957 DR.Data (1 .. DL) := SR.Data (Low .. High);
1962 return (AF.Controlled with Reference => DR);
1966 (Source : in out Unbounded_Wide_Wide_String;
1967 Left : Wide_Wide_Maps.Wide_Wide_Character_Set;
1968 Right : Wide_Wide_Maps.Wide_Wide_Character_Set)
1970 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
1972 DR : Shared_Wide_Wide_String_Access;
1977 Low := Index (Source, Left, Outside, Forward);
1979 -- Source includes only characters from Left set, reuse empty shared
1983 Reference (Empty_Shared_Wide_Wide_String'Access);
1984 Source.Reference := Empty_Shared_Wide_Wide_String'Access;
1988 High := Index (Source, Right, Outside, Backward);
1989 DL := Integer'Max (0, High - Low + 1);
1991 -- Source includes only characters from Right set or result string
1992 -- is empty, reuse empty shared string.
1994 if High = 0 or else DL = 0 then
1995 Reference (Empty_Shared_Wide_Wide_String'Access);
1996 Source.Reference := Empty_Shared_Wide_Wide_String'Access;
1999 -- Try to reuse existent shared string
2001 elsif Can_Be_Reused (SR, DL) then
2002 SR.Data (1 .. DL) := SR.Data (Low .. High);
2005 -- Otherwise, allocate new shared string and fill it
2008 DR := Allocate (DL);
2009 DR.Data (1 .. DL) := SR.Data (Low .. High);
2011 Source.Reference := DR;
2017 ---------------------
2018 -- Unbounded_Slice --
2019 ---------------------
2021 function Unbounded_Slice
2022 (Source : Unbounded_Wide_Wide_String;
2024 High : Natural) return Unbounded_Wide_Wide_String
2026 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
2028 DR : Shared_Wide_Wide_String_Access;
2033 if Low > SR.Last + 1 or else High > SR.Last then
2036 -- Result is empty slice, reuse empty shared string
2038 elsif Low > High then
2039 Reference (Empty_Shared_Wide_Wide_String'Access);
2040 DR := Empty_Shared_Wide_Wide_String'Access;
2042 -- Otherwise, allocate new shared string and fill it
2045 DL := High - Low + 1;
2046 DR := Allocate (DL);
2047 DR.Data (1 .. DL) := SR.Data (Low .. High);
2051 return (AF.Controlled with Reference => DR);
2052 end Unbounded_Slice;
2054 procedure Unbounded_Slice
2055 (Source : Unbounded_Wide_Wide_String;
2056 Target : out Unbounded_Wide_Wide_String;
2060 SR : constant Shared_Wide_Wide_String_Access := Source.Reference;
2061 TR : constant Shared_Wide_Wide_String_Access := Target.Reference;
2063 DR : Shared_Wide_Wide_String_Access;
2068 if Low > SR.Last + 1 or else High > SR.Last then
2071 -- Result is empty slice, reuse empty shared string
2073 elsif Low > High then
2074 Reference (Empty_Shared_Wide_Wide_String'Access);
2075 Target.Reference := Empty_Shared_Wide_Wide_String'Access;
2079 DL := High - Low + 1;
2081 -- Try to reuse existent shared string
2083 if Can_Be_Reused (TR, DL) then
2084 TR.Data (1 .. DL) := SR.Data (Low .. High);
2087 -- Otherwise, allocate new shared string and fill it
2090 DR := Allocate (DL);
2091 DR.Data (1 .. DL) := SR.Data (Low .. High);
2093 Target.Reference := DR;
2097 end Unbounded_Slice;
2103 procedure Unreference (Item : not null Shared_Wide_Wide_String_Access) is
2106 new Ada.Unchecked_Deallocation
2107 (Shared_Wide_Wide_String, Shared_Wide_Wide_String_Access);
2109 Aux : Shared_Wide_Wide_String_Access := Item;
2112 if System.Atomic_Counters.Decrement (Aux.Counter) then
2114 -- Reference counter of Empty_Shared_Wide_Wide_String must never
2117 pragma Assert (Aux /= Empty_Shared_Wide_Wide_String'Access);
2123 end Ada.Strings.Wide_Wide_Unbounded;