Disable tests for strdup/strndup on __hpux__
[official-gcc.git] / gcc / ada / libgnat / a-strunb__shared.ads
blob2da9dc72b3b533ad847c61615c112f9682123160
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT RUN-TIME COMPONENTS --
4 -- --
5 -- A D A . S T R I N G S . U N B O U N D E D --
6 -- --
7 -- S p e c --
8 -- --
9 -- Copyright (C) 1992-2023, Free Software Foundation, Inc. --
10 -- --
11 -- This specification is derived from the Ada Reference Manual for use with --
12 -- GNAT. The copyright notice above, and the license provisions that follow --
13 -- apply solely to the contents of the part following the private keyword. --
14 -- --
15 -- GNAT is free software; you can redistribute it and/or modify it under --
16 -- terms of the GNU General Public License as published by the Free Soft- --
17 -- ware Foundation; either version 3, or (at your option) any later ver- --
18 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
19 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
20 -- or FITNESS FOR A PARTICULAR PURPOSE. --
21 -- --
22 -- As a special exception under Section 7 of GPL version 3, you are granted --
23 -- additional permissions described in the GCC Runtime Library Exception, --
24 -- version 3.1, as published by the Free Software Foundation. --
25 -- --
26 -- You should have received a copy of the GNU General Public License and --
27 -- a copy of the GCC Runtime Library Exception along with this program; --
28 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
29 -- <http://www.gnu.org/licenses/>. --
30 -- --
31 -- GNAT was originally developed by the GNAT team at New York University. --
32 -- Extensive contributions were provided by Ada Core Technologies Inc. --
33 -- --
34 ------------------------------------------------------------------------------
36 -- Preconditions in this unit are meant for analysis only, not for run-time
37 -- checking, so that the expected exceptions are raised. This is enforced by
38 -- setting the corresponding assertion policy to Ignore.
40 pragma Assertion_Policy (Pre => Ignore);
42 -- This package provides an implementation of Ada.Strings.Unbounded that uses
43 -- reference counts to implement copy on modification (rather than copy on
44 -- assignment). This is significantly more efficient on many targets.
46 -- This version is supported on:
47 -- - all Alpha platforms
48 -- - all AARCH64 platforms
49 -- - all ARM platforms
50 -- - all ia64 platforms
51 -- - all PowerPC platforms
52 -- - all SPARC V9 platforms
53 -- - all x86 platforms
54 -- - all x86_64 platforms
56 -- This package uses several techniques to increase speed:
58 -- - Implicit sharing or copy-on-write. An Unbounded_String contains only
59 -- the reference to the data which is shared between several instances.
60 -- The shared data is reallocated only when its value is changed and
61 -- the object mutation can't be used or it is inefficient to use it.
63 -- - Object mutation. Shared data object can be reused without memory
64 -- reallocation when all of the following requirements are met:
65 -- - the shared data object is no longer used by anyone else;
66 -- - the size is sufficient to store the new value;
67 -- - the gap after reuse is less than a defined threshold.
69 -- - Memory preallocation. Most of used memory allocation algorithms
70 -- align allocated segments on the some boundary, thus some amount of
71 -- additional memory can be preallocated without any impact. Such
72 -- preallocated memory can used later by Append/Insert operations
73 -- without reallocation.
75 -- Reference counting uses GCC builtin atomic operations, which allows safe
76 -- sharing of internal data between Ada tasks. Nevertheless, this does not
77 -- make objects of Unbounded_String thread-safe: an instance cannot be
78 -- accessed by several tasks simultaneously.
80 with Ada.Strings.Maps;
81 private with Ada.Finalization;
82 private with System.Atomic_Counters;
83 private with Ada.Strings.Text_Buffers;
85 package Ada.Strings.Unbounded with
86 Initial_Condition => Length (Null_Unbounded_String) = 0,
87 Always_Terminates
89 pragma Preelaborate;
91 type Unbounded_String is private with
92 Default_Initial_Condition => Length (Unbounded_String) = 0;
93 pragma Preelaborable_Initialization (Unbounded_String);
95 Null_Unbounded_String : constant Unbounded_String;
97 function Length (Source : Unbounded_String) return Natural with
98 Global => null;
100 type String_Access is access all String;
102 procedure Free (X : in out String_Access);
104 --------------------------------------------------------
105 -- Conversion, Concatenation, and Selection Functions --
106 --------------------------------------------------------
108 function To_Unbounded_String
109 (Source : String) return Unbounded_String
110 with
111 Post => To_String (To_Unbounded_String'Result) = Source,
112 Global => null;
114 function To_Unbounded_String
115 (Length : Natural) return Unbounded_String
116 with
117 SPARK_Mode => Off,
118 Global => null;
120 function To_String (Source : Unbounded_String) return String with
121 Post =>
122 To_String'Result'First = 1
123 and then To_String'Result'Length = Length (Source),
124 Global => null;
126 procedure Set_Unbounded_String
127 (Target : out Unbounded_String;
128 Source : String)
129 with
130 Post => To_String (Target) = Source,
131 Global => null;
132 pragma Ada_05 (Set_Unbounded_String);
134 procedure Append
135 (Source : in out Unbounded_String;
136 New_Item : Unbounded_String)
137 with
138 Pre => Length (New_Item) <= Natural'Last - Length (Source),
139 Post => Length (Source) = Length (Source)'Old + Length (New_Item),
140 Global => null;
142 procedure Append
143 (Source : in out Unbounded_String;
144 New_Item : String)
145 with
146 Pre => New_Item'Length <= Natural'Last - Length (Source),
147 Post => Length (Source) = Length (Source)'Old + New_Item'Length,
148 Global => null;
150 procedure Append
151 (Source : in out Unbounded_String;
152 New_Item : Character)
153 with
154 Pre => Length (Source) < Natural'Last,
155 Post => Length (Source) = Length (Source)'Old + 1,
156 Global => null;
158 function "&"
159 (Left : Unbounded_String;
160 Right : Unbounded_String) return Unbounded_String
161 with
162 Pre => Length (Right) <= Natural'Last - Length (Left),
163 Post => Length ("&"'Result) = Length (Left) + Length (Right),
164 Global => null;
166 function "&"
167 (Left : Unbounded_String;
168 Right : String) return Unbounded_String
169 with
170 Pre => Right'Length <= Natural'Last - Length (Left),
171 Post => Length ("&"'Result) = Length (Left) + Right'Length,
172 Global => null;
174 function "&"
175 (Left : String;
176 Right : Unbounded_String) return Unbounded_String
177 with
178 Pre => Left'Length <= Natural'Last - Length (Right),
179 Post => Length ("&"'Result) = Left'Length + Length (Right),
180 Global => null;
182 function "&"
183 (Left : Unbounded_String;
184 Right : Character) return Unbounded_String
185 with
186 Pre => Length (Left) < Natural'Last,
187 Post => Length ("&"'Result) = Length (Left) + 1,
188 Global => null;
190 function "&"
191 (Left : Character;
192 Right : Unbounded_String) return Unbounded_String
193 with
194 Pre => Length (Right) < Natural'Last,
195 Post => Length ("&"'Result) = Length (Right) + 1,
196 Global => null;
198 function Element
199 (Source : Unbounded_String;
200 Index : Positive) return Character
201 with
202 Pre => Index <= Length (Source),
203 Post => Element'Result = To_String (Source) (Index),
204 Global => null;
206 procedure Replace_Element
207 (Source : in out Unbounded_String;
208 Index : Positive;
209 By : Character)
210 with
211 Pre => Index <= Length (Source),
212 Post => Length (Source) = Length (Source)'Old,
213 Global => null;
215 function Slice
216 (Source : Unbounded_String;
217 Low : Positive;
218 High : Natural) return String
219 with
220 Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
221 Post => Slice'Result'Length = Natural'Max (0, High - Low + 1),
222 Global => null;
224 function Unbounded_Slice
225 (Source : Unbounded_String;
226 Low : Positive;
227 High : Natural) return Unbounded_String
228 with
229 Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
230 Post =>
231 Length (Unbounded_Slice'Result) = Natural'Max (0, High - Low + 1),
232 Global => null;
233 pragma Ada_05 (Unbounded_Slice);
235 procedure Unbounded_Slice
236 (Source : Unbounded_String;
237 Target : out Unbounded_String;
238 Low : Positive;
239 High : Natural)
240 with
241 Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
242 Post => Length (Target) = Natural'Max (0, High - Low + 1),
243 Global => null;
244 pragma Ada_05 (Unbounded_Slice);
246 function "="
247 (Left : Unbounded_String;
248 Right : Unbounded_String) return Boolean
249 with
250 Post => "="'Result = (To_String (Left) = To_String (Right)),
251 Global => null;
253 function "="
254 (Left : Unbounded_String;
255 Right : String) return Boolean
256 with
257 Post => "="'Result = (To_String (Left) = Right),
258 Global => null;
260 function "="
261 (Left : String;
262 Right : Unbounded_String) return Boolean
263 with
264 Post => "="'Result = (Left = To_String (Right)),
265 Global => null;
267 function "<"
268 (Left : Unbounded_String;
269 Right : Unbounded_String) return Boolean
270 with
271 Global => null;
273 function "<"
274 (Left : Unbounded_String;
275 Right : String) return Boolean
276 with
277 Global => null;
279 function "<"
280 (Left : String;
281 Right : Unbounded_String) return Boolean
282 with
283 Global => null;
285 function "<="
286 (Left : Unbounded_String;
287 Right : Unbounded_String) return Boolean
288 with
289 Global => null;
291 function "<="
292 (Left : Unbounded_String;
293 Right : String) return Boolean
294 with
295 Global => null;
297 function "<="
298 (Left : String;
299 Right : Unbounded_String) return Boolean
300 with
301 Global => null;
303 function ">"
304 (Left : Unbounded_String;
305 Right : Unbounded_String) return Boolean
306 with
307 Global => null;
309 function ">"
310 (Left : Unbounded_String;
311 Right : String) return Boolean
312 with
313 Global => null;
315 function ">"
316 (Left : String;
317 Right : Unbounded_String) return Boolean
318 with
319 Global => null;
321 function ">="
322 (Left : Unbounded_String;
323 Right : Unbounded_String) return Boolean
324 with
325 Global => null;
327 function ">="
328 (Left : Unbounded_String;
329 Right : String) return Boolean
330 with
331 Global => null;
333 function ">="
334 (Left : String;
335 Right : Unbounded_String) return Boolean
336 with
337 Global => null;
339 ------------------------
340 -- Search Subprograms --
341 ------------------------
343 function Index
344 (Source : Unbounded_String;
345 Pattern : String;
346 Going : Direction := Forward;
347 Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
348 with
349 Pre => Pattern'Length /= 0,
350 Global => null;
352 function Index
353 (Source : Unbounded_String;
354 Pattern : String;
355 Going : Direction := Forward;
356 Mapping : Maps.Character_Mapping_Function) return Natural
357 with
358 Pre => Pattern'Length /= 0,
359 Global => null;
361 function Index
362 (Source : Unbounded_String;
363 Set : Maps.Character_Set;
364 Test : Membership := Inside;
365 Going : Direction := Forward) return Natural
366 with
367 Global => null;
369 function Index
370 (Source : Unbounded_String;
371 Pattern : String;
372 From : Positive;
373 Going : Direction := Forward;
374 Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
375 with
376 Pre => (if Length (Source) /= 0 then From <= Length (Source))
377 and then Pattern'Length /= 0,
378 Global => null;
379 pragma Ada_05 (Index);
381 function Index
382 (Source : Unbounded_String;
383 Pattern : String;
384 From : Positive;
385 Going : Direction := Forward;
386 Mapping : Maps.Character_Mapping_Function) return Natural
387 with
388 Pre => (if Length (Source) /= 0 then From <= Length (Source))
389 and then Pattern'Length /= 0,
390 Global => null;
391 pragma Ada_05 (Index);
393 function Index
394 (Source : Unbounded_String;
395 Set : Maps.Character_Set;
396 From : Positive;
397 Test : Membership := Inside;
398 Going : Direction := Forward) return Natural
399 with
400 Pre => (if Length (Source) /= 0 then From <= Length (Source)),
401 Global => null;
402 pragma Ada_05 (Index);
404 function Index_Non_Blank
405 (Source : Unbounded_String;
406 Going : Direction := Forward) return Natural
407 with
408 Global => null;
410 function Index_Non_Blank
411 (Source : Unbounded_String;
412 From : Positive;
413 Going : Direction := Forward) return Natural
414 with
415 Pre => (if Length (Source) /= 0 then From <= Length (Source)),
416 Global => null;
417 pragma Ada_05 (Index_Non_Blank);
419 function Count
420 (Source : Unbounded_String;
421 Pattern : String;
422 Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
423 with
424 Pre => Pattern'Length /= 0,
425 Global => null;
427 function Count
428 (Source : Unbounded_String;
429 Pattern : String;
430 Mapping : Maps.Character_Mapping_Function) return Natural
431 with
432 Pre => Pattern'Length /= 0,
433 Global => null;
435 function Count
436 (Source : Unbounded_String;
437 Set : Maps.Character_Set) return Natural
438 with
439 Global => null;
441 procedure Find_Token
442 (Source : Unbounded_String;
443 Set : Maps.Character_Set;
444 From : Positive;
445 Test : Membership;
446 First : out Positive;
447 Last : out Natural)
448 with
449 Pre => (if Length (Source) /= 0 then From <= Length (Source)),
450 Global => null;
451 pragma Ada_2012 (Find_Token);
453 procedure Find_Token
454 (Source : Unbounded_String;
455 Set : Maps.Character_Set;
456 Test : Membership;
457 First : out Positive;
458 Last : out Natural)
459 with
460 Global => null;
462 ------------------------------------
463 -- String Translation Subprograms --
464 ------------------------------------
466 function Translate
467 (Source : Unbounded_String;
468 Mapping : Maps.Character_Mapping) return Unbounded_String
469 with
470 Post => Length (Translate'Result) = Length (Source),
471 Global => null;
473 procedure Translate
474 (Source : in out Unbounded_String;
475 Mapping : Maps.Character_Mapping)
476 with
477 Post => Length (Source) = Length (Source)'Old,
478 Global => null;
480 function Translate
481 (Source : Unbounded_String;
482 Mapping : Maps.Character_Mapping_Function) return Unbounded_String
483 with
484 Post => Length (Translate'Result) = Length (Source),
485 Global => null;
487 procedure Translate
488 (Source : in out Unbounded_String;
489 Mapping : Maps.Character_Mapping_Function)
490 with
491 Post => Length (Source) = Length (Source)'Old,
492 Global => null;
494 ---------------------------------------
495 -- String Transformation Subprograms --
496 ---------------------------------------
498 function Replace_Slice
499 (Source : Unbounded_String;
500 Low : Positive;
501 High : Natural;
502 By : String) return Unbounded_String
503 with
504 Pre =>
505 Low - 1 <= Length (Source)
506 and then (if High >= Low
507 then Low - 1
508 <= Natural'Last - By'Length
509 - Natural'Max (Length (Source) - High, 0)
510 else Length (Source) <= Natural'Last - By'Length),
511 Contract_Cases =>
512 (High >= Low =>
513 Length (Replace_Slice'Result)
514 = Low - 1 + By'Length + Natural'Max (Length (Source)'Old - High, 0),
515 others =>
516 Length (Replace_Slice'Result) = Length (Source)'Old + By'Length),
517 Global => null;
519 procedure Replace_Slice
520 (Source : in out Unbounded_String;
521 Low : Positive;
522 High : Natural;
523 By : String)
524 with
525 Pre =>
526 Low - 1 <= Length (Source)
527 and then (if High >= Low
528 then Low - 1
529 <= Natural'Last - By'Length
530 - Natural'Max (Length (Source) - High, 0)
531 else Length (Source) <= Natural'Last - By'Length),
532 Contract_Cases =>
533 (High >= Low =>
534 Length (Source)
535 = Low - 1 + By'Length + Natural'Max (Length (Source)'Old - High, 0),
536 others =>
537 Length (Source) = Length (Source)'Old + By'Length),
538 Global => null;
540 function Insert
541 (Source : Unbounded_String;
542 Before : Positive;
543 New_Item : String) return Unbounded_String
544 with
545 Pre => Before - 1 <= Length (Source)
546 and then New_Item'Length <= Natural'Last - Length (Source),
547 Post => Length (Insert'Result) = Length (Source) + New_Item'Length,
548 Global => null;
550 procedure Insert
551 (Source : in out Unbounded_String;
552 Before : Positive;
553 New_Item : String)
554 with
555 Pre => Before - 1 <= Length (Source)
556 and then New_Item'Length <= Natural'Last - Length (Source),
557 Post => Length (Source) = Length (Source)'Old + New_Item'Length,
558 Global => null;
560 function Overwrite
561 (Source : Unbounded_String;
562 Position : Positive;
563 New_Item : String) return Unbounded_String
564 with
565 Pre => Position - 1 <= Length (Source)
566 and then (if New_Item'Length /= 0
567 then
568 New_Item'Length <= Natural'Last - (Position - 1)),
569 Post =>
570 Length (Overwrite'Result)
571 = Natural'Max (Length (Source), Position - 1 + New_Item'Length),
572 Global => null;
574 procedure Overwrite
575 (Source : in out Unbounded_String;
576 Position : Positive;
577 New_Item : String)
578 with
579 Pre => Position - 1 <= Length (Source)
580 and then (if New_Item'Length /= 0
581 then
582 New_Item'Length <= Natural'Last - (Position - 1)),
583 Post =>
584 Length (Source)
585 = Natural'Max (Length (Source)'Old, Position - 1 + New_Item'Length),
587 Global => null;
589 function Delete
590 (Source : Unbounded_String;
591 From : Positive;
592 Through : Natural) return Unbounded_String
593 with
594 Pre => (if Through <= From then From - 1 <= Length (Source)),
595 Contract_Cases =>
596 (Through >= From =>
597 Length (Delete'Result) = Length (Source) - (Through - From + 1),
598 others =>
599 Length (Delete'Result) = Length (Source)),
600 Global => null;
602 procedure Delete
603 (Source : in out Unbounded_String;
604 From : Positive;
605 Through : Natural)
606 with
607 Pre => (if Through <= From then From - 1 <= Length (Source)),
608 Contract_Cases =>
609 (Through >= From =>
610 Length (Source) = Length (Source)'Old - (Through - From + 1),
611 others =>
612 Length (Source) = Length (Source)'Old),
613 Global => null;
615 function Trim
616 (Source : Unbounded_String;
617 Side : Trim_End) return Unbounded_String
618 with
619 Post => Length (Trim'Result) <= Length (Source),
620 Global => null;
622 procedure Trim
623 (Source : in out Unbounded_String;
624 Side : Trim_End)
625 with
626 Post => Length (Source) <= Length (Source)'Old,
627 Global => null;
629 function Trim
630 (Source : Unbounded_String;
631 Left : Maps.Character_Set;
632 Right : Maps.Character_Set) return Unbounded_String
633 with
634 Post => Length (Trim'Result) <= Length (Source),
635 Global => null;
637 procedure Trim
638 (Source : in out Unbounded_String;
639 Left : Maps.Character_Set;
640 Right : Maps.Character_Set)
641 with
642 Post => Length (Source) <= Length (Source)'Old,
643 Global => null;
645 function Head
646 (Source : Unbounded_String;
647 Count : Natural;
648 Pad : Character := Space) return Unbounded_String
649 with
650 Post => Length (Head'Result) = Count,
651 Global => null;
653 procedure Head
654 (Source : in out Unbounded_String;
655 Count : Natural;
656 Pad : Character := Space)
657 with
658 Post => Length (Source) = Count,
659 Global => null;
661 function Tail
662 (Source : Unbounded_String;
663 Count : Natural;
664 Pad : Character := Space) return Unbounded_String
665 with
666 Post => Length (Tail'Result) = Count,
667 Global => null;
669 procedure Tail
670 (Source : in out Unbounded_String;
671 Count : Natural;
672 Pad : Character := Space)
673 with
674 Post => Length (Source) = Count,
675 Global => null;
677 function "*"
678 (Left : Natural;
679 Right : Character) return Unbounded_String
680 with
681 Pre => Left <= Natural'Last,
682 Post => Length ("*"'Result) = Left,
683 Global => null;
685 function "*"
686 (Left : Natural;
687 Right : String) return Unbounded_String
688 with
689 Pre => (if Left /= 0 then Right'Length <= Natural'Last / Left),
690 Post => Length ("*"'Result) = Left * Right'Length,
691 Global => null;
693 function "*"
694 (Left : Natural;
695 Right : Unbounded_String) return Unbounded_String
696 with
697 Pre => (if Left /= 0 then Length (Right) <= Natural'Last / Left),
698 Post => Length ("*"'Result) = Left * Length (Right),
699 Global => null;
701 private
702 pragma Inline (Length);
704 package AF renames Ada.Finalization;
706 type Shared_String (Max_Length : Natural) is limited record
707 Counter : System.Atomic_Counters.Atomic_Counter;
708 -- Reference counter
710 Last : Natural := 0;
711 Data : String (1 .. Max_Length);
712 -- Last is the index of last significant element of the Data. All
713 -- elements with larger indexes are currently insignificant.
714 end record;
716 type Shared_String_Access is access all Shared_String;
718 procedure Reference (Item : not null Shared_String_Access);
719 -- Increment reference counter.
720 -- Do nothing if Item points to Empty_Shared_String.
722 procedure Unreference (Item : not null Shared_String_Access);
723 -- Decrement reference counter, deallocate Item when counter goes to zero.
724 -- Do nothing if Item points to Empty_Shared_String.
726 function Can_Be_Reused
727 (Item : not null Shared_String_Access;
728 Length : Natural) return Boolean;
729 -- Returns True if Shared_String can be reused. There are two criteria when
730 -- Shared_String can be reused: its reference counter must be one (thus
731 -- Shared_String is owned exclusively) and its size is sufficient to
732 -- store string with specified length effectively.
734 function Allocate
735 (Required_Length : Natural;
736 Reserved_Length : Natural := 0) return not null Shared_String_Access;
737 -- Allocates new Shared_String. Actual maximum length of allocated object
738 -- is at least the specified required length. Additional storage is
739 -- allocated to allow to store up to the specified reserved length when
740 -- possible. Returns reference to Empty_Shared_String when requested length
741 -- is zero.
743 Empty_Shared_String : aliased Shared_String (0);
745 function To_Unbounded (S : String) return Unbounded_String
746 renames To_Unbounded_String;
747 -- This renames are here only to be used in the pragma Stream_Convert
749 type Unbounded_String is new AF.Controlled with record
750 Reference : not null Shared_String_Access := Empty_Shared_String'Access;
751 end record with Put_Image => Put_Image;
753 procedure Put_Image
754 (S : in out Ada.Strings.Text_Buffers.Root_Buffer_Type'Class;
755 V : Unbounded_String);
757 pragma Stream_Convert (Unbounded_String, To_Unbounded, To_String);
758 -- Provide stream routines without dragging in Ada.Streams
760 pragma Finalize_Storage_Only (Unbounded_String);
761 -- Finalization is required only for freeing storage
763 overriding procedure Initialize (Object : in out Unbounded_String);
764 overriding procedure Adjust (Object : in out Unbounded_String);
765 overriding procedure Finalize (Object : in out Unbounded_String);
766 pragma Inline (Initialize, Adjust);
768 Null_Unbounded_String : constant Unbounded_String :=
769 (AF.Controlled with
770 Reference => Empty_Shared_String'Access);
772 end Ada.Strings.Unbounded;