1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- A D A . S T R I N G S . U N B O U N D E D --
9 -- Copyright (C) 1992-2017, 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
.Search
;
33 with Ada
.Unchecked_Deallocation
;
35 package body Ada
.Strings
.Unbounded
is
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 the
56 -- allocated memory segments to use memory effectively by Append/Insert/etc
64 (Left
: Unbounded_String
;
65 Right
: Unbounded_String
) return Unbounded_String
67 LR
: constant Shared_String_Access
:= Left
.Reference
;
68 RR
: constant Shared_String_Access
:= Right
.Reference
;
69 DL
: constant Natural := LR
.Last
+ RR
.Last
;
70 DR
: Shared_String_Access
;
73 -- Result is an empty string, reuse shared empty string
76 Reference
(Empty_Shared_String
'Access);
77 DR
:= Empty_Shared_String
'Access;
79 -- Left string is empty, return Right string
81 elsif LR
.Last
= 0 then
85 -- Right string is empty, return Left string
87 elsif RR
.Last
= 0 then
91 -- Otherwise, allocate new shared string and fill data
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_String
;
105 Right
: String) return Unbounded_String
107 LR
: constant Shared_String_Access
:= Left
.Reference
;
108 DL
: constant Natural := LR
.Last
+ Right
'Length;
109 DR
: Shared_String_Access
;
112 -- Result is an empty string, reuse shared empty string
115 Reference
(Empty_Shared_String
'Access);
116 DR
:= Empty_Shared_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
);
138 Right
: Unbounded_String
) return Unbounded_String
140 RR
: constant Shared_String_Access
:= Right
.Reference
;
141 DL
: constant Natural := Left
'Length + RR
.Last
;
142 DR
: Shared_String_Access
;
145 -- Result is an empty string, reuse shared one
148 Reference
(Empty_Shared_String
'Access);
149 DR
:= Empty_Shared_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_String
;
171 Right
: Character) return Unbounded_String
173 LR
: constant Shared_String_Access
:= Left
.Reference
;
174 DL
: constant Natural := LR
.Last
+ 1;
175 DR
: Shared_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
);
188 Right
: Unbounded_String
) return Unbounded_String
190 RR
: constant Shared_String_Access
:= Right
.Reference
;
191 DL
: constant Natural := 1 + RR
.Last
;
192 DR
: Shared_String_Access
;
197 DR
.Data
(2 .. DL
) := RR
.Data
(1 .. RR
.Last
);
200 return (AF
.Controlled
with Reference
=> DR
);
209 Right
: Character) return Unbounded_String
211 DR
: Shared_String_Access
;
214 -- Result is an empty string, reuse shared empty string
217 Reference
(Empty_Shared_String
'Access);
218 DR
:= Empty_Shared_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
: String) return Unbounded_String
239 DL
: constant Natural := Left
* Right
'Length;
240 DR
: Shared_String_Access
;
244 -- Result is an empty string, reuse shared empty string
247 Reference
(Empty_Shared_String
'Access);
248 DR
:= Empty_Shared_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_String
) return Unbounded_String
271 RR
: constant Shared_String_Access
:= Right
.Reference
;
272 DL
: constant Natural := Left
* RR
.Last
;
273 DR
: Shared_String_Access
;
277 -- Result is an empty string, reuse shared empty string
280 Reference
(Empty_Shared_String
'Access);
281 DR
:= Empty_Shared_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_String
;
312 Right
: Unbounded_String
) return Boolean
314 LR
: constant Shared_String_Access
:= Left
.Reference
;
315 RR
: constant Shared_String_Access
:= Right
.Reference
;
317 return LR
.Data
(1 .. LR
.Last
) < RR
.Data
(1 .. RR
.Last
);
321 (Left
: Unbounded_String
;
322 Right
: String) return Boolean
324 LR
: constant Shared_String_Access
:= Left
.Reference
;
326 return LR
.Data
(1 .. LR
.Last
) < Right
;
331 Right
: Unbounded_String
) return Boolean
333 RR
: constant Shared_String_Access
:= Right
.Reference
;
335 return Left
< RR
.Data
(1 .. RR
.Last
);
343 (Left
: Unbounded_String
;
344 Right
: Unbounded_String
) return Boolean
346 LR
: constant Shared_String_Access
:= Left
.Reference
;
347 RR
: constant Shared_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_String
;
357 Right
: String) return Boolean
359 LR
: constant Shared_String_Access
:= Left
.Reference
;
361 return LR
.Data
(1 .. LR
.Last
) <= Right
;
366 Right
: Unbounded_String
) return Boolean
368 RR
: constant Shared_String_Access
:= Right
.Reference
;
370 return Left
<= RR
.Data
(1 .. RR
.Last
);
378 (Left
: Unbounded_String
;
379 Right
: Unbounded_String
) return Boolean
381 LR
: constant Shared_String_Access
:= Left
.Reference
;
382 RR
: constant Shared_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_String
;
391 Right
: String) return Boolean
393 LR
: constant Shared_String_Access
:= Left
.Reference
;
395 return LR
.Data
(1 .. LR
.Last
) = Right
;
400 Right
: Unbounded_String
) return Boolean
402 RR
: constant Shared_String_Access
:= Right
.Reference
;
404 return Left
= RR
.Data
(1 .. RR
.Last
);
412 (Left
: Unbounded_String
;
413 Right
: Unbounded_String
) return Boolean
415 LR
: constant Shared_String_Access
:= Left
.Reference
;
416 RR
: constant Shared_String_Access
:= Right
.Reference
;
418 return LR
.Data
(1 .. LR
.Last
) > RR
.Data
(1 .. RR
.Last
);
422 (Left
: Unbounded_String
;
423 Right
: String) return Boolean
425 LR
: constant Shared_String_Access
:= Left
.Reference
;
427 return LR
.Data
(1 .. LR
.Last
) > Right
;
432 Right
: Unbounded_String
) return Boolean
434 RR
: constant Shared_String_Access
:= Right
.Reference
;
436 return Left
> RR
.Data
(1 .. RR
.Last
);
444 (Left
: Unbounded_String
;
445 Right
: Unbounded_String
) return Boolean
447 LR
: constant Shared_String_Access
:= Left
.Reference
;
448 RR
: constant Shared_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_String
;
458 Right
: String) return Boolean
460 LR
: constant Shared_String_Access
:= Left
.Reference
;
462 return LR
.Data
(1 .. LR
.Last
) >= Right
;
467 Right
: Unbounded_String
) return Boolean
469 RR
: constant Shared_String_Access
:= Right
.Reference
;
471 return Left
>= RR
.Data
(1 .. RR
.Last
);
478 procedure Adjust
(Object
: in out Unbounded_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_String
'Size / Standard
'Storage_Unit;
490 -- Total size of all static components
494 ((Static_Size
+ Max_Length
- 1) / Min_Mul_Alloc
+ 2) * Min_Mul_Alloc
496 end Aligned_Max_Length
;
503 (Max_Length
: Natural) return not null Shared_String_Access
506 -- Empty string requested, return shared empty string
508 if Max_Length
= 0 then
509 Reference
(Empty_Shared_String
'Access);
510 return Empty_Shared_String
'Access;
512 -- Otherwise, allocate requested space (and probably some more room)
515 return new Shared_String
(Aligned_Max_Length
(Max_Length
));
524 (Source
: in out Unbounded_String
;
525 New_Item
: Unbounded_String
)
527 SR
: constant Shared_String_Access
:= Source
.Reference
;
528 NR
: constant Shared_String_Access
:= New_Item
.Reference
;
529 DL
: constant Natural := SR
.Last
+ NR
.Last
;
530 DR
: Shared_String_Access
;
533 -- Source is an empty string, reuse New_Item data
537 Source
.Reference
:= NR
;
540 -- New_Item is empty string, nothing to do
542 elsif NR
.Last
= 0 then
545 -- Try to reuse existing shared string
547 elsif Can_Be_Reused
(SR
, DL
) then
548 SR
.Data
(SR
.Last
+ 1 .. DL
) := NR
.Data
(1 .. NR
.Last
);
551 -- Otherwise, allocate new one and fill it
554 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
555 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
556 DR
.Data
(SR
.Last
+ 1 .. DL
) := NR
.Data
(1 .. NR
.Last
);
558 Source
.Reference
:= DR
;
564 (Source
: in out Unbounded_String
;
567 SR
: constant Shared_String_Access
:= Source
.Reference
;
568 DL
: constant Natural := SR
.Last
+ New_Item
'Length;
569 DR
: Shared_String_Access
;
572 -- New_Item is an empty string, nothing to do
574 if New_Item
'Length = 0 then
577 -- Try to reuse existing shared string
579 elsif Can_Be_Reused
(SR
, DL
) then
580 SR
.Data
(SR
.Last
+ 1 .. DL
) := New_Item
;
583 -- Otherwise, allocate new one and fill it
586 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
587 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
588 DR
.Data
(SR
.Last
+ 1 .. DL
) := New_Item
;
590 Source
.Reference
:= DR
;
596 (Source
: in out Unbounded_String
;
597 New_Item
: Character)
599 SR
: constant Shared_String_Access
:= Source
.Reference
;
600 DL
: constant Natural := SR
.Last
+ 1;
601 DR
: Shared_String_Access
;
604 -- Try to reuse existing shared string
606 if Can_Be_Reused
(SR
, SR
.Last
+ 1) then
607 SR
.Data
(SR
.Last
+ 1) := New_Item
;
608 SR
.Last
:= SR
.Last
+ 1;
610 -- Otherwise, allocate new one and fill it
613 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
614 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
615 DR
.Data
(DL
) := New_Item
;
617 Source
.Reference
:= DR
;
626 function Can_Be_Reused
627 (Item
: not null Shared_String_Access
;
628 Length
: Natural) return Boolean
632 System
.Atomic_Counters
.Is_One
(Item
.Counter
)
633 and then Item
.Max_Length
>= Length
634 and then Item
.Max_Length
<=
635 Aligned_Max_Length
(Length
+ Length
/ Growth_Factor
);
643 (Source
: Unbounded_String
;
645 Mapping
: Maps
.Character_Mapping
:= Maps
.Identity
) return Natural
647 SR
: constant Shared_String_Access
:= Source
.Reference
;
649 return Search
.Count
(SR
.Data
(1 .. SR
.Last
), Pattern
, Mapping
);
653 (Source
: Unbounded_String
;
655 Mapping
: Maps
.Character_Mapping_Function
) return Natural
657 SR
: constant Shared_String_Access
:= Source
.Reference
;
659 return Search
.Count
(SR
.Data
(1 .. SR
.Last
), Pattern
, Mapping
);
663 (Source
: Unbounded_String
;
664 Set
: Maps
.Character_Set
) return Natural
666 SR
: constant Shared_String_Access
:= Source
.Reference
;
668 return Search
.Count
(SR
.Data
(1 .. SR
.Last
), Set
);
676 (Source
: Unbounded_String
;
678 Through
: Natural) return Unbounded_String
680 SR
: constant Shared_String_Access
:= Source
.Reference
;
682 DR
: Shared_String_Access
;
685 -- Empty slice is deleted, use the same shared string
687 if From
> Through
then
691 -- Index is out of range
693 elsif Through
> SR
.Last
then
696 -- Compute size of the result
699 DL
:= SR
.Last
- (Through
- From
+ 1);
701 -- Result is an empty string, reuse shared empty string
704 Reference
(Empty_Shared_String
'Access);
705 DR
:= Empty_Shared_String
'Access;
707 -- Otherwise, allocate new shared string and fill it
711 DR
.Data
(1 .. From
- 1) := SR
.Data
(1 .. From
- 1);
712 DR
.Data
(From
.. DL
) := SR
.Data
(Through
+ 1 .. SR
.Last
);
717 return (AF
.Controlled
with Reference
=> DR
);
721 (Source
: in out Unbounded_String
;
725 SR
: constant Shared_String_Access
:= Source
.Reference
;
727 DR
: Shared_String_Access
;
730 -- Nothing changed, return
732 if From
> Through
then
735 -- Through is outside of the range
737 elsif Through
> SR
.Last
then
741 DL
:= SR
.Last
- (Through
- From
+ 1);
743 -- Result is empty, reuse shared empty string
746 Reference
(Empty_Shared_String
'Access);
747 Source
.Reference
:= Empty_Shared_String
'Access;
750 -- Try to reuse existing shared string
752 elsif Can_Be_Reused
(SR
, DL
) then
753 SR
.Data
(From
.. DL
) := SR
.Data
(Through
+ 1 .. SR
.Last
);
756 -- Otherwise, allocate new shared string
760 DR
.Data
(1 .. From
- 1) := SR
.Data
(1 .. From
- 1);
761 DR
.Data
(From
.. DL
) := SR
.Data
(Through
+ 1 .. SR
.Last
);
763 Source
.Reference
:= DR
;
774 (Source
: Unbounded_String
;
775 Index
: Positive) return Character
777 SR
: constant Shared_String_Access
:= Source
.Reference
;
779 if Index
<= SR
.Last
then
780 return SR
.Data
(Index
);
790 procedure Finalize
(Object
: in out Unbounded_String
) is
791 SR
: constant not null Shared_String_Access
:= Object
.Reference
;
793 if SR
/= Null_Unbounded_String
.Reference
then
795 -- The same controlled object can be finalized several times for
796 -- some reason. As per 7.6.1(24) this should have no ill effect,
797 -- so we need to add a guard for the case of finalizing the same
800 -- We set the Object to the empty string so there will be no ill
801 -- effects if a program references an already-finalized object.
803 Object
.Reference
:= Null_Unbounded_String
.Reference
;
804 Reference
(Object
.Reference
);
814 (Source
: Unbounded_String
;
815 Set
: Maps
.Character_Set
;
817 Test
: Strings
.Membership
;
818 First
: out Positive;
821 SR
: constant Shared_String_Access
:= Source
.Reference
;
823 Search
.Find_Token
(SR
.Data
(From
.. SR
.Last
), Set
, Test
, First
, Last
);
827 (Source
: Unbounded_String
;
828 Set
: Maps
.Character_Set
;
829 Test
: Strings
.Membership
;
830 First
: out Positive;
833 SR
: constant Shared_String_Access
:= Source
.Reference
;
835 Search
.Find_Token
(SR
.Data
(1 .. SR
.Last
), Set
, Test
, First
, Last
);
842 procedure Free
(X
: in out String_Access
) is
843 procedure Deallocate
is
844 new Ada
.Unchecked_Deallocation
(String, String_Access
);
854 (Source
: Unbounded_String
;
856 Pad
: Character := Space
) return Unbounded_String
858 SR
: constant Shared_String_Access
:= Source
.Reference
;
859 DR
: Shared_String_Access
;
862 -- Result is empty, reuse shared empty string
865 Reference
(Empty_Shared_String
'Access);
866 DR
:= Empty_Shared_String
'Access;
868 -- Length of the string is the same as requested, reuse source shared
871 elsif Count
= SR
.Last
then
875 -- Otherwise, allocate new shared string and fill it
878 DR
:= Allocate
(Count
);
880 -- Length of the source string is more than requested, copy
881 -- corresponding slice.
883 if Count
< SR
.Last
then
884 DR
.Data
(1 .. Count
) := SR
.Data
(1 .. Count
);
886 -- Length of the source string is less than requested, copy all
887 -- contents and fill others by Pad character.
890 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
892 for J
in SR
.Last
+ 1 .. Count
loop
900 return (AF
.Controlled
with Reference
=> DR
);
904 (Source
: in out Unbounded_String
;
906 Pad
: Character := Space
)
908 SR
: constant Shared_String_Access
:= Source
.Reference
;
909 DR
: Shared_String_Access
;
912 -- Result is empty, reuse empty shared string
915 Reference
(Empty_Shared_String
'Access);
916 Source
.Reference
:= Empty_Shared_String
'Access;
919 -- Result is same as source string, reuse source shared string
921 elsif Count
= SR
.Last
then
924 -- Try to reuse existing shared string
926 elsif Can_Be_Reused
(SR
, Count
) then
927 if Count
> SR
.Last
then
928 for J
in SR
.Last
+ 1 .. Count
loop
935 -- Otherwise, allocate new shared string and fill it
938 DR
:= Allocate
(Count
);
940 -- Length of the source string is greater than requested, copy
941 -- corresponding slice.
943 if Count
< SR
.Last
then
944 DR
.Data
(1 .. Count
) := SR
.Data
(1 .. Count
);
946 -- Length of the source string is less than requested, copy all
947 -- existing data and fill remaining positions with Pad characters.
950 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
952 for J
in SR
.Last
+ 1 .. Count
loop
958 Source
.Reference
:= DR
;
968 (Source
: Unbounded_String
;
970 Going
: Strings
.Direction
:= Strings
.Forward
;
971 Mapping
: Maps
.Character_Mapping
:= Maps
.Identity
) return Natural
973 SR
: constant Shared_String_Access
:= Source
.Reference
;
975 return Search
.Index
(SR
.Data
(1 .. SR
.Last
), Pattern
, Going
, Mapping
);
979 (Source
: Unbounded_String
;
981 Going
: Direction
:= Forward
;
982 Mapping
: Maps
.Character_Mapping_Function
) return Natural
984 SR
: constant Shared_String_Access
:= Source
.Reference
;
986 return Search
.Index
(SR
.Data
(1 .. SR
.Last
), Pattern
, Going
, Mapping
);
990 (Source
: Unbounded_String
;
991 Set
: Maps
.Character_Set
;
992 Test
: Strings
.Membership
:= Strings
.Inside
;
993 Going
: Strings
.Direction
:= Strings
.Forward
) return Natural
995 SR
: constant Shared_String_Access
:= Source
.Reference
;
997 return Search
.Index
(SR
.Data
(1 .. SR
.Last
), Set
, Test
, Going
);
1001 (Source
: Unbounded_String
;
1004 Going
: Direction
:= Forward
;
1005 Mapping
: Maps
.Character_Mapping
:= Maps
.Identity
) return Natural
1007 SR
: constant Shared_String_Access
:= Source
.Reference
;
1010 (SR
.Data
(1 .. SR
.Last
), Pattern
, From
, Going
, Mapping
);
1014 (Source
: Unbounded_String
;
1017 Going
: Direction
:= Forward
;
1018 Mapping
: Maps
.Character_Mapping_Function
) return Natural
1020 SR
: constant Shared_String_Access
:= Source
.Reference
;
1023 (SR
.Data
(1 .. SR
.Last
), Pattern
, From
, Going
, Mapping
);
1027 (Source
: Unbounded_String
;
1028 Set
: Maps
.Character_Set
;
1030 Test
: Membership
:= Inside
;
1031 Going
: Direction
:= Forward
) return Natural
1033 SR
: constant Shared_String_Access
:= Source
.Reference
;
1035 return Search
.Index
(SR
.Data
(1 .. SR
.Last
), Set
, From
, Test
, Going
);
1038 ---------------------
1039 -- Index_Non_Blank --
1040 ---------------------
1042 function Index_Non_Blank
1043 (Source
: Unbounded_String
;
1044 Going
: Strings
.Direction
:= Strings
.Forward
) return Natural
1046 SR
: constant Shared_String_Access
:= Source
.Reference
;
1048 return Search
.Index_Non_Blank
(SR
.Data
(1 .. SR
.Last
), Going
);
1049 end Index_Non_Blank
;
1051 function Index_Non_Blank
1052 (Source
: Unbounded_String
;
1054 Going
: Direction
:= Forward
) return Natural
1056 SR
: constant Shared_String_Access
:= Source
.Reference
;
1058 return Search
.Index_Non_Blank
(SR
.Data
(1 .. SR
.Last
), From
, Going
);
1059 end Index_Non_Blank
;
1065 procedure Initialize
(Object
: in out Unbounded_String
) is
1067 Reference
(Object
.Reference
);
1075 (Source
: Unbounded_String
;
1077 New_Item
: String) return Unbounded_String
1079 SR
: constant Shared_String_Access
:= Source
.Reference
;
1080 DL
: constant Natural := SR
.Last
+ New_Item
'Length;
1081 DR
: Shared_String_Access
;
1084 -- Check index first
1086 if Before
> SR
.Last
+ 1 then
1090 -- Result is empty, reuse empty shared string
1093 Reference
(Empty_Shared_String
'Access);
1094 DR
:= Empty_Shared_String
'Access;
1096 -- Inserted string is empty, reuse source shared string
1098 elsif New_Item
'Length = 0 then
1102 -- Otherwise, allocate new shared string and fill it
1105 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
1106 DR
.Data
(1 .. Before
- 1) := SR
.Data
(1 .. Before
- 1);
1107 DR
.Data
(Before
.. Before
+ New_Item
'Length - 1) := New_Item
;
1108 DR
.Data
(Before
+ New_Item
'Length .. DL
) :=
1109 SR
.Data
(Before
.. SR
.Last
);
1113 return (AF
.Controlled
with Reference
=> DR
);
1117 (Source
: in out Unbounded_String
;
1121 SR
: constant Shared_String_Access
:= Source
.Reference
;
1122 DL
: constant Natural := SR
.Last
+ New_Item
'Length;
1123 DR
: Shared_String_Access
;
1128 if Before
> SR
.Last
+ 1 then
1132 -- Result is empty string, reuse empty shared string
1135 Reference
(Empty_Shared_String
'Access);
1136 Source
.Reference
:= Empty_Shared_String
'Access;
1139 -- Inserted string is empty, nothing to do
1141 elsif New_Item
'Length = 0 then
1144 -- Try to reuse existing shared string first
1146 elsif Can_Be_Reused
(SR
, DL
) then
1147 SR
.Data
(Before
+ New_Item
'Length .. DL
) :=
1148 SR
.Data
(Before
.. SR
.Last
);
1149 SR
.Data
(Before
.. Before
+ New_Item
'Length - 1) := New_Item
;
1152 -- Otherwise, allocate new shared string and fill it
1155 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
1156 DR
.Data
(1 .. Before
- 1) := SR
.Data
(1 .. Before
- 1);
1157 DR
.Data
(Before
.. Before
+ New_Item
'Length - 1) := New_Item
;
1158 DR
.Data
(Before
+ New_Item
'Length .. DL
) :=
1159 SR
.Data
(Before
.. SR
.Last
);
1161 Source
.Reference
:= DR
;
1170 function Length
(Source
: Unbounded_String
) return Natural is
1172 return Source
.Reference
.Last
;
1180 (Source
: Unbounded_String
;
1181 Position
: Positive;
1182 New_Item
: String) return Unbounded_String
1184 SR
: constant Shared_String_Access
:= Source
.Reference
;
1186 DR
: Shared_String_Access
;
1191 if Position
> SR
.Last
+ 1 then
1195 DL
:= Integer'Max (SR
.Last
, Position
+ New_Item
'Length - 1);
1197 -- Result is empty string, reuse empty shared string
1200 Reference
(Empty_Shared_String
'Access);
1201 DR
:= Empty_Shared_String
'Access;
1203 -- Result is same as source string, reuse source shared string
1205 elsif New_Item
'Length = 0 then
1209 -- Otherwise, allocate new shared string and fill it
1212 DR
:= Allocate
(DL
);
1213 DR
.Data
(1 .. Position
- 1) := SR
.Data
(1 .. Position
- 1);
1214 DR
.Data
(Position
.. Position
+ New_Item
'Length - 1) := New_Item
;
1215 DR
.Data
(Position
+ New_Item
'Length .. DL
) :=
1216 SR
.Data
(Position
+ New_Item
'Length .. SR
.Last
);
1220 return (AF
.Controlled
with Reference
=> DR
);
1224 (Source
: in out Unbounded_String
;
1225 Position
: Positive;
1228 SR
: constant Shared_String_Access
:= Source
.Reference
;
1230 DR
: Shared_String_Access
;
1235 if Position
> SR
.Last
+ 1 then
1239 DL
:= Integer'Max (SR
.Last
, Position
+ New_Item
'Length - 1);
1241 -- Result is empty string, reuse empty shared string
1244 Reference
(Empty_Shared_String
'Access);
1245 Source
.Reference
:= Empty_Shared_String
'Access;
1248 -- String unchanged, nothing to do
1250 elsif New_Item
'Length = 0 then
1253 -- Try to reuse existing shared string
1255 elsif Can_Be_Reused
(SR
, DL
) then
1256 SR
.Data
(Position
.. Position
+ New_Item
'Length - 1) := New_Item
;
1259 -- Otherwise allocate new shared string and fill it
1262 DR
:= Allocate
(DL
);
1263 DR
.Data
(1 .. Position
- 1) := SR
.Data
(1 .. Position
- 1);
1264 DR
.Data
(Position
.. Position
+ New_Item
'Length - 1) := New_Item
;
1265 DR
.Data
(Position
+ New_Item
'Length .. DL
) :=
1266 SR
.Data
(Position
+ New_Item
'Length .. SR
.Last
);
1268 Source
.Reference
:= DR
;
1277 procedure Reference
(Item
: not null Shared_String_Access
) is
1279 System
.Atomic_Counters
.Increment
(Item
.Counter
);
1282 ---------------------
1283 -- Replace_Element --
1284 ---------------------
1286 procedure Replace_Element
1287 (Source
: in out Unbounded_String
;
1291 SR
: constant Shared_String_Access
:= Source
.Reference
;
1292 DR
: Shared_String_Access
;
1297 if Index
<= SR
.Last
then
1299 -- Try to reuse existing shared string
1301 if Can_Be_Reused
(SR
, SR
.Last
) then
1302 SR
.Data
(Index
) := By
;
1304 -- Otherwise allocate new shared string and fill it
1307 DR
:= Allocate
(SR
.Last
);
1308 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
1309 DR
.Data
(Index
) := By
;
1311 Source
.Reference
:= DR
;
1318 end Replace_Element
;
1324 function Replace_Slice
1325 (Source
: Unbounded_String
;
1328 By
: String) return Unbounded_String
1330 SR
: constant Shared_String_Access
:= Source
.Reference
;
1332 DR
: Shared_String_Access
;
1337 if Low
> SR
.Last
+ 1 then
1341 -- Do replace operation when removed slice is not empty
1344 DL
:= By
'Length + SR
.Last
+ Low
- Integer'Min (High
, SR
.Last
) - 1;
1345 -- This is the number of characters remaining in the string after
1346 -- replacing the slice.
1348 -- Result is empty string, reuse empty shared string
1351 Reference
(Empty_Shared_String
'Access);
1352 DR
:= Empty_Shared_String
'Access;
1354 -- Otherwise allocate new shared string and fill it
1357 DR
:= Allocate
(DL
);
1358 DR
.Data
(1 .. Low
- 1) := SR
.Data
(1 .. Low
- 1);
1359 DR
.Data
(Low
.. Low
+ By
'Length - 1) := By
;
1360 DR
.Data
(Low
+ By
'Length .. DL
) := SR
.Data
(High
+ 1 .. SR
.Last
);
1364 return (AF
.Controlled
with Reference
=> DR
);
1366 -- Otherwise just insert string
1369 return Insert
(Source
, Low
, By
);
1373 procedure Replace_Slice
1374 (Source
: in out Unbounded_String
;
1379 SR
: constant Shared_String_Access
:= Source
.Reference
;
1381 DR
: Shared_String_Access
;
1386 if Low
> SR
.Last
+ 1 then
1390 -- Do replace operation only when replaced slice is not empty
1393 DL
:= By
'Length + SR
.Last
+ Low
- Integer'Min (High
, SR
.Last
) - 1;
1394 -- This is the number of characters remaining in the string after
1395 -- replacing the slice.
1397 -- Result is empty string, reuse empty shared string
1400 Reference
(Empty_Shared_String
'Access);
1401 Source
.Reference
:= Empty_Shared_String
'Access;
1404 -- Try to reuse existing shared string
1406 elsif Can_Be_Reused
(SR
, DL
) then
1407 SR
.Data
(Low
+ By
'Length .. DL
) := SR
.Data
(High
+ 1 .. SR
.Last
);
1408 SR
.Data
(Low
.. Low
+ By
'Length - 1) := By
;
1411 -- Otherwise allocate new shared string and fill it
1414 DR
:= Allocate
(DL
);
1415 DR
.Data
(1 .. Low
- 1) := SR
.Data
(1 .. Low
- 1);
1416 DR
.Data
(Low
.. Low
+ By
'Length - 1) := By
;
1417 DR
.Data
(Low
+ By
'Length .. DL
) := SR
.Data
(High
+ 1 .. SR
.Last
);
1419 Source
.Reference
:= DR
;
1423 -- Otherwise just insert item
1426 Insert
(Source
, Low
, By
);
1430 --------------------------
1431 -- Set_Unbounded_String --
1432 --------------------------
1434 procedure Set_Unbounded_String
1435 (Target
: out Unbounded_String
;
1438 TR
: constant Shared_String_Access
:= Target
.Reference
;
1439 DR
: Shared_String_Access
;
1442 -- In case of empty string, reuse empty shared string
1444 if Source
'Length = 0 then
1445 Reference
(Empty_Shared_String
'Access);
1446 Target
.Reference
:= Empty_Shared_String
'Access;
1449 -- Try to reuse existing shared string
1451 if Can_Be_Reused
(TR
, Source
'Length) then
1455 -- Otherwise allocate new shared string
1458 DR
:= Allocate
(Source
'Length);
1459 Target
.Reference
:= DR
;
1462 DR
.Data
(1 .. Source
'Length) := Source
;
1463 DR
.Last
:= Source
'Length;
1467 end Set_Unbounded_String
;
1474 (Source
: Unbounded_String
;
1476 High
: Natural) return String
1478 SR
: constant Shared_String_Access
:= Source
.Reference
;
1481 -- Note: test of High > Length is in accordance with AI95-00128
1483 if Low
> SR
.Last
+ 1 or else High
> SR
.Last
then
1487 return SR
.Data
(Low
.. High
);
1496 (Source
: Unbounded_String
;
1498 Pad
: Character := Space
) return Unbounded_String
1500 SR
: constant Shared_String_Access
:= Source
.Reference
;
1501 DR
: Shared_String_Access
;
1504 -- For empty result reuse empty shared string
1507 Reference
(Empty_Shared_String
'Access);
1508 DR
:= Empty_Shared_String
'Access;
1510 -- Result is whole source string, reuse source shared string
1512 elsif Count
= SR
.Last
then
1516 -- Otherwise allocate new shared string and fill it
1519 DR
:= Allocate
(Count
);
1521 if Count
< SR
.Last
then
1522 DR
.Data
(1 .. Count
) := SR
.Data
(SR
.Last
- Count
+ 1 .. SR
.Last
);
1525 for J
in 1 .. Count
- SR
.Last
loop
1529 DR
.Data
(Count
- SR
.Last
+ 1 .. Count
) := SR
.Data
(1 .. SR
.Last
);
1535 return (AF
.Controlled
with Reference
=> DR
);
1539 (Source
: in out Unbounded_String
;
1541 Pad
: Character := Space
)
1543 SR
: constant Shared_String_Access
:= Source
.Reference
;
1544 DR
: Shared_String_Access
;
1547 (SR
: Shared_String_Access
;
1548 DR
: Shared_String_Access
;
1550 -- Common code of tail computation. SR/DR can point to the same object
1557 (SR
: Shared_String_Access
;
1558 DR
: Shared_String_Access
;
1561 if Count
< SR
.Last
then
1562 DR
.Data
(1 .. Count
) := SR
.Data
(SR
.Last
- Count
+ 1 .. SR
.Last
);
1565 DR
.Data
(Count
- SR
.Last
+ 1 .. Count
) := SR
.Data
(1 .. SR
.Last
);
1567 for J
in 1 .. Count
- SR
.Last
loop
1576 -- Result is empty string, reuse empty shared string
1579 Reference
(Empty_Shared_String
'Access);
1580 Source
.Reference
:= Empty_Shared_String
'Access;
1583 -- Length of the result is the same as length of the source string,
1584 -- reuse source shared string.
1586 elsif Count
= SR
.Last
then
1589 -- Try to reuse existing shared string
1591 elsif Can_Be_Reused
(SR
, Count
) then
1592 Common
(SR
, SR
, Count
);
1594 -- Otherwise allocate new shared string and fill it
1597 DR
:= Allocate
(Count
);
1598 Common
(SR
, DR
, Count
);
1599 Source
.Reference
:= DR
;
1608 function To_String
(Source
: Unbounded_String
) return String is
1610 return Source
.Reference
.Data
(1 .. Source
.Reference
.Last
);
1613 -------------------------
1614 -- To_Unbounded_String --
1615 -------------------------
1617 function To_Unbounded_String
(Source
: String) return Unbounded_String
is
1618 DR
: Shared_String_Access
;
1621 if Source
'Length = 0 then
1622 Reference
(Empty_Shared_String
'Access);
1623 DR
:= Empty_Shared_String
'Access;
1626 DR
:= Allocate
(Source
'Length);
1627 DR
.Data
(1 .. Source
'Length) := Source
;
1628 DR
.Last
:= Source
'Length;
1631 return (AF
.Controlled
with Reference
=> DR
);
1632 end To_Unbounded_String
;
1634 function To_Unbounded_String
(Length
: Natural) return Unbounded_String
is
1635 DR
: Shared_String_Access
;
1639 Reference
(Empty_Shared_String
'Access);
1640 DR
:= Empty_Shared_String
'Access;
1643 DR
:= Allocate
(Length
);
1647 return (AF
.Controlled
with Reference
=> DR
);
1648 end To_Unbounded_String
;
1655 (Source
: Unbounded_String
;
1656 Mapping
: Maps
.Character_Mapping
) return Unbounded_String
1658 SR
: constant Shared_String_Access
:= Source
.Reference
;
1659 DR
: Shared_String_Access
;
1662 -- Nothing to translate, reuse empty shared string
1665 Reference
(Empty_Shared_String
'Access);
1666 DR
:= Empty_Shared_String
'Access;
1668 -- Otherwise, allocate new shared string and fill it
1671 DR
:= Allocate
(SR
.Last
);
1673 for J
in 1 .. SR
.Last
loop
1674 DR
.Data
(J
) := Value
(Mapping
, SR
.Data
(J
));
1680 return (AF
.Controlled
with Reference
=> DR
);
1684 (Source
: in out Unbounded_String
;
1685 Mapping
: Maps
.Character_Mapping
)
1687 SR
: constant Shared_String_Access
:= Source
.Reference
;
1688 DR
: Shared_String_Access
;
1691 -- Nothing to translate
1696 -- Try to reuse shared string
1698 elsif Can_Be_Reused
(SR
, SR
.Last
) then
1699 for J
in 1 .. SR
.Last
loop
1700 SR
.Data
(J
) := Value
(Mapping
, SR
.Data
(J
));
1703 -- Otherwise, allocate new shared string
1706 DR
:= Allocate
(SR
.Last
);
1708 for J
in 1 .. SR
.Last
loop
1709 DR
.Data
(J
) := Value
(Mapping
, SR
.Data
(J
));
1713 Source
.Reference
:= DR
;
1719 (Source
: Unbounded_String
;
1720 Mapping
: Maps
.Character_Mapping_Function
) return Unbounded_String
1722 SR
: constant Shared_String_Access
:= Source
.Reference
;
1723 DR
: Shared_String_Access
;
1726 -- Nothing to translate, reuse empty shared string
1729 Reference
(Empty_Shared_String
'Access);
1730 DR
:= Empty_Shared_String
'Access;
1732 -- Otherwise, allocate new shared string and fill it
1735 DR
:= Allocate
(SR
.Last
);
1737 for J
in 1 .. SR
.Last
loop
1738 DR
.Data
(J
) := Mapping
.all (SR
.Data
(J
));
1744 return (AF
.Controlled
with Reference
=> DR
);
1754 (Source
: in out Unbounded_String
;
1755 Mapping
: Maps
.Character_Mapping_Function
)
1757 SR
: constant Shared_String_Access
:= Source
.Reference
;
1758 DR
: Shared_String_Access
;
1761 -- Nothing to translate
1766 -- Try to reuse shared string
1768 elsif Can_Be_Reused
(SR
, SR
.Last
) then
1769 for J
in 1 .. SR
.Last
loop
1770 SR
.Data
(J
) := Mapping
.all (SR
.Data
(J
));
1773 -- Otherwise allocate new shared string and fill it
1776 DR
:= Allocate
(SR
.Last
);
1778 for J
in 1 .. SR
.Last
loop
1779 DR
.Data
(J
) := Mapping
.all (SR
.Data
(J
));
1783 Source
.Reference
:= DR
;
1801 (Source
: Unbounded_String
;
1802 Side
: Trim_End
) return Unbounded_String
1804 SR
: constant Shared_String_Access
:= Source
.Reference
;
1806 DR
: Shared_String_Access
;
1811 Low
:= Index_Non_Blank
(Source
, Forward
);
1813 -- All blanks, reuse empty shared string
1816 Reference
(Empty_Shared_String
'Access);
1817 DR
:= Empty_Shared_String
'Access;
1823 DL
:= SR
.Last
- Low
+ 1;
1827 High
:= Index_Non_Blank
(Source
, Backward
);
1831 High
:= Index_Non_Blank
(Source
, Backward
);
1832 DL
:= High
- Low
+ 1;
1835 -- Length of the result is the same as length of the source string,
1836 -- reuse source shared string.
1838 if DL
= SR
.Last
then
1842 -- Otherwise, allocate new shared string
1845 DR
:= Allocate
(DL
);
1846 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
1851 return (AF
.Controlled
with Reference
=> DR
);
1855 (Source
: in out Unbounded_String
;
1858 SR
: constant Shared_String_Access
:= Source
.Reference
;
1860 DR
: Shared_String_Access
;
1865 Low
:= Index_Non_Blank
(Source
, Forward
);
1867 -- All blanks, reuse empty shared string
1870 Reference
(Empty_Shared_String
'Access);
1871 Source
.Reference
:= Empty_Shared_String
'Access;
1878 DL
:= SR
.Last
- Low
+ 1;
1882 High
:= Index_Non_Blank
(Source
, Backward
);
1886 High
:= Index_Non_Blank
(Source
, Backward
);
1887 DL
:= High
- Low
+ 1;
1890 -- Length of the result is the same as length of the source string,
1893 if DL
= SR
.Last
then
1896 -- Try to reuse existing shared string
1898 elsif Can_Be_Reused
(SR
, DL
) then
1899 SR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
1902 -- Otherwise, allocate new shared string
1905 DR
:= Allocate
(DL
);
1906 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
1908 Source
.Reference
:= DR
;
1915 (Source
: Unbounded_String
;
1916 Left
: Maps
.Character_Set
;
1917 Right
: Maps
.Character_Set
) return Unbounded_String
1919 SR
: constant Shared_String_Access
:= Source
.Reference
;
1921 DR
: Shared_String_Access
;
1926 Low
:= Index
(Source
, Left
, Outside
, Forward
);
1928 -- Source includes only characters from Left set, reuse empty shared
1932 Reference
(Empty_Shared_String
'Access);
1933 DR
:= Empty_Shared_String
'Access;
1936 High
:= Index
(Source
, Right
, Outside
, Backward
);
1937 DL
:= Integer'Max (0, High
- Low
+ 1);
1939 -- Source includes only characters from Right set or result string
1940 -- is empty, reuse empty shared string.
1942 if High
= 0 or else DL
= 0 then
1943 Reference
(Empty_Shared_String
'Access);
1944 DR
:= Empty_Shared_String
'Access;
1946 -- Otherwise, allocate new shared string and fill it
1949 DR
:= Allocate
(DL
);
1950 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
1955 return (AF
.Controlled
with Reference
=> DR
);
1959 (Source
: in out Unbounded_String
;
1960 Left
: Maps
.Character_Set
;
1961 Right
: Maps
.Character_Set
)
1963 SR
: constant Shared_String_Access
:= Source
.Reference
;
1965 DR
: Shared_String_Access
;
1970 Low
:= Index
(Source
, Left
, Outside
, Forward
);
1972 -- Source includes only characters from Left set, reuse empty shared
1976 Reference
(Empty_Shared_String
'Access);
1977 Source
.Reference
:= Empty_Shared_String
'Access;
1981 High
:= Index
(Source
, Right
, Outside
, Backward
);
1982 DL
:= Integer'Max (0, High
- Low
+ 1);
1984 -- Source includes only characters from Right set or result string
1985 -- is empty, reuse empty shared string.
1987 if High
= 0 or else DL
= 0 then
1988 Reference
(Empty_Shared_String
'Access);
1989 Source
.Reference
:= Empty_Shared_String
'Access;
1992 -- Try to reuse existing shared string
1994 elsif Can_Be_Reused
(SR
, DL
) then
1995 SR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
1998 -- Otherwise, allocate new shared string and fill it
2001 DR
:= Allocate
(DL
);
2002 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2004 Source
.Reference
:= DR
;
2010 ---------------------
2011 -- Unbounded_Slice --
2012 ---------------------
2014 function Unbounded_Slice
2015 (Source
: Unbounded_String
;
2017 High
: Natural) return Unbounded_String
2019 SR
: constant Shared_String_Access
:= Source
.Reference
;
2021 DR
: Shared_String_Access
;
2026 if Low
> SR
.Last
+ 1 or else High
> SR
.Last
then
2029 -- Result is empty slice, reuse empty shared string
2031 elsif Low
> High
then
2032 Reference
(Empty_Shared_String
'Access);
2033 DR
:= Empty_Shared_String
'Access;
2035 -- Otherwise, allocate new shared string and fill it
2038 DL
:= High
- Low
+ 1;
2039 DR
:= Allocate
(DL
);
2040 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2044 return (AF
.Controlled
with Reference
=> DR
);
2045 end Unbounded_Slice
;
2047 procedure Unbounded_Slice
2048 (Source
: Unbounded_String
;
2049 Target
: out Unbounded_String
;
2053 SR
: constant Shared_String_Access
:= Source
.Reference
;
2054 TR
: constant Shared_String_Access
:= Target
.Reference
;
2056 DR
: Shared_String_Access
;
2061 if Low
> SR
.Last
+ 1 or else High
> SR
.Last
then
2064 -- Result is empty slice, reuse empty shared string
2066 elsif Low
> High
then
2067 Reference
(Empty_Shared_String
'Access);
2068 Target
.Reference
:= Empty_Shared_String
'Access;
2072 DL
:= High
- Low
+ 1;
2074 -- Try to reuse existing shared string
2076 if Can_Be_Reused
(TR
, DL
) then
2077 TR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2080 -- Otherwise, allocate new shared string and fill it
2083 DR
:= Allocate
(DL
);
2084 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2086 Target
.Reference
:= DR
;
2090 end Unbounded_Slice
;
2096 procedure Unreference
(Item
: not null Shared_String_Access
) is
2099 new Ada
.Unchecked_Deallocation
(Shared_String
, Shared_String_Access
);
2101 Aux
: Shared_String_Access
:= Item
;
2104 if System
.Atomic_Counters
.Decrement
(Aux
.Counter
) then
2106 -- Reference counter of Empty_Shared_String should never reach
2107 -- zero. We check here in case it wraps around.
2109 if Aux
/= Empty_Shared_String
'Access then
2115 end Ada
.Strings
.Unbounded
;