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-2024, 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 procedure Non_Inlined_Append
40 (Source
: in out Unbounded_Wide_Wide_String
;
41 New_Item
: Unbounded_Wide_Wide_String
);
43 procedure Non_Inlined_Append
44 (Source
: in out Unbounded_Wide_Wide_String
;
45 New_Item
: Wide_Wide_String
);
47 procedure Non_Inlined_Append
48 (Source
: in out Unbounded_Wide_Wide_String
;
49 New_Item
: Wide_Wide_Character
);
50 -- Non_Inlined_Append are part of the respective Append method that
51 -- should not be inlined. The idea is that the code of Append is inlined.
52 -- In order to make inlining efficient it is better to have the inlined
53 -- code as small as possible. Thus most common cases are inlined and less
54 -- common cases are deferred in these functions.
56 Growth_Factor
: constant := 2;
57 -- The growth factor controls how much extra space is allocated when
58 -- we have to increase the size of an allocated unbounded string. By
59 -- allocating extra space, we avoid the need to reallocate on every
60 -- append, particularly important when a string is built up by repeated
61 -- append operations of small pieces. This is expressed as a factor so
62 -- 32 means add 1/32 of the length of the string as growth space.
64 Min_Mul_Alloc
: constant := Standard
'Maximum_Alignment;
65 -- Allocation will be done by a multiple of Min_Mul_Alloc. This causes
66 -- no memory loss as most (all?) malloc implementations are obliged to
67 -- align the returned memory on the maximum alignment as malloc does not
68 -- know the target alignment.
70 function Aligned_Max_Length
(Max_Length
: Natural) return Natural;
71 -- Returns recommended length of the shared string which is greater or
72 -- equal to specified length. Calculation take in sense alignment of
73 -- the allocated memory segments to use memory effectively by
74 -- Append/Insert/etc operations.
81 (Left
: Unbounded_Wide_Wide_String
;
82 Right
: Unbounded_Wide_Wide_String
) return Unbounded_Wide_Wide_String
84 LR
: constant Shared_Wide_Wide_String_Access
:= Left
.Reference
;
85 RR
: constant Shared_Wide_Wide_String_Access
:= Right
.Reference
;
86 DL
: constant Natural := LR
.Last
+ RR
.Last
;
87 DR
: Shared_Wide_Wide_String_Access
;
90 -- Result is an empty string, reuse shared empty string
93 Reference
(Empty_Shared_Wide_Wide_String
'Access);
94 DR
:= Empty_Shared_Wide_Wide_String
'Access;
96 -- Left string is empty, return Right string
98 elsif LR
.Last
= 0 then
102 -- Right string is empty, return Left string
104 elsif RR
.Last
= 0 then
108 -- Overwise, allocate new shared string and fill data
112 DR
.Data
(1 .. LR
.Last
) := LR
.Data
(1 .. LR
.Last
);
113 DR
.Data
(LR
.Last
+ 1 .. DL
) := RR
.Data
(1 .. RR
.Last
);
117 return (AF
.Controlled
with Reference
=> DR
);
121 (Left
: Unbounded_Wide_Wide_String
;
122 Right
: Wide_Wide_String
) return Unbounded_Wide_Wide_String
124 LR
: constant Shared_Wide_Wide_String_Access
:= Left
.Reference
;
125 DL
: constant Natural := LR
.Last
+ Right
'Length;
126 DR
: Shared_Wide_Wide_String_Access
;
129 -- Result is an empty string, reuse shared empty string
132 Reference
(Empty_Shared_Wide_Wide_String
'Access);
133 DR
:= Empty_Shared_Wide_Wide_String
'Access;
135 -- Right is an empty string, return Left string
137 elsif Right
'Length = 0 then
141 -- Otherwise, allocate new shared string and fill it
145 DR
.Data
(1 .. LR
.Last
) := LR
.Data
(1 .. LR
.Last
);
146 DR
.Data
(LR
.Last
+ 1 .. DL
) := Right
;
150 return (AF
.Controlled
with Reference
=> DR
);
154 (Left
: Wide_Wide_String
;
155 Right
: Unbounded_Wide_Wide_String
) return Unbounded_Wide_Wide_String
157 RR
: constant Shared_Wide_Wide_String_Access
:= Right
.Reference
;
158 DL
: constant Natural := Left
'Length + RR
.Last
;
159 DR
: Shared_Wide_Wide_String_Access
;
162 -- Result is an empty string, reuse shared one
165 Reference
(Empty_Shared_Wide_Wide_String
'Access);
166 DR
:= Empty_Shared_Wide_Wide_String
'Access;
168 -- Left is empty string, return Right string
170 elsif Left
'Length = 0 then
174 -- Otherwise, allocate new shared string and fill it
178 DR
.Data
(1 .. Left
'Length) := Left
;
179 DR
.Data
(Left
'Length + 1 .. DL
) := RR
.Data
(1 .. RR
.Last
);
183 return (AF
.Controlled
with Reference
=> DR
);
187 (Left
: Unbounded_Wide_Wide_String
;
188 Right
: Wide_Wide_Character
) return Unbounded_Wide_Wide_String
190 LR
: constant Shared_Wide_Wide_String_Access
:= Left
.Reference
;
191 DL
: constant Natural := LR
.Last
+ 1;
192 DR
: Shared_Wide_Wide_String_Access
;
196 DR
.Data
(1 .. LR
.Last
) := LR
.Data
(1 .. LR
.Last
);
197 DR
.Data
(DL
) := Right
;
200 return (AF
.Controlled
with Reference
=> DR
);
204 (Left
: Wide_Wide_Character
;
205 Right
: Unbounded_Wide_Wide_String
) return Unbounded_Wide_Wide_String
207 RR
: constant Shared_Wide_Wide_String_Access
:= Right
.Reference
;
208 DL
: constant Natural := 1 + RR
.Last
;
209 DR
: Shared_Wide_Wide_String_Access
;
214 DR
.Data
(2 .. DL
) := RR
.Data
(1 .. RR
.Last
);
217 return (AF
.Controlled
with Reference
=> DR
);
226 Right
: Wide_Wide_Character
) return Unbounded_Wide_Wide_String
228 DR
: Shared_Wide_Wide_String_Access
;
231 -- Result is an empty string, reuse shared empty string
234 Reference
(Empty_Shared_Wide_Wide_String
'Access);
235 DR
:= Empty_Shared_Wide_Wide_String
'Access;
237 -- Otherwise, allocate new shared string and fill it
240 DR
:= Allocate
(Left
);
242 for J
in 1 .. Left
loop
243 DR
.Data
(J
) := Right
;
249 return (AF
.Controlled
with Reference
=> DR
);
254 Right
: Wide_Wide_String
) return Unbounded_Wide_Wide_String
256 DL
: constant Natural := Left
* Right
'Length;
257 DR
: Shared_Wide_Wide_String_Access
;
261 -- Result is an empty string, reuse shared empty string
264 Reference
(Empty_Shared_Wide_Wide_String
'Access);
265 DR
:= Empty_Shared_Wide_Wide_String
'Access;
267 -- Otherwise, allocate new shared string and fill it
273 for J
in 1 .. Left
loop
274 DR
.Data
(K
.. K
+ Right
'Length - 1) := Right
;
275 K
:= K
+ Right
'Length;
281 return (AF
.Controlled
with Reference
=> DR
);
286 Right
: Unbounded_Wide_Wide_String
) return Unbounded_Wide_Wide_String
288 RR
: constant Shared_Wide_Wide_String_Access
:= Right
.Reference
;
289 DL
: constant Natural := Left
* RR
.Last
;
290 DR
: Shared_Wide_Wide_String_Access
;
294 -- Result is an empty string, reuse shared empty string
297 Reference
(Empty_Shared_Wide_Wide_String
'Access);
298 DR
:= Empty_Shared_Wide_Wide_String
'Access;
300 -- Coefficient is one, just return string itself
306 -- Otherwise, allocate new shared string and fill it
312 for J
in 1 .. Left
loop
313 DR
.Data
(K
.. K
+ RR
.Last
- 1) := RR
.Data
(1 .. RR
.Last
);
320 return (AF
.Controlled
with Reference
=> DR
);
328 (Left
: Unbounded_Wide_Wide_String
;
329 Right
: Unbounded_Wide_Wide_String
) return Boolean
331 LR
: constant Shared_Wide_Wide_String_Access
:= Left
.Reference
;
332 RR
: constant Shared_Wide_Wide_String_Access
:= Right
.Reference
;
334 return LR
.Data
(1 .. LR
.Last
) < RR
.Data
(1 .. RR
.Last
);
338 (Left
: Unbounded_Wide_Wide_String
;
339 Right
: Wide_Wide_String
) return Boolean
341 LR
: constant Shared_Wide_Wide_String_Access
:= Left
.Reference
;
343 return LR
.Data
(1 .. LR
.Last
) < Right
;
347 (Left
: Wide_Wide_String
;
348 Right
: Unbounded_Wide_Wide_String
) return Boolean
350 RR
: constant Shared_Wide_Wide_String_Access
:= Right
.Reference
;
352 return Left
< RR
.Data
(1 .. RR
.Last
);
360 (Left
: Unbounded_Wide_Wide_String
;
361 Right
: Unbounded_Wide_Wide_String
) return Boolean
363 LR
: constant Shared_Wide_Wide_String_Access
:= Left
.Reference
;
364 RR
: constant Shared_Wide_Wide_String_Access
:= Right
.Reference
;
367 -- LR = RR means two strings shares shared string, thus they are equal
369 return LR
= RR
or else LR
.Data
(1 .. LR
.Last
) <= RR
.Data
(1 .. RR
.Last
);
373 (Left
: Unbounded_Wide_Wide_String
;
374 Right
: Wide_Wide_String
) return Boolean
376 LR
: constant Shared_Wide_Wide_String_Access
:= Left
.Reference
;
378 return LR
.Data
(1 .. LR
.Last
) <= Right
;
382 (Left
: Wide_Wide_String
;
383 Right
: Unbounded_Wide_Wide_String
) return Boolean
385 RR
: constant Shared_Wide_Wide_String_Access
:= Right
.Reference
;
387 return Left
<= RR
.Data
(1 .. RR
.Last
);
395 (Left
: Unbounded_Wide_Wide_String
;
396 Right
: Unbounded_Wide_Wide_String
) return Boolean
398 LR
: constant Shared_Wide_Wide_String_Access
:= Left
.Reference
;
399 RR
: constant Shared_Wide_Wide_String_Access
:= Right
.Reference
;
402 return LR
= RR
or else LR
.Data
(1 .. LR
.Last
) = RR
.Data
(1 .. RR
.Last
);
403 -- LR = RR means two strings shares shared string, thus they are equal
407 (Left
: Unbounded_Wide_Wide_String
;
408 Right
: Wide_Wide_String
) return Boolean
410 LR
: constant Shared_Wide_Wide_String_Access
:= Left
.Reference
;
412 return LR
.Data
(1 .. LR
.Last
) = Right
;
416 (Left
: Wide_Wide_String
;
417 Right
: Unbounded_Wide_Wide_String
) return Boolean
419 RR
: constant Shared_Wide_Wide_String_Access
:= Right
.Reference
;
421 return Left
= RR
.Data
(1 .. RR
.Last
);
429 (Left
: Unbounded_Wide_Wide_String
;
430 Right
: Unbounded_Wide_Wide_String
) return Boolean
432 LR
: constant Shared_Wide_Wide_String_Access
:= Left
.Reference
;
433 RR
: constant Shared_Wide_Wide_String_Access
:= Right
.Reference
;
435 return LR
.Data
(1 .. LR
.Last
) > RR
.Data
(1 .. RR
.Last
);
439 (Left
: Unbounded_Wide_Wide_String
;
440 Right
: Wide_Wide_String
) return Boolean
442 LR
: constant Shared_Wide_Wide_String_Access
:= Left
.Reference
;
444 return LR
.Data
(1 .. LR
.Last
) > Right
;
448 (Left
: Wide_Wide_String
;
449 Right
: Unbounded_Wide_Wide_String
) return Boolean
451 RR
: constant Shared_Wide_Wide_String_Access
:= Right
.Reference
;
453 return Left
> RR
.Data
(1 .. RR
.Last
);
461 (Left
: Unbounded_Wide_Wide_String
;
462 Right
: Unbounded_Wide_Wide_String
) return Boolean
464 LR
: constant Shared_Wide_Wide_String_Access
:= Left
.Reference
;
465 RR
: constant Shared_Wide_Wide_String_Access
:= Right
.Reference
;
468 -- LR = RR means two strings shares shared string, thus they are equal
470 return LR
= RR
or else LR
.Data
(1 .. LR
.Last
) >= RR
.Data
(1 .. RR
.Last
);
474 (Left
: Unbounded_Wide_Wide_String
;
475 Right
: Wide_Wide_String
) return Boolean
477 LR
: constant Shared_Wide_Wide_String_Access
:= Left
.Reference
;
479 return LR
.Data
(1 .. LR
.Last
) >= Right
;
483 (Left
: Wide_Wide_String
;
484 Right
: Unbounded_Wide_Wide_String
) return Boolean
486 RR
: constant Shared_Wide_Wide_String_Access
:= Right
.Reference
;
488 return Left
>= RR
.Data
(1 .. RR
.Last
);
495 procedure Adjust
(Object
: in out Unbounded_Wide_Wide_String
) is
497 Reference
(Object
.Reference
);
500 ------------------------
501 -- Aligned_Max_Length --
502 ------------------------
504 function Aligned_Max_Length
(Max_Length
: Natural) return Natural is
505 Static_Size
: constant Natural :=
506 Empty_Shared_Wide_Wide_String
'Size / Standard
'Storage_Unit;
507 -- Total size of all static components
509 Element_Size
: constant Natural :=
510 Wide_Wide_Character
'Size / Standard
'Storage_Unit;
514 (((Static_Size
+ Max_Length
* Element_Size
- 1) / Min_Mul_Alloc
+ 2)
515 * Min_Mul_Alloc
- Static_Size
) / Element_Size
;
516 end Aligned_Max_Length
;
523 (Max_Length
: Natural) return Shared_Wide_Wide_String_Access
is
525 -- Empty string requested, return shared empty string
527 if Max_Length
= 0 then
528 Reference
(Empty_Shared_Wide_Wide_String
'Access);
529 return Empty_Shared_Wide_Wide_String
'Access;
531 -- Otherwise, allocate requested space (and probably some more room)
534 return new Shared_Wide_Wide_String
(Aligned_Max_Length
(Max_Length
));
543 (Source
: in out Unbounded_Wide_Wide_String
;
544 New_Item
: Unbounded_Wide_Wide_String
)
546 pragma Suppress
(All_Checks
);
547 -- Suppress checks as they are redundant with the checks done in that
550 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
551 NR
: constant Shared_Wide_Wide_String_Access
:= New_Item
.Reference
;
554 -- Source is an empty string, reuse New_Item data
558 Source
.Reference
:= NR
;
561 -- New_Item is empty string, nothing to do
563 elsif NR
.Last
= 0 then
566 -- Try to reuse existent shared string
568 elsif System
.Atomic_Counters
.Is_One
(SR
.Counter
)
569 and then NR
.Last
<= SR
.Max_Length
570 and then SR
.Max_Length
- NR
.Last
>= SR
.Last
572 SR
.Data
(SR
.Last
+ 1 .. SR
.Last
+ NR
.Last
) := NR
.Data
(1 .. NR
.Last
);
573 SR
.Last
:= SR
.Last
+ NR
.Last
;
575 -- Otherwise, allocate new one and fill it
578 Non_Inlined_Append
(Source
, New_Item
);
583 (Source
: in out Unbounded_Wide_Wide_String
;
584 New_Item
: Wide_Wide_String
)
586 pragma Suppress
(All_Checks
);
587 -- Suppress checks as they are redundant with the checks done in that
590 New_Item_Length
: constant Natural := New_Item
'Length;
591 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
594 if New_Item
'Length = 0 then
595 -- New_Item is an empty string, nothing to do
598 elsif System
.Atomic_Counters
.Is_One
(SR
.Counter
)
599 -- The following test checks in fact that
600 -- SR.Max_Length >= SR.Last + New_Item_Length without causing
602 and then New_Item_Length
<= SR
.Max_Length
603 and then SR
.Max_Length
- New_Item_Length
>= SR
.Last
605 -- Try to reuse existing shared string
606 SR
.Data
(SR
.Last
+ 1 .. SR
.Last
+ New_Item_Length
) := New_Item
;
607 SR
.Last
:= SR
.Last
+ New_Item_Length
;
610 -- Otherwise, allocate new one and fill it. Deferring the worst case
611 -- into a separate non-inlined function ensure that inlined Append
612 -- code size remains short and thus efficient.
613 Non_Inlined_Append
(Source
, New_Item
);
618 (Source
: in out Unbounded_Wide_Wide_String
;
619 New_Item
: Wide_Wide_Character
)
621 pragma Suppress
(All_Checks
);
622 -- Suppress checks as they are redundant with the checks done in that
625 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
627 if System
.Atomic_Counters
.Is_One
(SR
.Counter
)
628 and then SR
.Max_Length
> SR
.Last
630 -- Try to reuse existing shared string
631 SR
.Data
(SR
.Last
+ 1) := New_Item
;
632 SR
.Last
:= SR
.Last
+ 1;
635 -- Otherwise, allocate new one and fill it. Deferring the worst case
636 -- into a separate non-inlined function ensure that inlined Append
637 -- code size remains short and thus efficient.
638 Non_Inlined_Append
(Source
, New_Item
);
646 function Can_Be_Reused
647 (Item
: Shared_Wide_Wide_String_Access
;
648 Length
: Natural) return Boolean is
651 System
.Atomic_Counters
.Is_One
(Item
.Counter
)
652 and then Item
.Max_Length
>= Length
653 and then Item
.Max_Length
<=
654 Aligned_Max_Length
(Length
+ Length
/ Growth_Factor
);
662 (Source
: Unbounded_Wide_Wide_String
;
663 Pattern
: Wide_Wide_String
;
664 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping
:=
665 Wide_Wide_Maps
.Identity
) return Natural
667 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
669 return Wide_Wide_Search
.Count
(SR
.Data
(1 .. SR
.Last
), Pattern
, Mapping
);
673 (Source
: Unbounded_Wide_Wide_String
;
674 Pattern
: Wide_Wide_String
;
675 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping_Function
)
678 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
680 return Wide_Wide_Search
.Count
(SR
.Data
(1 .. SR
.Last
), Pattern
, Mapping
);
684 (Source
: Unbounded_Wide_Wide_String
;
685 Set
: Wide_Wide_Maps
.Wide_Wide_Character_Set
) return Natural
687 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
689 return Wide_Wide_Search
.Count
(SR
.Data
(1 .. SR
.Last
), Set
);
697 (Source
: Unbounded_Wide_Wide_String
;
699 Through
: Natural) return Unbounded_Wide_Wide_String
701 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
703 DR
: Shared_Wide_Wide_String_Access
;
706 -- Empty slice is deleted, use the same shared string
708 if From
> Through
then
712 -- Index is out of range
714 elsif Through
> SR
.Last
then
717 -- Compute size of the result
720 DL
:= SR
.Last
- (Through
- From
+ 1);
722 -- Result is an empty string, reuse shared empty string
725 Reference
(Empty_Shared_Wide_Wide_String
'Access);
726 DR
:= Empty_Shared_Wide_Wide_String
'Access;
728 -- Otherwise, allocate new shared string and fill it
732 DR
.Data
(1 .. From
- 1) := SR
.Data
(1 .. From
- 1);
733 DR
.Data
(From
.. DL
) := SR
.Data
(Through
+ 1 .. SR
.Last
);
738 return (AF
.Controlled
with Reference
=> DR
);
742 (Source
: in out Unbounded_Wide_Wide_String
;
746 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
748 DR
: Shared_Wide_Wide_String_Access
;
751 -- Nothing changed, return
753 if From
> Through
then
756 -- Through is outside of the range
758 elsif Through
> SR
.Last
then
762 DL
:= SR
.Last
- (Through
- From
+ 1);
764 -- Result is empty, reuse shared empty string
767 Reference
(Empty_Shared_Wide_Wide_String
'Access);
768 Source
.Reference
:= Empty_Shared_Wide_Wide_String
'Access;
771 -- Try to reuse existent shared string
773 elsif Can_Be_Reused
(SR
, DL
) then
774 SR
.Data
(From
.. DL
) := SR
.Data
(Through
+ 1 .. SR
.Last
);
777 -- Otherwise, allocate new shared string
781 DR
.Data
(1 .. From
- 1) := SR
.Data
(1 .. From
- 1);
782 DR
.Data
(From
.. DL
) := SR
.Data
(Through
+ 1 .. SR
.Last
);
784 Source
.Reference
:= DR
;
795 (Source
: Unbounded_Wide_Wide_String
;
796 Index
: Positive) return Wide_Wide_Character
798 pragma Suppress
(All_Checks
);
799 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
801 if Index
<= SR
.Last
then
802 return SR
.Data
(Index
);
812 procedure Finalize
(Object
: in out Unbounded_Wide_Wide_String
) is
813 SR
: constant Shared_Wide_Wide_String_Access
:= Object
.Reference
;
818 -- The same controlled object can be finalized several times for
819 -- some reason. As per 7.6.1(24) this should have no ill effect,
820 -- so we need to add a guard for the case of finalizing the same
823 Object
.Reference
:= null;
833 (Source
: Unbounded_Wide_Wide_String
;
834 Set
: Wide_Wide_Maps
.Wide_Wide_Character_Set
;
836 Test
: Strings
.Membership
;
837 First
: out Positive;
840 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
842 Wide_Wide_Search
.Find_Token
843 (SR
.Data
(From
.. SR
.Last
), Set
, Test
, First
, Last
);
847 (Source
: Unbounded_Wide_Wide_String
;
848 Set
: Wide_Wide_Maps
.Wide_Wide_Character_Set
;
849 Test
: Strings
.Membership
;
850 First
: out Positive;
853 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
855 Wide_Wide_Search
.Find_Token
856 (SR
.Data
(1 .. SR
.Last
), Set
, Test
, First
, Last
);
863 procedure Free
(X
: in out Wide_Wide_String_Access
) is
864 procedure Deallocate
is
865 new Ada
.Unchecked_Deallocation
866 (Wide_Wide_String
, Wide_Wide_String_Access
);
876 (Source
: Unbounded_Wide_Wide_String
;
878 Pad
: Wide_Wide_Character
:= Wide_Wide_Space
)
879 return Unbounded_Wide_Wide_String
881 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
882 DR
: Shared_Wide_Wide_String_Access
;
885 -- Result is empty, reuse shared empty string
888 Reference
(Empty_Shared_Wide_Wide_String
'Access);
889 DR
:= Empty_Shared_Wide_Wide_String
'Access;
891 -- Length of the string is the same as requested, reuse source shared
894 elsif Count
= SR
.Last
then
898 -- Otherwise, allocate new shared string and fill it
901 DR
:= Allocate
(Count
);
903 -- Length of the source string is more than requested, copy
904 -- corresponding slice.
906 if Count
< SR
.Last
then
907 DR
.Data
(1 .. Count
) := SR
.Data
(1 .. Count
);
909 -- Length of the source string is less than requested, copy all
910 -- contents and fill others by Pad character.
913 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
915 for J
in SR
.Last
+ 1 .. Count
loop
923 return (AF
.Controlled
with Reference
=> DR
);
927 (Source
: in out Unbounded_Wide_Wide_String
;
929 Pad
: Wide_Wide_Character
:= Wide_Wide_Space
)
931 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
932 DR
: Shared_Wide_Wide_String_Access
;
935 -- Result is empty, reuse empty shared string
938 Reference
(Empty_Shared_Wide_Wide_String
'Access);
939 Source
.Reference
:= Empty_Shared_Wide_Wide_String
'Access;
942 -- Result is same with source string, reuse source shared string
944 elsif Count
= SR
.Last
then
947 -- Try to reuse existent shared string
949 elsif Can_Be_Reused
(SR
, Count
) then
950 if Count
> SR
.Last
then
951 for J
in SR
.Last
+ 1 .. Count
loop
958 -- Otherwise, allocate new shared string and fill it
961 DR
:= Allocate
(Count
);
963 -- Length of the source string is greater than requested, copy
964 -- corresponding slice.
966 if Count
< SR
.Last
then
967 DR
.Data
(1 .. Count
) := SR
.Data
(1 .. Count
);
969 -- Length of the source string is less than requested, copy all
970 -- exists data and fill others by Pad character.
973 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
975 for J
in SR
.Last
+ 1 .. Count
loop
981 Source
.Reference
:= DR
;
991 (Source
: Unbounded_Wide_Wide_String
;
992 Pattern
: Wide_Wide_String
;
993 Going
: Strings
.Direction
:= Strings
.Forward
;
994 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping
:=
995 Wide_Wide_Maps
.Identity
) return Natural
997 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
999 return Wide_Wide_Search
.Index
1000 (SR
.Data
(1 .. SR
.Last
), Pattern
, Going
, Mapping
);
1004 (Source
: Unbounded_Wide_Wide_String
;
1005 Pattern
: Wide_Wide_String
;
1006 Going
: Direction
:= Forward
;
1007 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping_Function
)
1010 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1012 return Wide_Wide_Search
.Index
1013 (SR
.Data
(1 .. SR
.Last
), Pattern
, Going
, Mapping
);
1017 (Source
: Unbounded_Wide_Wide_String
;
1018 Set
: Wide_Wide_Maps
.Wide_Wide_Character_Set
;
1019 Test
: Strings
.Membership
:= Strings
.Inside
;
1020 Going
: Strings
.Direction
:= Strings
.Forward
) return Natural
1022 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1024 return Wide_Wide_Search
.Index
(SR
.Data
(1 .. SR
.Last
), Set
, Test
, Going
);
1028 (Source
: Unbounded_Wide_Wide_String
;
1029 Pattern
: Wide_Wide_String
;
1031 Going
: Direction
:= Forward
;
1032 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping
:=
1033 Wide_Wide_Maps
.Identity
) return Natural
1035 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1037 return Wide_Wide_Search
.Index
1038 (SR
.Data
(1 .. SR
.Last
), Pattern
, From
, Going
, Mapping
);
1042 (Source
: Unbounded_Wide_Wide_String
;
1043 Pattern
: Wide_Wide_String
;
1045 Going
: Direction
:= Forward
;
1046 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping_Function
)
1049 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1051 return Wide_Wide_Search
.Index
1052 (SR
.Data
(1 .. SR
.Last
), Pattern
, From
, Going
, Mapping
);
1056 (Source
: Unbounded_Wide_Wide_String
;
1057 Set
: Wide_Wide_Maps
.Wide_Wide_Character_Set
;
1059 Test
: Membership
:= Inside
;
1060 Going
: Direction
:= Forward
) return Natural
1062 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1064 return Wide_Wide_Search
.Index
1065 (SR
.Data
(1 .. SR
.Last
), Set
, From
, Test
, Going
);
1068 ---------------------
1069 -- Index_Non_Blank --
1070 ---------------------
1072 function Index_Non_Blank
1073 (Source
: Unbounded_Wide_Wide_String
;
1074 Going
: Strings
.Direction
:= Strings
.Forward
) return Natural
1076 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1078 return Wide_Wide_Search
.Index_Non_Blank
(SR
.Data
(1 .. SR
.Last
), Going
);
1079 end Index_Non_Blank
;
1081 function Index_Non_Blank
1082 (Source
: Unbounded_Wide_Wide_String
;
1084 Going
: Direction
:= Forward
) return Natural
1086 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1088 return Wide_Wide_Search
.Index_Non_Blank
1089 (SR
.Data
(1 .. SR
.Last
), From
, Going
);
1090 end Index_Non_Blank
;
1096 procedure Initialize
(Object
: in out Unbounded_Wide_Wide_String
) is
1098 Reference
(Object
.Reference
);
1106 (Source
: Unbounded_Wide_Wide_String
;
1108 New_Item
: Wide_Wide_String
) return Unbounded_Wide_Wide_String
1110 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1111 DL
: constant Natural := SR
.Last
+ New_Item
'Length;
1112 DR
: Shared_Wide_Wide_String_Access
;
1115 -- Check index first
1117 if Before
> SR
.Last
+ 1 then
1121 -- Result is empty, reuse empty shared string
1124 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1125 DR
:= Empty_Shared_Wide_Wide_String
'Access;
1127 -- Inserted string is empty, reuse source shared string
1129 elsif New_Item
'Length = 0 then
1133 -- Otherwise, allocate new shared string and fill it
1136 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
1137 DR
.Data
(1 .. Before
- 1) := SR
.Data
(1 .. Before
- 1);
1138 DR
.Data
(Before
.. Before
+ New_Item
'Length - 1) := New_Item
;
1139 DR
.Data
(Before
+ New_Item
'Length .. DL
) :=
1140 SR
.Data
(Before
.. SR
.Last
);
1144 return (AF
.Controlled
with Reference
=> DR
);
1148 (Source
: in out Unbounded_Wide_Wide_String
;
1150 New_Item
: Wide_Wide_String
)
1152 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1153 DL
: constant Natural := SR
.Last
+ New_Item
'Length;
1154 DR
: Shared_Wide_Wide_String_Access
;
1159 if Before
> SR
.Last
+ 1 then
1163 -- Result is empty string, reuse empty shared string
1166 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1167 Source
.Reference
:= Empty_Shared_Wide_Wide_String
'Access;
1170 -- Inserted string is empty, nothing to do
1172 elsif New_Item
'Length = 0 then
1175 -- Try to reuse existent shared string first
1177 elsif Can_Be_Reused
(SR
, DL
) then
1178 SR
.Data
(Before
+ New_Item
'Length .. DL
) :=
1179 SR
.Data
(Before
.. SR
.Last
);
1180 SR
.Data
(Before
.. Before
+ New_Item
'Length - 1) := New_Item
;
1183 -- Otherwise, allocate new shared string and fill it
1186 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
1187 DR
.Data
(1 .. Before
- 1) := SR
.Data
(1 .. Before
- 1);
1188 DR
.Data
(Before
.. Before
+ New_Item
'Length - 1) := New_Item
;
1189 DR
.Data
(Before
+ New_Item
'Length .. DL
) :=
1190 SR
.Data
(Before
.. SR
.Last
);
1192 Source
.Reference
:= DR
;
1201 function Length
(Source
: Unbounded_Wide_Wide_String
) return Natural is
1203 return Source
.Reference
.Last
;
1206 ------------------------
1207 -- Non_Inlined_Append --
1208 ------------------------
1210 procedure Non_Inlined_Append
1211 (Source
: in out Unbounded_Wide_Wide_String
;
1212 New_Item
: Unbounded_Wide_Wide_String
)
1214 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1215 NR
: constant Shared_Wide_Wide_String_Access
:= New_Item
.Reference
;
1216 DL
: constant Natural := SR
.Last
+ NR
.Last
;
1217 DR
: Shared_Wide_Wide_String_Access
;
1219 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
1220 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
1221 DR
.Data
(SR
.Last
+ 1 .. DL
) := NR
.Data
(1 .. NR
.Last
);
1223 Source
.Reference
:= DR
;
1225 end Non_Inlined_Append
;
1227 procedure Non_Inlined_Append
1228 (Source
: in out Unbounded_Wide_Wide_String
;
1229 New_Item
: Wide_Wide_String
)
1231 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1232 DL
: constant Natural := SR
.Last
+ New_Item
'Length;
1233 DR
: Shared_Wide_Wide_String_Access
;
1235 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
1236 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
1237 DR
.Data
(SR
.Last
+ 1 .. DL
) := New_Item
;
1239 Source
.Reference
:= DR
;
1241 end Non_Inlined_Append
;
1243 procedure Non_Inlined_Append
1244 (Source
: in out Unbounded_Wide_Wide_String
;
1245 New_Item
: Wide_Wide_Character
)
1247 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1249 if SR
.Last
= Natural'Last then
1250 raise Constraint_Error
;
1253 DL
: constant Natural := SR
.Last
+ 1;
1254 DR
: Shared_Wide_Wide_String_Access
;
1256 DR
:= Allocate
(DL
+ DL
/ Growth_Factor
);
1257 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
1258 DR
.Data
(DL
) := New_Item
;
1260 Source
.Reference
:= DR
;
1264 end Non_Inlined_Append
;
1271 (Source
: Unbounded_Wide_Wide_String
;
1272 Position
: Positive;
1273 New_Item
: Wide_Wide_String
) return Unbounded_Wide_Wide_String
1275 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1277 DR
: Shared_Wide_Wide_String_Access
;
1282 if Position
> SR
.Last
+ 1 then
1286 DL
:= Integer'Max (SR
.Last
, Position
+ New_Item
'Length - 1);
1288 -- Result is empty string, reuse empty shared string
1291 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1292 DR
:= Empty_Shared_Wide_Wide_String
'Access;
1294 -- Result is same with source string, reuse source shared string
1296 elsif New_Item
'Length = 0 then
1300 -- Otherwise, allocate new shared string and fill it
1303 DR
:= Allocate
(DL
);
1304 DR
.Data
(1 .. Position
- 1) := SR
.Data
(1 .. Position
- 1);
1305 DR
.Data
(Position
.. Position
+ New_Item
'Length - 1) := New_Item
;
1306 DR
.Data
(Position
+ New_Item
'Length .. DL
) :=
1307 SR
.Data
(Position
+ New_Item
'Length .. SR
.Last
);
1311 return (AF
.Controlled
with Reference
=> DR
);
1315 (Source
: in out Unbounded_Wide_Wide_String
;
1316 Position
: Positive;
1317 New_Item
: Wide_Wide_String
)
1319 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1321 DR
: Shared_Wide_Wide_String_Access
;
1326 if Position
> SR
.Last
+ 1 then
1330 DL
:= Integer'Max (SR
.Last
, Position
+ New_Item
'Length - 1);
1332 -- Result is empty string, reuse empty shared string
1335 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1336 Source
.Reference
:= Empty_Shared_Wide_Wide_String
'Access;
1339 -- String unchanged, nothing to do
1341 elsif New_Item
'Length = 0 then
1344 -- Try to reuse existent shared string
1346 elsif Can_Be_Reused
(SR
, DL
) then
1347 SR
.Data
(Position
.. Position
+ New_Item
'Length - 1) := New_Item
;
1350 -- Otherwise allocate new shared string and fill it
1353 DR
:= Allocate
(DL
);
1354 DR
.Data
(1 .. Position
- 1) := SR
.Data
(1 .. Position
- 1);
1355 DR
.Data
(Position
.. Position
+ New_Item
'Length - 1) := New_Item
;
1356 DR
.Data
(Position
+ New_Item
'Length .. DL
) :=
1357 SR
.Data
(Position
+ New_Item
'Length .. SR
.Last
);
1359 Source
.Reference
:= DR
;
1368 procedure Reference
(Item
: not null Shared_Wide_Wide_String_Access
) is
1370 System
.Atomic_Counters
.Increment
(Item
.Counter
);
1373 ---------------------
1374 -- Replace_Element --
1375 ---------------------
1377 procedure Replace_Element
1378 (Source
: in out Unbounded_Wide_Wide_String
;
1380 By
: Wide_Wide_Character
)
1382 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1383 DR
: Shared_Wide_Wide_String_Access
;
1388 if Index
<= SR
.Last
then
1390 -- Try to reuse existent shared string
1392 if Can_Be_Reused
(SR
, SR
.Last
) then
1393 SR
.Data
(Index
) := By
;
1395 -- Otherwise allocate new shared string and fill it
1398 DR
:= Allocate
(SR
.Last
);
1399 DR
.Data
(1 .. SR
.Last
) := SR
.Data
(1 .. SR
.Last
);
1400 DR
.Data
(Index
) := By
;
1402 Source
.Reference
:= DR
;
1409 end Replace_Element
;
1415 function Replace_Slice
1416 (Source
: Unbounded_Wide_Wide_String
;
1419 By
: Wide_Wide_String
) return Unbounded_Wide_Wide_String
1421 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1423 DR
: Shared_Wide_Wide_String_Access
;
1428 if Low
> SR
.Last
+ 1 then
1432 -- Do replace operation when removed slice is not empty
1435 DL
:= By
'Length + SR
.Last
+ Low
- Integer'Min (High
, SR
.Last
) - 1;
1436 -- This is the number of characters remaining in the string after
1437 -- replacing the slice.
1439 -- Result is empty string, reuse empty shared string
1442 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1443 DR
:= Empty_Shared_Wide_Wide_String
'Access;
1445 -- Otherwise allocate new shared string and fill it
1448 DR
:= Allocate
(DL
);
1449 DR
.Data
(1 .. Low
- 1) := SR
.Data
(1 .. Low
- 1);
1450 DR
.Data
(Low
.. Low
+ By
'Length - 1) := By
;
1451 DR
.Data
(Low
+ By
'Length .. DL
) := SR
.Data
(High
+ 1 .. SR
.Last
);
1455 return (AF
.Controlled
with Reference
=> DR
);
1457 -- Otherwise just insert string
1460 return Insert
(Source
, Low
, By
);
1464 procedure Replace_Slice
1465 (Source
: in out Unbounded_Wide_Wide_String
;
1468 By
: Wide_Wide_String
)
1470 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1472 DR
: Shared_Wide_Wide_String_Access
;
1477 if Low
> SR
.Last
+ 1 then
1481 -- Do replace operation only when replaced slice is not empty
1484 DL
:= By
'Length + SR
.Last
+ Low
- Integer'Min (High
, SR
.Last
) - 1;
1485 -- This is the number of characters remaining in the string after
1486 -- replacing the slice.
1488 -- Result is empty string, reuse empty shared string
1491 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1492 Source
.Reference
:= Empty_Shared_Wide_Wide_String
'Access;
1495 -- Try to reuse existent shared string
1497 elsif Can_Be_Reused
(SR
, DL
) then
1498 SR
.Data
(Low
+ By
'Length .. DL
) := SR
.Data
(High
+ 1 .. SR
.Last
);
1499 SR
.Data
(Low
.. Low
+ By
'Length - 1) := By
;
1502 -- Otherwise allocate new shared string and fill it
1505 DR
:= Allocate
(DL
);
1506 DR
.Data
(1 .. Low
- 1) := SR
.Data
(1 .. Low
- 1);
1507 DR
.Data
(Low
.. Low
+ By
'Length - 1) := By
;
1508 DR
.Data
(Low
+ By
'Length .. DL
) := SR
.Data
(High
+ 1 .. SR
.Last
);
1510 Source
.Reference
:= DR
;
1514 -- Otherwise just insert item
1517 Insert
(Source
, Low
, By
);
1521 -------------------------------
1522 -- Set_Unbounded_Wide_Wide_String --
1523 -------------------------------
1525 procedure Set_Unbounded_Wide_Wide_String
1526 (Target
: out Unbounded_Wide_Wide_String
;
1527 Source
: Wide_Wide_String
)
1529 TR
: constant Shared_Wide_Wide_String_Access
:= Target
.Reference
;
1530 DR
: Shared_Wide_Wide_String_Access
;
1533 -- In case of empty string, reuse empty shared string
1535 if Source
'Length = 0 then
1536 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1537 Target
.Reference
:= Empty_Shared_Wide_Wide_String
'Access;
1540 -- Try to reuse existent shared string
1542 if Can_Be_Reused
(TR
, Source
'Length) then
1546 -- Otherwise allocate new shared string
1549 DR
:= Allocate
(Source
'Length);
1550 Target
.Reference
:= DR
;
1553 DR
.Data
(1 .. Source
'Length) := Source
;
1554 DR
.Last
:= Source
'Length;
1558 end Set_Unbounded_Wide_Wide_String
;
1565 (Source
: Unbounded_Wide_Wide_String
;
1567 High
: Natural) return Wide_Wide_String
1569 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1572 -- Note: test of High > Length is in accordance with AI95-00128
1574 if Low
> SR
.Last
+ 1 or else High
> SR
.Last
then
1578 return SR
.Data
(Low
.. High
);
1587 (Source
: Unbounded_Wide_Wide_String
;
1589 Pad
: Wide_Wide_Character
:= Wide_Wide_Space
)
1590 return Unbounded_Wide_Wide_String
1592 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1593 DR
: Shared_Wide_Wide_String_Access
;
1596 -- For empty result reuse empty shared string
1599 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1600 DR
:= Empty_Shared_Wide_Wide_String
'Access;
1602 -- Result is hole source string, reuse source shared string
1604 elsif Count
= SR
.Last
then
1608 -- Otherwise allocate new shared string and fill it
1611 DR
:= Allocate
(Count
);
1613 if Count
< SR
.Last
then
1614 DR
.Data
(1 .. Count
) := SR
.Data
(SR
.Last
- Count
+ 1 .. SR
.Last
);
1617 for J
in 1 .. Count
- SR
.Last
loop
1621 DR
.Data
(Count
- SR
.Last
+ 1 .. Count
) := SR
.Data
(1 .. SR
.Last
);
1627 return (AF
.Controlled
with Reference
=> DR
);
1631 (Source
: in out Unbounded_Wide_Wide_String
;
1633 Pad
: Wide_Wide_Character
:= Wide_Wide_Space
)
1635 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1636 DR
: Shared_Wide_Wide_String_Access
;
1639 (SR
: Shared_Wide_Wide_String_Access
;
1640 DR
: Shared_Wide_Wide_String_Access
;
1642 -- Common code of tail computation. SR/DR can point to the same object
1649 (SR
: Shared_Wide_Wide_String_Access
;
1650 DR
: Shared_Wide_Wide_String_Access
;
1653 if Count
< SR
.Last
then
1654 DR
.Data
(1 .. Count
) := SR
.Data
(SR
.Last
- Count
+ 1 .. SR
.Last
);
1657 DR
.Data
(Count
- SR
.Last
+ 1 .. Count
) := SR
.Data
(1 .. SR
.Last
);
1659 for J
in 1 .. Count
- SR
.Last
loop
1668 -- Result is empty string, reuse empty shared string
1671 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1672 Source
.Reference
:= Empty_Shared_Wide_Wide_String
'Access;
1675 -- Length of the result is the same with length of the source string,
1676 -- reuse source shared string.
1678 elsif Count
= SR
.Last
then
1681 -- Try to reuse existent shared string
1683 elsif Can_Be_Reused
(SR
, Count
) then
1684 Common
(SR
, SR
, Count
);
1686 -- Otherwise allocate new shared string and fill it
1689 DR
:= Allocate
(Count
);
1690 Common
(SR
, DR
, Count
);
1691 Source
.Reference
:= DR
;
1696 -------------------------
1697 -- To_Wide_Wide_String --
1698 -------------------------
1700 function To_Wide_Wide_String
1701 (Source
: Unbounded_Wide_Wide_String
) return Wide_Wide_String
is
1703 return Source
.Reference
.Data
(1 .. Source
.Reference
.Last
);
1704 end To_Wide_Wide_String
;
1706 -----------------------------------
1707 -- To_Unbounded_Wide_Wide_String --
1708 -----------------------------------
1710 function To_Unbounded_Wide_Wide_String
1711 (Source
: Wide_Wide_String
) return Unbounded_Wide_Wide_String
1713 DR
: Shared_Wide_Wide_String_Access
;
1716 if Source
'Length = 0 then
1717 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1718 DR
:= Empty_Shared_Wide_Wide_String
'Access;
1721 DR
:= Allocate
(Source
'Length);
1722 DR
.Data
(1 .. Source
'Length) := Source
;
1723 DR
.Last
:= Source
'Length;
1726 return (AF
.Controlled
with Reference
=> DR
);
1727 end To_Unbounded_Wide_Wide_String
;
1729 function To_Unbounded_Wide_Wide_String
1730 (Length
: Natural) return Unbounded_Wide_Wide_String
1732 DR
: Shared_Wide_Wide_String_Access
;
1736 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1737 DR
:= Empty_Shared_Wide_Wide_String
'Access;
1740 DR
:= Allocate
(Length
);
1744 return (AF
.Controlled
with Reference
=> DR
);
1745 end To_Unbounded_Wide_Wide_String
;
1752 (Source
: Unbounded_Wide_Wide_String
;
1753 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping
)
1754 return Unbounded_Wide_Wide_String
1756 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1757 DR
: Shared_Wide_Wide_String_Access
;
1760 -- Nothing to translate, reuse empty shared string
1763 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1764 DR
:= Empty_Shared_Wide_Wide_String
'Access;
1766 -- Otherwise, allocate new shared string and fill it
1769 DR
:= Allocate
(SR
.Last
);
1771 for J
in 1 .. SR
.Last
loop
1772 DR
.Data
(J
) := Value
(Mapping
, SR
.Data
(J
));
1778 return (AF
.Controlled
with Reference
=> DR
);
1782 (Source
: in out Unbounded_Wide_Wide_String
;
1783 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping
)
1785 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1786 DR
: Shared_Wide_Wide_String_Access
;
1789 -- Nothing to translate
1794 -- Try to reuse shared string
1796 elsif Can_Be_Reused
(SR
, SR
.Last
) then
1797 for J
in 1 .. SR
.Last
loop
1798 SR
.Data
(J
) := Value
(Mapping
, SR
.Data
(J
));
1801 -- Otherwise, allocate new shared string
1804 DR
:= Allocate
(SR
.Last
);
1806 for J
in 1 .. SR
.Last
loop
1807 DR
.Data
(J
) := Value
(Mapping
, SR
.Data
(J
));
1811 Source
.Reference
:= DR
;
1817 (Source
: Unbounded_Wide_Wide_String
;
1818 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping_Function
)
1819 return Unbounded_Wide_Wide_String
1821 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1822 DR
: Shared_Wide_Wide_String_Access
;
1825 -- Nothing to translate, reuse empty shared string
1828 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1829 DR
:= Empty_Shared_Wide_Wide_String
'Access;
1831 -- Otherwise, allocate new shared string and fill it
1834 DR
:= Allocate
(SR
.Last
);
1836 for J
in 1 .. SR
.Last
loop
1837 DR
.Data
(J
) := Mapping
.all (SR
.Data
(J
));
1843 return (AF
.Controlled
with Reference
=> DR
);
1853 (Source
: in out Unbounded_Wide_Wide_String
;
1854 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping_Function
)
1856 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1857 DR
: Shared_Wide_Wide_String_Access
;
1860 -- Nothing to translate
1865 -- Try to reuse shared string
1867 elsif Can_Be_Reused
(SR
, SR
.Last
) then
1868 for J
in 1 .. SR
.Last
loop
1869 SR
.Data
(J
) := Mapping
.all (SR
.Data
(J
));
1872 -- Otherwise allocate new shared string and fill it
1875 DR
:= Allocate
(SR
.Last
);
1877 for J
in 1 .. SR
.Last
loop
1878 DR
.Data
(J
) := Mapping
.all (SR
.Data
(J
));
1882 Source
.Reference
:= DR
;
1900 (Source
: Unbounded_Wide_Wide_String
;
1901 Side
: Trim_End
) return Unbounded_Wide_Wide_String
1903 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1905 DR
: Shared_Wide_Wide_String_Access
;
1910 Low
:= Index_Non_Blank
(Source
, Forward
);
1912 -- All blanks, reuse empty shared string
1915 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1916 DR
:= Empty_Shared_Wide_Wide_String
'Access;
1922 DL
:= SR
.Last
- Low
+ 1;
1926 High
:= Index_Non_Blank
(Source
, Backward
);
1930 High
:= Index_Non_Blank
(Source
, Backward
);
1931 DL
:= High
- Low
+ 1;
1934 -- Length of the result is the same as length of the source string,
1935 -- reuse source shared string.
1937 if DL
= SR
.Last
then
1941 -- Otherwise, allocate new shared string
1944 DR
:= Allocate
(DL
);
1945 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
1950 return (AF
.Controlled
with Reference
=> DR
);
1954 (Source
: in out Unbounded_Wide_Wide_String
;
1957 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
1959 DR
: Shared_Wide_Wide_String_Access
;
1964 Low
:= Index_Non_Blank
(Source
, Forward
);
1966 -- All blanks, reuse empty shared string
1969 Reference
(Empty_Shared_Wide_Wide_String
'Access);
1970 Source
.Reference
:= Empty_Shared_Wide_Wide_String
'Access;
1977 DL
:= SR
.Last
- Low
+ 1;
1981 High
:= Index_Non_Blank
(Source
, Backward
);
1985 High
:= Index_Non_Blank
(Source
, Backward
);
1986 DL
:= High
- Low
+ 1;
1989 -- Length of the result is the same as length of the source string,
1992 if DL
= SR
.Last
then
1995 -- Try to reuse existent shared string
1997 elsif Can_Be_Reused
(SR
, DL
) then
1998 SR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2001 -- Otherwise, allocate new shared string
2004 DR
:= Allocate
(DL
);
2005 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2007 Source
.Reference
:= DR
;
2014 (Source
: Unbounded_Wide_Wide_String
;
2015 Left
: Wide_Wide_Maps
.Wide_Wide_Character_Set
;
2016 Right
: Wide_Wide_Maps
.Wide_Wide_Character_Set
)
2017 return Unbounded_Wide_Wide_String
2019 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
2021 DR
: Shared_Wide_Wide_String_Access
;
2026 Low
:= Index
(Source
, Left
, Outside
, Forward
);
2028 -- Source includes only characters from Left set, reuse empty shared
2032 Reference
(Empty_Shared_Wide_Wide_String
'Access);
2033 DR
:= Empty_Shared_Wide_Wide_String
'Access;
2036 High
:= Index
(Source
, Right
, Outside
, Backward
);
2037 DL
:= Integer'Max (0, High
- Low
+ 1);
2039 -- Source includes only characters from Right set or result string
2040 -- is empty, reuse empty shared string.
2042 if High
= 0 or else DL
= 0 then
2043 Reference
(Empty_Shared_Wide_Wide_String
'Access);
2044 DR
:= Empty_Shared_Wide_Wide_String
'Access;
2046 -- Otherwise, allocate new shared string and fill it
2049 DR
:= Allocate
(DL
);
2050 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2055 return (AF
.Controlled
with Reference
=> DR
);
2059 (Source
: in out Unbounded_Wide_Wide_String
;
2060 Left
: Wide_Wide_Maps
.Wide_Wide_Character_Set
;
2061 Right
: Wide_Wide_Maps
.Wide_Wide_Character_Set
)
2063 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
2065 DR
: Shared_Wide_Wide_String_Access
;
2070 Low
:= Index
(Source
, Left
, Outside
, Forward
);
2072 -- Source includes only characters from Left set, reuse empty shared
2076 Reference
(Empty_Shared_Wide_Wide_String
'Access);
2077 Source
.Reference
:= Empty_Shared_Wide_Wide_String
'Access;
2081 High
:= Index
(Source
, Right
, Outside
, Backward
);
2082 DL
:= Integer'Max (0, High
- Low
+ 1);
2084 -- Source includes only characters from Right set or result string
2085 -- is empty, reuse empty shared string.
2087 if High
= 0 or else DL
= 0 then
2088 Reference
(Empty_Shared_Wide_Wide_String
'Access);
2089 Source
.Reference
:= Empty_Shared_Wide_Wide_String
'Access;
2092 -- Try to reuse existent shared string
2094 elsif Can_Be_Reused
(SR
, DL
) then
2095 SR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2098 -- Otherwise, allocate new shared string and fill it
2101 DR
:= Allocate
(DL
);
2102 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2104 Source
.Reference
:= DR
;
2110 ---------------------
2111 -- Unbounded_Slice --
2112 ---------------------
2114 function Unbounded_Slice
2115 (Source
: Unbounded_Wide_Wide_String
;
2117 High
: Natural) return Unbounded_Wide_Wide_String
2119 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
2121 DR
: Shared_Wide_Wide_String_Access
;
2126 if Low
> SR
.Last
+ 1 or else High
> SR
.Last
then
2129 -- Result is empty slice, reuse empty shared string
2131 elsif Low
> High
then
2132 Reference
(Empty_Shared_Wide_Wide_String
'Access);
2133 DR
:= Empty_Shared_Wide_Wide_String
'Access;
2135 -- Otherwise, allocate new shared string and fill it
2138 DL
:= High
- Low
+ 1;
2139 DR
:= Allocate
(DL
);
2140 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2144 return (AF
.Controlled
with Reference
=> DR
);
2145 end Unbounded_Slice
;
2147 procedure Unbounded_Slice
2148 (Source
: Unbounded_Wide_Wide_String
;
2149 Target
: out Unbounded_Wide_Wide_String
;
2153 SR
: constant Shared_Wide_Wide_String_Access
:= Source
.Reference
;
2154 TR
: constant Shared_Wide_Wide_String_Access
:= Target
.Reference
;
2156 DR
: Shared_Wide_Wide_String_Access
;
2161 if Low
> SR
.Last
+ 1 or else High
> SR
.Last
then
2164 -- Result is empty slice, reuse empty shared string
2166 elsif Low
> High
then
2167 Reference
(Empty_Shared_Wide_Wide_String
'Access);
2168 Target
.Reference
:= Empty_Shared_Wide_Wide_String
'Access;
2172 DL
:= High
- Low
+ 1;
2174 -- Try to reuse existent shared string
2176 if Can_Be_Reused
(TR
, DL
) then
2177 TR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2180 -- Otherwise, allocate new shared string and fill it
2183 DR
:= Allocate
(DL
);
2184 DR
.Data
(1 .. DL
) := SR
.Data
(Low
.. High
);
2186 Target
.Reference
:= DR
;
2190 end Unbounded_Slice
;
2196 procedure Unreference
(Item
: not null Shared_Wide_Wide_String_Access
) is
2199 new Ada
.Unchecked_Deallocation
2200 (Shared_Wide_Wide_String
, Shared_Wide_Wide_String_Access
);
2202 Aux
: Shared_Wide_Wide_String_Access
:= Item
;
2205 if System
.Atomic_Counters
.Decrement
(Aux
.Counter
) then
2207 -- Reference counter of Empty_Shared_Wide_Wide_String must never
2210 pragma Assert
(Aux
/= Empty_Shared_Wide_Wide_String
'Access);
2216 end Ada
.Strings
.Wide_Wide_Unbounded
;