1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME 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-2023, 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_Search
;
33 with Ada
.Unchecked_Deallocation
;
35 package body Ada
.Strings
.Wide_Unbounded
is
37 use Ada
.Strings
.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_String
;
65 Right
: Unbounded_Wide_String
) return Unbounded_Wide_String
67 LR
: constant Shared_Wide_String_Access
:= Left
.Reference
;
68 RR
: constant Shared_Wide_String_Access
:= Right
.Reference
;
69 DL
: constant Natural := LR
.Last
+ RR
.Last
;
70 DR
: Shared_Wide_String_Access
;
73 -- Result is an empty string, reuse shared empty string
76 Reference
(Empty_Shared_Wide_String
'Access);
77 DR
:= Empty_Shared_Wide_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 -- Overwise, 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_Wide_String
;
105 Right
: Wide_String) return Unbounded_Wide_String
107 LR
: constant Shared_Wide_String_Access
:= Left
.Reference
;
108 DL
: constant Natural := LR
.Last
+ Right
'Length;
109 DR
: Shared_Wide_String_Access
;
112 -- Result is an empty string, reuse shared empty string
115 Reference
(Empty_Shared_Wide_String
'Access);
116 DR
:= Empty_Shared_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
);
138 Right
: Unbounded_Wide_String
) return Unbounded_Wide_String
140 RR
: constant Shared_Wide_String_Access
:= Right
.Reference
;
141 DL
: constant Natural := Left
'Length + RR
.Last
;
142 DR
: Shared_Wide_String_Access
;
145 -- Result is an empty string, reuse shared one
148 Reference
(Empty_Shared_Wide_String
'Access);
149 DR
:= Empty_Shared_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_String
;
171 Right
: Wide_Character) return Unbounded_Wide_String
173 LR
: constant Shared_Wide_String_Access
:= Left
.Reference
;
174 DL
: constant Natural := LR
.Last
+ 1;
175 DR
: Shared_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_Character;
188 Right
: Unbounded_Wide_String
) return Unbounded_Wide_String
190 RR
: constant Shared_Wide_String_Access
:= Right
.Reference
;
191 DL
: constant Natural := 1 + RR
.Last
;
192 DR
: Shared_Wide_String_Access
;
197 DR
.Data
(2 .. DL
) := RR
.Data
(1 .. RR
.Last
);
200 return (AF
.Controlled
with Reference
=> DR
);
209 Right
: Wide_Character) return Unbounded_Wide_String
211 DR
: Shared_Wide_String_Access
;
214 -- Result is an empty string, reuse shared empty string
217 Reference
(Empty_Shared_Wide_String
'Access);
218 DR
:= Empty_Shared_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_String) return Unbounded_Wide_String
239 DL
: constant Natural := Left
* Right
'Length;
240 DR
: Shared_Wide_String_Access
;
244 -- Result is an empty string, reuse shared empty string
247 Reference
(Empty_Shared_Wide_String
'Access);
248 DR
:= Empty_Shared_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_String
) return Unbounded_Wide_String
271 RR
: constant Shared_Wide_String_Access
:= Right
.Reference
;
272 DL
: constant Natural := Left
* RR
.Last
;
273 DR
: Shared_Wide_String_Access
;
277 -- Result is an empty string, reuse shared empty string
280 Reference
(Empty_Shared_Wide_String
'Access);
281 DR
:= Empty_Shared_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_String
;
312 Right
: Unbounded_Wide_String
) return Boolean
314 LR
: constant Shared_Wide_String_Access
:= Left
.Reference
;
315 RR
: constant Shared_Wide_String_Access
:= Right
.Reference
;
317 return LR
.Data
(1 .. LR
.Last
) < RR
.Data
(1 .. RR
.Last
);
321 (Left
: Unbounded_Wide_String
;
322 Right
: Wide_String) return Boolean
324 LR
: constant Shared_Wide_String_Access
:= Left
.Reference
;
326 return LR
.Data
(1 .. LR
.Last
) < Right
;
331 Right
: Unbounded_Wide_String
) return Boolean
333 RR
: constant Shared_Wide_String_Access
:= Right
.Reference
;
335 return Left
< RR
.Data
(1 .. RR
.Last
);
343 (Left
: Unbounded_Wide_String
;
344 Right
: Unbounded_Wide_String
) return Boolean
346 LR
: constant Shared_Wide_String_Access
:= Left
.Reference
;
347 RR
: constant Shared_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_String
;
357 Right
: Wide_String) return Boolean
359 LR
: constant Shared_Wide_String_Access
:= Left
.Reference
;
361 return LR
.Data
(1 .. LR
.Last
) <= Right
;
366 Right
: Unbounded_Wide_String
) return Boolean
368 RR
: constant Shared_Wide_String_Access
:= Right
.Reference
;
370 return Left
<= RR
.Data
(1 .. RR
.Last
);
378 (Left
: Unbounded_Wide_String
;
379 Right
: Unbounded_Wide_String
) return Boolean
381 LR
: constant Shared_Wide_String_Access
:= Left
.Reference
;
382 RR
: constant Shared_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_String
;
391 Right
: Wide_String) return Boolean
393 LR
: constant Shared_Wide_String_Access
:= Left
.Reference
;
395 return LR
.Data
(1 .. LR
.Last
) = Right
;
400 Right
: Unbounded_Wide_String
) return Boolean
402 RR
: constant Shared_Wide_String_Access
:= Right
.Reference
;
404 return Left
= RR
.Data
(1 .. RR
.Last
);
412 (Left
: Unbounded_Wide_String
;
413 Right
: Unbounded_Wide_String
) return Boolean
415 LR
: constant Shared_Wide_String_Access
:= Left
.Reference
;
416 RR
: constant Shared_Wide_String_Access
:= Right
.Reference
;
418 return LR
.Data
(1 .. LR
.Last
) > RR
.Data
(1 .. RR
.Last
);
422 (Left
: Unbounded_Wide_String
;
423 Right
: Wide_String) return Boolean
425 LR
: constant Shared_Wide_String_Access
:= Left
.Reference
;
427 return LR
.Data
(1 .. LR
.Last
) > Right
;
432 Right
: Unbounded_Wide_String
) return Boolean
434 RR
: constant Shared_Wide_String_Access
:= Right
.Reference
;
436 return Left
> RR
.Data
(1 .. RR
.Last
);
444 (Left
: Unbounded_Wide_String
;
445 Right
: Unbounded_Wide_String
) return Boolean
447 LR
: constant Shared_Wide_String_Access
:= Left
.Reference
;
448 RR
: constant Shared_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_String
;
458 Right
: Wide_String) return Boolean
460 LR
: constant Shared_Wide_String_Access
:= Left
.Reference
;
462 return LR
.Data
(1 .. LR
.Last
) >= Right
;
467 Right
: Unbounded_Wide_String
) return Boolean
469 RR
: constant Shared_Wide_String_Access
:= Right
.Reference
;
471 return Left
>= RR
.Data
(1 .. RR
.Last
);
478 procedure Adjust
(Object
: in out Unbounded_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_String
'Size / Standard
'Storage_Unit;
490 -- Total size of all static components
492 Element_Size
: constant Natural :=
493 Wide_Character'Size / Standard
'Storage_Unit;
497 (((Static_Size
+ Max_Length
* Element_Size
- 1) / Min_Mul_Alloc
+ 2)
498 * Min_Mul_Alloc
- Static_Size
) / Element_Size
;
499 end Aligned_Max_Length
;
505 function Allocate
(Max_Length
: Natural) return Shared_Wide_String_Access
is
507 -- Empty string requested, return shared empty string
509 if Max_Length
= 0 then
510 Reference
(Empty_Shared_Wide_String
'Access);
511 return Empty_Shared_Wide_String
'Access;
513 -- Otherwise, allocate requested space (and probably some more room)
516 return new Shared_Wide_String
(Aligned_Max_Length
(Max_Length
));
525 (Source
: in out Unbounded_Wide_String
;
526 New_Item
: Unbounded_Wide_String
)
528 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
529 NR
: constant Shared_Wide_String_Access
:= New_Item
.Reference
;
530 DL
: constant Natural := SR
.Last
+ NR
.Last
;
531 DR
: Shared_Wide_String_Access
;
534 -- Source is an empty string, reuse New_Item data
538 Source
.Reference
:= NR
;
541 -- New_Item is empty string, nothing to do
543 elsif NR
.Last
= 0 then
546 -- Try to reuse existent shared string
548 elsif Can_Be_Reused
(SR
, DL
) then
549 SR
.Data
(SR
.Last
+ 1 .. DL
) := NR
.Data
(1 .. NR
.Last
);
552 -- Otherwise, allocate new one and fill it
555 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
556 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
557 DR
.Data
(SR
.Last
+ 1 .. DL
) := NR
.Data
(1 .. NR
.Last
);
559 Source
.Reference
:= DR
;
565 (Source
: in out Unbounded_Wide_String
;
566 New_Item
: Wide_String)
568 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
569 DL
: constant Natural := SR
.Last
+ New_Item
'Length;
570 DR
: Shared_Wide_String_Access
;
573 -- New_Item is an empty string, nothing to do
575 if New_Item
'Length = 0 then
578 -- Try to reuse existing shared string
580 elsif Can_Be_Reused
(SR
, DL
) then
581 SR
.Data
(SR
.Last
+ 1 .. DL
) := New_Item
;
584 -- Otherwise, allocate new one and fill it
587 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
588 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
589 DR
.Data
(SR
.Last
+ 1 .. DL
) := New_Item
;
591 Source
.Reference
:= DR
;
597 (Source
: in out Unbounded_Wide_String
;
598 New_Item
: Wide_Character)
600 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
601 DL
: constant Natural := SR
.Last
+ 1;
602 DR
: Shared_Wide_String_Access
;
605 -- Try to reuse existing shared string
607 if Can_Be_Reused
(SR
, SR
.Last
+ 1) then
608 SR
.Data
(SR
.Last
+ 1) := New_Item
;
609 SR
.Last
:= SR
.Last
+ 1;
611 -- Otherwise, allocate new one and fill it
614 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
615 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
616 DR
.Data
(DL
) := New_Item
;
618 Source
.Reference
:= DR
;
627 function Can_Be_Reused
628 (Item
: Shared_Wide_String_Access
;
629 Length
: Natural) return Boolean is
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_Wide_String
;
644 Pattern
: Wide_String;
645 Mapping
: Wide_Maps
.Wide_Character_Mapping
:= Wide_Maps
.Identity
)
648 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
650 return Wide_Search
.Count
(SR
.Data
(1 .. SR
.Last
), Pattern
, Mapping
);
654 (Source
: Unbounded_Wide_String
;
655 Pattern
: Wide_String;
656 Mapping
: Wide_Maps
.Wide_Character_Mapping_Function
) return Natural
658 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
660 return Wide_Search
.Count
(SR
.Data
(1 .. SR
.Last
), Pattern
, Mapping
);
664 (Source
: Unbounded_Wide_String
;
665 Set
: Wide_Maps
.Wide_Character_Set
) return Natural
667 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
669 return Wide_Search
.Count
(SR
.Data
(1 .. SR
.Last
), Set
);
677 (Source
: Unbounded_Wide_String
;
679 Through
: Natural) return Unbounded_Wide_String
681 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
683 DR
: Shared_Wide_String_Access
;
686 -- Empty slice is deleted, use the same shared string
688 if From
> Through
then
692 -- Index is out of range
694 elsif Through
> SR
.Last
then
697 -- Compute size of the result
700 DL
:= SR
.Last
- (Through
- From
+ 1);
702 -- Result is an empty string, reuse shared empty string
705 Reference
(Empty_Shared_Wide_String
'Access);
706 DR
:= Empty_Shared_Wide_String
'Access;
708 -- Otherwise, allocate new shared string and fill it
712 DR
.Data
(1 .. From
- 1) := SR
.Data
(1 .. From
- 1);
713 DR
.Data
(From
.. DL
) := SR
.Data
(Through
+ 1 .. SR
.Last
);
718 return (AF
.Controlled
with Reference
=> DR
);
722 (Source
: in out Unbounded_Wide_String
;
726 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
728 DR
: Shared_Wide_String_Access
;
731 -- Nothing changed, return
733 if From
> Through
then
736 -- Through is outside of the range
738 elsif Through
> SR
.Last
then
742 DL
:= SR
.Last
- (Through
- From
+ 1);
744 -- Result is empty, reuse shared empty string
747 Reference
(Empty_Shared_Wide_String
'Access);
748 Source
.Reference
:= Empty_Shared_Wide_String
'Access;
751 -- Try to reuse existent shared string
753 elsif Can_Be_Reused
(SR
, DL
) then
754 SR
.Data
(From
.. DL
) := SR
.Data
(Through
+ 1 .. SR
.Last
);
757 -- Otherwise, allocate new shared string
761 DR
.Data
(1 .. From
- 1) := SR
.Data
(1 .. From
- 1);
762 DR
.Data
(From
.. DL
) := SR
.Data
(Through
+ 1 .. SR
.Last
);
764 Source
.Reference
:= DR
;
775 (Source
: Unbounded_Wide_String
;
776 Index
: Positive) return Wide_Character
778 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
780 if Index
<= SR
.Last
then
781 return SR
.Data
(Index
);
791 procedure Finalize
(Object
: in out Unbounded_Wide_String
) is
792 SR
: constant Shared_Wide_String_Access
:= Object
.Reference
;
797 -- The same controlled object can be finalized several times for
798 -- some reason. As per 7.6.1(24) this should have no ill effect,
799 -- so we need to add a guard for the case of finalizing the same
802 Object
.Reference
:= null;
812 (Source
: Unbounded_Wide_String
;
813 Set
: Wide_Maps
.Wide_Character_Set
;
815 Test
: Strings
.Membership
;
816 First
: out Positive;
819 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
821 Wide_Search
.Find_Token
822 (SR
.Data
(From
.. SR
.Last
), Set
, Test
, First
, Last
);
826 (Source
: Unbounded_Wide_String
;
827 Set
: Wide_Maps
.Wide_Character_Set
;
828 Test
: Strings
.Membership
;
829 First
: out Positive;
832 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
834 Wide_Search
.Find_Token
835 (SR
.Data
(1 .. SR
.Last
), Set
, Test
, First
, Last
);
842 procedure Free
(X
: in out Wide_String_Access
) is
843 procedure Deallocate
is
844 new Ada
.Unchecked_Deallocation
(Wide_String, Wide_String_Access
);
854 (Source
: Unbounded_Wide_String
;
856 Pad
: Wide_Character := Wide_Space
) return Unbounded_Wide_String
858 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
859 DR
: Shared_Wide_String_Access
;
862 -- Result is empty, reuse shared empty string
865 Reference
(Empty_Shared_Wide_String
'Access);
866 DR
:= Empty_Shared_Wide_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_Wide_String
;
906 Pad
: Wide_Character := Wide_Space
)
908 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
909 DR
: Shared_Wide_String_Access
;
912 -- Result is empty, reuse empty shared string
915 Reference
(Empty_Shared_Wide_String
'Access);
916 Source
.Reference
:= Empty_Shared_Wide_String
'Access;
919 -- Result is same with source string, reuse source shared string
921 elsif Count
= SR
.Last
then
924 -- Try to reuse existent 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 -- exists data and fill others by Pad character.
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_Wide_String
;
969 Pattern
: Wide_String;
970 Going
: Strings
.Direction
:= Strings
.Forward
;
971 Mapping
: Wide_Maps
.Wide_Character_Mapping
:= Wide_Maps
.Identity
)
974 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
976 return Wide_Search
.Index
977 (SR
.Data
(1 .. SR
.Last
), Pattern
, Going
, Mapping
);
981 (Source
: Unbounded_Wide_String
;
982 Pattern
: Wide_String;
983 Going
: Direction
:= Forward
;
984 Mapping
: Wide_Maps
.Wide_Character_Mapping_Function
) return Natural
986 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
988 return Wide_Search
.Index
989 (SR
.Data
(1 .. SR
.Last
), Pattern
, Going
, Mapping
);
993 (Source
: Unbounded_Wide_String
;
994 Set
: Wide_Maps
.Wide_Character_Set
;
995 Test
: Strings
.Membership
:= Strings
.Inside
;
996 Going
: Strings
.Direction
:= Strings
.Forward
) return Natural
998 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1000 return Wide_Search
.Index
(SR
.Data
(1 .. SR
.Last
), Set
, Test
, Going
);
1004 (Source
: Unbounded_Wide_String
;
1005 Pattern
: Wide_String;
1007 Going
: Direction
:= Forward
;
1008 Mapping
: Wide_Maps
.Wide_Character_Mapping
:= Wide_Maps
.Identity
)
1011 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1013 return Wide_Search
.Index
1014 (SR
.Data
(1 .. SR
.Last
), Pattern
, From
, Going
, Mapping
);
1018 (Source
: Unbounded_Wide_String
;
1019 Pattern
: Wide_String;
1021 Going
: Direction
:= Forward
;
1022 Mapping
: Wide_Maps
.Wide_Character_Mapping_Function
) return Natural
1024 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1026 return Wide_Search
.Index
1027 (SR
.Data
(1 .. SR
.Last
), Pattern
, From
, Going
, Mapping
);
1031 (Source
: Unbounded_Wide_String
;
1032 Set
: Wide_Maps
.Wide_Character_Set
;
1034 Test
: Membership
:= Inside
;
1035 Going
: Direction
:= Forward
) return Natural
1037 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1039 return Wide_Search
.Index
1040 (SR
.Data
(1 .. SR
.Last
), Set
, From
, Test
, Going
);
1043 ---------------------
1044 -- Index_Non_Blank --
1045 ---------------------
1047 function Index_Non_Blank
1048 (Source
: Unbounded_Wide_String
;
1049 Going
: Strings
.Direction
:= Strings
.Forward
) return Natural
1051 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1053 return Wide_Search
.Index_Non_Blank
(SR
.Data
(1 .. SR
.Last
), Going
);
1054 end Index_Non_Blank
;
1056 function Index_Non_Blank
1057 (Source
: Unbounded_Wide_String
;
1059 Going
: Direction
:= Forward
) return Natural
1061 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1063 return Wide_Search
.Index_Non_Blank
1064 (SR
.Data
(1 .. SR
.Last
), From
, Going
);
1065 end Index_Non_Blank
;
1071 procedure Initialize
(Object
: in out Unbounded_Wide_String
) is
1073 Reference
(Object
.Reference
);
1081 (Source
: Unbounded_Wide_String
;
1083 New_Item
: Wide_String) return Unbounded_Wide_String
1085 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1086 DL
: constant Natural := SR
.Last
+ New_Item
'Length;
1087 DR
: Shared_Wide_String_Access
;
1090 -- Check index first
1092 if Before
> SR
.Last
+ 1 then
1096 -- Result is empty, reuse empty shared string
1099 Reference
(Empty_Shared_Wide_String
'Access);
1100 DR
:= Empty_Shared_Wide_String
'Access;
1102 -- Inserted string is empty, reuse source shared string
1104 elsif New_Item
'Length = 0 then
1108 -- Otherwise, allocate new shared string and fill it
1111 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
1112 DR
.Data
(1 .. Before
- 1) := SR
.Data
(1 .. Before
- 1);
1113 DR
.Data
(Before
.. Before
+ New_Item
'Length - 1) := New_Item
;
1114 DR
.Data
(Before
+ New_Item
'Length .. DL
) :=
1115 SR
.Data
(Before
.. SR
.Last
);
1119 return (AF
.Controlled
with Reference
=> DR
);
1123 (Source
: in out Unbounded_Wide_String
;
1125 New_Item
: Wide_String)
1127 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1128 DL
: constant Natural := SR
.Last
+ New_Item
'Length;
1129 DR
: Shared_Wide_String_Access
;
1134 if Before
> SR
.Last
+ 1 then
1138 -- Result is empty string, reuse empty shared string
1141 Reference
(Empty_Shared_Wide_String
'Access);
1142 Source
.Reference
:= Empty_Shared_Wide_String
'Access;
1145 -- Inserted string is empty, nothing to do
1147 elsif New_Item
'Length = 0 then
1150 -- Try to reuse existent shared string first
1152 elsif Can_Be_Reused
(SR
, DL
) then
1153 SR
.Data
(Before
+ New_Item
'Length .. DL
) :=
1154 SR
.Data
(Before
.. SR
.Last
);
1155 SR
.Data
(Before
.. Before
+ New_Item
'Length - 1) := New_Item
;
1158 -- Otherwise, allocate new shared string and fill it
1161 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
1162 DR
.Data
(1 .. Before
- 1) := SR
.Data
(1 .. Before
- 1);
1163 DR
.Data
(Before
.. Before
+ New_Item
'Length - 1) := New_Item
;
1164 DR
.Data
(Before
+ New_Item
'Length .. DL
) :=
1165 SR
.Data
(Before
.. SR
.Last
);
1167 Source
.Reference
:= DR
;
1176 function Length
(Source
: Unbounded_Wide_String
) return Natural is
1178 return Source
.Reference
.Last
;
1186 (Source
: Unbounded_Wide_String
;
1187 Position
: Positive;
1188 New_Item
: Wide_String) return Unbounded_Wide_String
1190 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1192 DR
: Shared_Wide_String_Access
;
1197 if Position
> SR
.Last
+ 1 then
1201 DL
:= Integer'Max (SR
.Last
, Position
+ New_Item
'Length - 1);
1203 -- Result is empty string, reuse empty shared string
1206 Reference
(Empty_Shared_Wide_String
'Access);
1207 DR
:= Empty_Shared_Wide_String
'Access;
1209 -- Result is same with source string, reuse source shared string
1211 elsif New_Item
'Length = 0 then
1215 -- Otherwise, allocate new shared string and fill it
1218 DR
:= Allocate
(DL
);
1219 DR
.Data
(1 .. Position
- 1) := SR
.Data
(1 .. Position
- 1);
1220 DR
.Data
(Position
.. Position
+ New_Item
'Length - 1) := New_Item
;
1221 DR
.Data
(Position
+ New_Item
'Length .. DL
) :=
1222 SR
.Data
(Position
+ New_Item
'Length .. SR
.Last
);
1226 return (AF
.Controlled
with Reference
=> DR
);
1230 (Source
: in out Unbounded_Wide_String
;
1231 Position
: Positive;
1232 New_Item
: Wide_String)
1234 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1236 DR
: Shared_Wide_String_Access
;
1241 if Position
> SR
.Last
+ 1 then
1245 DL
:= Integer'Max (SR
.Last
, Position
+ New_Item
'Length - 1);
1247 -- Result is empty string, reuse empty shared string
1250 Reference
(Empty_Shared_Wide_String
'Access);
1251 Source
.Reference
:= Empty_Shared_Wide_String
'Access;
1254 -- String unchanged, nothing to do
1256 elsif New_Item
'Length = 0 then
1259 -- Try to reuse existent shared string
1261 elsif Can_Be_Reused
(SR
, DL
) then
1262 SR
.Data
(Position
.. Position
+ New_Item
'Length - 1) := New_Item
;
1265 -- Otherwise allocate new shared string and fill it
1268 DR
:= Allocate
(DL
);
1269 DR
.Data
(1 .. Position
- 1) := SR
.Data
(1 .. Position
- 1);
1270 DR
.Data
(Position
.. Position
+ New_Item
'Length - 1) := New_Item
;
1271 DR
.Data
(Position
+ New_Item
'Length .. DL
) :=
1272 SR
.Data
(Position
+ New_Item
'Length .. SR
.Last
);
1274 Source
.Reference
:= DR
;
1283 procedure Reference
(Item
: not null Shared_Wide_String_Access
) is
1285 System
.Atomic_Counters
.Increment
(Item
.Counter
);
1288 ---------------------
1289 -- Replace_Element --
1290 ---------------------
1292 procedure Replace_Element
1293 (Source
: in out Unbounded_Wide_String
;
1295 By
: Wide_Character)
1297 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1298 DR
: Shared_Wide_String_Access
;
1303 if Index
<= SR
.Last
then
1305 -- Try to reuse existent shared string
1307 if Can_Be_Reused
(SR
, SR
.Last
) then
1308 SR
.Data
(Index
) := By
;
1310 -- Otherwise allocate new shared string and fill it
1313 DR
:= Allocate
(SR
.Last
);
1314 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
1315 DR
.Data
(Index
) := By
;
1317 Source
.Reference
:= DR
;
1324 end Replace_Element
;
1330 function Replace_Slice
1331 (Source
: Unbounded_Wide_String
;
1334 By
: Wide_String) return Unbounded_Wide_String
1336 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1338 DR
: Shared_Wide_String_Access
;
1343 if Low
> SR
.Last
+ 1 then
1347 -- Do replace operation when removed slice is not empty
1350 DL
:= By
'Length + SR
.Last
+ Low
- Integer'Min (High
, SR
.Last
) - 1;
1351 -- This is the number of characters remaining in the string after
1352 -- replacing the slice.
1354 -- Result is empty string, reuse empty shared string
1357 Reference
(Empty_Shared_Wide_String
'Access);
1358 DR
:= Empty_Shared_Wide_String
'Access;
1360 -- Otherwise allocate new shared string and fill it
1363 DR
:= Allocate
(DL
);
1364 DR
.Data
(1 .. Low
- 1) := SR
.Data
(1 .. Low
- 1);
1365 DR
.Data
(Low
.. Low
+ By
'Length - 1) := By
;
1366 DR
.Data
(Low
+ By
'Length .. DL
) := SR
.Data
(High
+ 1 .. SR
.Last
);
1370 return (AF
.Controlled
with Reference
=> DR
);
1372 -- Otherwise just insert string
1375 return Insert
(Source
, Low
, By
);
1379 procedure Replace_Slice
1380 (Source
: in out Unbounded_Wide_String
;
1385 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1387 DR
: Shared_Wide_String_Access
;
1392 if Low
> SR
.Last
+ 1 then
1396 -- Do replace operation only when replaced slice is not empty
1399 DL
:= By
'Length + SR
.Last
+ Low
- Integer'Min (High
, SR
.Last
) - 1;
1400 -- This is the number of characters remaining in the string after
1401 -- replacing the slice.
1403 -- Result is empty string, reuse empty shared string
1406 Reference
(Empty_Shared_Wide_String
'Access);
1407 Source
.Reference
:= Empty_Shared_Wide_String
'Access;
1410 -- Try to reuse existent shared string
1412 elsif Can_Be_Reused
(SR
, DL
) then
1413 SR
.Data
(Low
+ By
'Length .. DL
) := SR
.Data
(High
+ 1 .. SR
.Last
);
1414 SR
.Data
(Low
.. Low
+ By
'Length - 1) := By
;
1417 -- Otherwise allocate new shared string and fill it
1420 DR
:= Allocate
(DL
);
1421 DR
.Data
(1 .. Low
- 1) := SR
.Data
(1 .. Low
- 1);
1422 DR
.Data
(Low
.. Low
+ By
'Length - 1) := By
;
1423 DR
.Data
(Low
+ By
'Length .. DL
) := SR
.Data
(High
+ 1 .. SR
.Last
);
1425 Source
.Reference
:= DR
;
1429 -- Otherwise just insert item
1432 Insert
(Source
, Low
, By
);
1436 -------------------------------
1437 -- Set_Unbounded_Wide_String --
1438 -------------------------------
1440 procedure Set_Unbounded_Wide_String
1441 (Target
: out Unbounded_Wide_String
;
1442 Source
: Wide_String)
1444 TR
: constant Shared_Wide_String_Access
:= Target
.Reference
;
1445 DR
: Shared_Wide_String_Access
;
1448 -- In case of empty string, reuse empty shared string
1450 if Source
'Length = 0 then
1451 Reference
(Empty_Shared_Wide_String
'Access);
1452 Target
.Reference
:= Empty_Shared_Wide_String
'Access;
1455 -- Try to reuse existent shared string
1457 if Can_Be_Reused
(TR
, Source
'Length) then
1461 -- Otherwise allocate new shared string
1464 DR
:= Allocate
(Source
'Length);
1465 Target
.Reference
:= DR
;
1468 DR
.Data
(1 .. Source
'Length) := Source
;
1469 DR
.Last
:= Source
'Length;
1473 end Set_Unbounded_Wide_String
;
1480 (Source
: Unbounded_Wide_String
;
1482 High
: Natural) return Wide_String
1484 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1487 -- Note: test of High > Length is in accordance with AI95-00128
1489 if Low
> SR
.Last
+ 1 or else High
> SR
.Last
then
1493 return SR
.Data
(Low
.. High
);
1502 (Source
: Unbounded_Wide_String
;
1504 Pad
: Wide_Character := Wide_Space
) return Unbounded_Wide_String
1506 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1507 DR
: Shared_Wide_String_Access
;
1510 -- For empty result reuse empty shared string
1513 Reference
(Empty_Shared_Wide_String
'Access);
1514 DR
:= Empty_Shared_Wide_String
'Access;
1516 -- Result is hole source string, reuse source shared string
1518 elsif Count
= SR
.Last
then
1522 -- Otherwise allocate new shared string and fill it
1525 DR
:= Allocate
(Count
);
1527 if Count
< SR
.Last
then
1528 DR
.Data
(1 .. Count
) := SR
.Data
(SR
.Last
- Count
+ 1 .. SR
.Last
);
1531 for J
in 1 .. Count
- SR
.Last
loop
1535 DR
.Data
(Count
- SR
.Last
+ 1 .. Count
) := SR
.Data
(1 .. SR
.Last
);
1541 return (AF
.Controlled
with Reference
=> DR
);
1545 (Source
: in out Unbounded_Wide_String
;
1547 Pad
: Wide_Character := Wide_Space
)
1549 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1550 DR
: Shared_Wide_String_Access
;
1553 (SR
: Shared_Wide_String_Access
;
1554 DR
: Shared_Wide_String_Access
;
1556 -- Common code of tail computation. SR/DR can point to the same object
1563 (SR
: Shared_Wide_String_Access
;
1564 DR
: Shared_Wide_String_Access
;
1567 if Count
< SR
.Last
then
1568 DR
.Data
(1 .. Count
) := SR
.Data
(SR
.Last
- Count
+ 1 .. SR
.Last
);
1571 DR
.Data
(Count
- SR
.Last
+ 1 .. Count
) := SR
.Data
(1 .. SR
.Last
);
1573 for J
in 1 .. Count
- SR
.Last
loop
1582 -- Result is empty string, reuse empty shared string
1585 Reference
(Empty_Shared_Wide_String
'Access);
1586 Source
.Reference
:= Empty_Shared_Wide_String
'Access;
1589 -- Length of the result is the same with length of the source string,
1590 -- reuse source shared string.
1592 elsif Count
= SR
.Last
then
1595 -- Try to reuse existent shared string
1597 elsif Can_Be_Reused
(SR
, Count
) then
1598 Common
(SR
, SR
, Count
);
1600 -- Otherwise allocate new shared string and fill it
1603 DR
:= Allocate
(Count
);
1604 Common
(SR
, DR
, Count
);
1605 Source
.Reference
:= DR
;
1610 --------------------
1611 -- To_Wide_String --
1612 --------------------
1614 function To_Wide_String
1615 (Source
: Unbounded_Wide_String
) return Wide_String is
1617 return Source
.Reference
.Data
(1 .. Source
.Reference
.Last
);
1620 ------------------------------
1621 -- To_Unbounded_Wide_String --
1622 ------------------------------
1624 function To_Unbounded_Wide_String
1625 (Source
: Wide_String) return Unbounded_Wide_String
1627 DR
: Shared_Wide_String_Access
;
1630 if Source
'Length = 0 then
1631 Reference
(Empty_Shared_Wide_String
'Access);
1632 DR
:= Empty_Shared_Wide_String
'Access;
1635 DR
:= Allocate
(Source
'Length);
1636 DR
.Data
(1 .. Source
'Length) := Source
;
1637 DR
.Last
:= Source
'Length;
1640 return (AF
.Controlled
with Reference
=> DR
);
1641 end To_Unbounded_Wide_String
;
1643 function To_Unbounded_Wide_String
1644 (Length
: Natural) return Unbounded_Wide_String
1646 DR
: Shared_Wide_String_Access
;
1650 Reference
(Empty_Shared_Wide_String
'Access);
1651 DR
:= Empty_Shared_Wide_String
'Access;
1654 DR
:= Allocate
(Length
);
1658 return (AF
.Controlled
with Reference
=> DR
);
1659 end To_Unbounded_Wide_String
;
1666 (Source
: Unbounded_Wide_String
;
1667 Mapping
: Wide_Maps
.Wide_Character_Mapping
) return Unbounded_Wide_String
1669 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1670 DR
: Shared_Wide_String_Access
;
1673 -- Nothing to translate, reuse empty shared string
1676 Reference
(Empty_Shared_Wide_String
'Access);
1677 DR
:= Empty_Shared_Wide_String
'Access;
1679 -- Otherwise, allocate new shared string and fill it
1682 DR
:= Allocate
(SR
.Last
);
1684 for J
in 1 .. SR
.Last
loop
1685 DR
.Data
(J
) := Value
(Mapping
, SR
.Data
(J
));
1691 return (AF
.Controlled
with Reference
=> DR
);
1695 (Source
: in out Unbounded_Wide_String
;
1696 Mapping
: Wide_Maps
.Wide_Character_Mapping
)
1698 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1699 DR
: Shared_Wide_String_Access
;
1702 -- Nothing to translate
1707 -- Try to reuse shared string
1709 elsif Can_Be_Reused
(SR
, SR
.Last
) then
1710 for J
in 1 .. SR
.Last
loop
1711 SR
.Data
(J
) := Value
(Mapping
, SR
.Data
(J
));
1714 -- Otherwise, allocate new shared string
1717 DR
:= Allocate
(SR
.Last
);
1719 for J
in 1 .. SR
.Last
loop
1720 DR
.Data
(J
) := Value
(Mapping
, SR
.Data
(J
));
1724 Source
.Reference
:= DR
;
1730 (Source
: Unbounded_Wide_String
;
1731 Mapping
: Wide_Maps
.Wide_Character_Mapping_Function
)
1732 return Unbounded_Wide_String
1734 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1735 DR
: Shared_Wide_String_Access
;
1738 -- Nothing to translate, reuse empty shared string
1741 Reference
(Empty_Shared_Wide_String
'Access);
1742 DR
:= Empty_Shared_Wide_String
'Access;
1744 -- Otherwise, allocate new shared string and fill it
1747 DR
:= Allocate
(SR
.Last
);
1749 for J
in 1 .. SR
.Last
loop
1750 DR
.Data
(J
) := Mapping
.all (SR
.Data
(J
));
1756 return (AF
.Controlled
with Reference
=> DR
);
1766 (Source
: in out Unbounded_Wide_String
;
1767 Mapping
: Wide_Maps
.Wide_Character_Mapping_Function
)
1769 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1770 DR
: Shared_Wide_String_Access
;
1773 -- Nothing to translate
1778 -- Try to reuse shared string
1780 elsif Can_Be_Reused
(SR
, SR
.Last
) then
1781 for J
in 1 .. SR
.Last
loop
1782 SR
.Data
(J
) := Mapping
.all (SR
.Data
(J
));
1785 -- Otherwise allocate new shared string and fill it
1788 DR
:= Allocate
(SR
.Last
);
1790 for J
in 1 .. SR
.Last
loop
1791 DR
.Data
(J
) := Mapping
.all (SR
.Data
(J
));
1795 Source
.Reference
:= DR
;
1813 (Source
: Unbounded_Wide_String
;
1814 Side
: Trim_End
) return Unbounded_Wide_String
1816 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1818 DR
: Shared_Wide_String_Access
;
1823 Low
:= Index_Non_Blank
(Source
, Forward
);
1825 -- All blanks, reuse empty shared string
1828 Reference
(Empty_Shared_Wide_String
'Access);
1829 DR
:= Empty_Shared_Wide_String
'Access;
1835 DL
:= SR
.Last
- Low
+ 1;
1839 High
:= Index_Non_Blank
(Source
, Backward
);
1843 High
:= Index_Non_Blank
(Source
, Backward
);
1844 DL
:= High
- Low
+ 1;
1847 -- Length of the result is the same as length of the source string,
1848 -- reuse source shared string.
1850 if DL
= SR
.Last
then
1854 -- Otherwise, allocate new shared string
1857 DR
:= Allocate
(DL
);
1858 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
1863 return (AF
.Controlled
with Reference
=> DR
);
1867 (Source
: in out Unbounded_Wide_String
;
1870 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1872 DR
: Shared_Wide_String_Access
;
1877 Low
:= Index_Non_Blank
(Source
, Forward
);
1879 -- All blanks, reuse empty shared string
1882 Reference
(Empty_Shared_Wide_String
'Access);
1883 Source
.Reference
:= Empty_Shared_Wide_String
'Access;
1890 DL
:= SR
.Last
- Low
+ 1;
1894 High
:= Index_Non_Blank
(Source
, Backward
);
1898 High
:= Index_Non_Blank
(Source
, Backward
);
1899 DL
:= High
- Low
+ 1;
1902 -- Length of the result is the same as length of the source string,
1905 if DL
= SR
.Last
then
1908 -- Try to reuse existent shared string
1910 elsif Can_Be_Reused
(SR
, DL
) then
1911 SR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
1914 -- Otherwise, allocate new shared string
1917 DR
:= Allocate
(DL
);
1918 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
1920 Source
.Reference
:= DR
;
1927 (Source
: Unbounded_Wide_String
;
1928 Left
: Wide_Maps
.Wide_Character_Set
;
1929 Right
: Wide_Maps
.Wide_Character_Set
) return Unbounded_Wide_String
1931 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1933 DR
: Shared_Wide_String_Access
;
1938 Low
:= Index
(Source
, Left
, Outside
, Forward
);
1940 -- Source includes only characters from Left set, reuse empty shared
1944 Reference
(Empty_Shared_Wide_String
'Access);
1945 DR
:= Empty_Shared_Wide_String
'Access;
1948 High
:= Index
(Source
, Right
, Outside
, Backward
);
1949 DL
:= Integer'Max (0, High
- Low
+ 1);
1951 -- Source includes only characters from Right set or result string
1952 -- is empty, reuse empty shared string.
1954 if High
= 0 or else DL
= 0 then
1955 Reference
(Empty_Shared_Wide_String
'Access);
1956 DR
:= Empty_Shared_Wide_String
'Access;
1958 -- Otherwise, allocate new shared string and fill it
1961 DR
:= Allocate
(DL
);
1962 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
1967 return (AF
.Controlled
with Reference
=> DR
);
1971 (Source
: in out Unbounded_Wide_String
;
1972 Left
: Wide_Maps
.Wide_Character_Set
;
1973 Right
: Wide_Maps
.Wide_Character_Set
)
1975 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
1977 DR
: Shared_Wide_String_Access
;
1982 Low
:= Index
(Source
, Left
, Outside
, Forward
);
1984 -- Source includes only characters from Left set, reuse empty shared
1988 Reference
(Empty_Shared_Wide_String
'Access);
1989 Source
.Reference
:= Empty_Shared_Wide_String
'Access;
1993 High
:= Index
(Source
, Right
, Outside
, Backward
);
1994 DL
:= Integer'Max (0, High
- Low
+ 1);
1996 -- Source includes only characters from Right set or result string
1997 -- is empty, reuse empty shared string.
1999 if High
= 0 or else DL
= 0 then
2000 Reference
(Empty_Shared_Wide_String
'Access);
2001 Source
.Reference
:= Empty_Shared_Wide_String
'Access;
2004 -- Try to reuse existent shared string
2006 elsif Can_Be_Reused
(SR
, DL
) then
2007 SR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2010 -- Otherwise, allocate new shared string and fill it
2013 DR
:= Allocate
(DL
);
2014 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2016 Source
.Reference
:= DR
;
2022 ---------------------
2023 -- Unbounded_Slice --
2024 ---------------------
2026 function Unbounded_Slice
2027 (Source
: Unbounded_Wide_String
;
2029 High
: Natural) return Unbounded_Wide_String
2031 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
2033 DR
: Shared_Wide_String_Access
;
2038 if Low
> SR
.Last
+ 1 or else High
> SR
.Last
then
2041 -- Result is empty slice, reuse empty shared string
2043 elsif Low
> High
then
2044 Reference
(Empty_Shared_Wide_String
'Access);
2045 DR
:= Empty_Shared_Wide_String
'Access;
2047 -- Otherwise, allocate new shared string and fill it
2050 DL
:= High
- Low
+ 1;
2051 DR
:= Allocate
(DL
);
2052 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2056 return (AF
.Controlled
with Reference
=> DR
);
2057 end Unbounded_Slice
;
2059 procedure Unbounded_Slice
2060 (Source
: Unbounded_Wide_String
;
2061 Target
: out Unbounded_Wide_String
;
2065 SR
: constant Shared_Wide_String_Access
:= Source
.Reference
;
2066 TR
: constant Shared_Wide_String_Access
:= Target
.Reference
;
2068 DR
: Shared_Wide_String_Access
;
2073 if Low
> SR
.Last
+ 1 or else High
> SR
.Last
then
2076 -- Result is empty slice, reuse empty shared string
2078 elsif Low
> High
then
2079 Reference
(Empty_Shared_Wide_String
'Access);
2080 Target
.Reference
:= Empty_Shared_Wide_String
'Access;
2084 DL
:= High
- Low
+ 1;
2086 -- Try to reuse existent shared string
2088 if Can_Be_Reused
(TR
, DL
) then
2089 TR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2092 -- Otherwise, allocate new shared string and fill it
2095 DR
:= Allocate
(DL
);
2096 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2098 Target
.Reference
:= DR
;
2102 end Unbounded_Slice
;
2108 procedure Unreference
(Item
: not null Shared_Wide_String_Access
) is
2111 new Ada
.Unchecked_Deallocation
2112 (Shared_Wide_String
, Shared_Wide_String_Access
);
2114 Aux
: Shared_Wide_String_Access
:= Item
;
2117 if System
.Atomic_Counters
.Decrement
(Aux
.Counter
) then
2119 -- Reference counter of Empty_Shared_Wide_String must never reach
2122 pragma Assert
(Aux
/= Empty_Shared_Wide_String
'Access);
2128 end Ada
.Strings
.Wide_Unbounded
;