1------------------------------------------------------------------------------ 2-- -- 3-- GNAT RUN-TIME COMPONENTS -- 4-- -- 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 -- 6-- -- 7-- B o d y -- 8-- -- 9-- Copyright (C) 1992-2018, Free Software Foundation, Inc. -- 10-- -- 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. -- 17-- -- 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. -- 21-- -- 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/>. -- 26-- -- 27-- GNAT was originally developed by the GNAT team at New York University. -- 28-- Extensive contributions were provided by Ada Core Technologies Inc. -- 29-- -- 30------------------------------------------------------------------------------ 31 32with Ada.Strings.Wide_Wide_Fixed; 33with Ada.Strings.Wide_Wide_Search; 34with Ada.Unchecked_Deallocation; 35 36package body Ada.Strings.Wide_Wide_Unbounded is 37 38 --------- 39 -- "&" -- 40 --------- 41 42 function "&" 43 (Left : Unbounded_Wide_Wide_String; 44 Right : Unbounded_Wide_Wide_String) return Unbounded_Wide_Wide_String 45 is 46 L_Length : constant Natural := Left.Last; 47 R_Length : constant Natural := Right.Last; 48 Result : Unbounded_Wide_Wide_String; 49 50 begin 51 Result.Last := L_Length + R_Length; 52 53 Result.Reference := new Wide_Wide_String (1 .. Result.Last); 54 55 Result.Reference (1 .. L_Length) := 56 Left.Reference (1 .. Left.Last); 57 Result.Reference (L_Length + 1 .. Result.Last) := 58 Right.Reference (1 .. Right.Last); 59 60 return Result; 61 end "&"; 62 63 function "&" 64 (Left : Unbounded_Wide_Wide_String; 65 Right : Wide_Wide_String) return Unbounded_Wide_Wide_String 66 is 67 L_Length : constant Natural := Left.Last; 68 Result : Unbounded_Wide_Wide_String; 69 70 begin 71 Result.Last := L_Length + Right'Length; 72 73 Result.Reference := new Wide_Wide_String (1 .. Result.Last); 74 75 Result.Reference (1 .. L_Length) := Left.Reference (1 .. Left.Last); 76 Result.Reference (L_Length + 1 .. Result.Last) := Right; 77 78 return Result; 79 end "&"; 80 81 function "&" 82 (Left : Wide_Wide_String; 83 Right : Unbounded_Wide_Wide_String) return Unbounded_Wide_Wide_String 84 is 85 R_Length : constant Natural := Right.Last; 86 Result : Unbounded_Wide_Wide_String; 87 88 begin 89 Result.Last := Left'Length + R_Length; 90 91 Result.Reference := new Wide_Wide_String (1 .. Result.Last); 92 93 Result.Reference (1 .. Left'Length) := Left; 94 Result.Reference (Left'Length + 1 .. Result.Last) := 95 Right.Reference (1 .. Right.Last); 96 97 return Result; 98 end "&"; 99 100 function "&" 101 (Left : Unbounded_Wide_Wide_String; 102 Right : Wide_Wide_Character) return Unbounded_Wide_Wide_String 103 is 104 Result : Unbounded_Wide_Wide_String; 105 106 begin 107 Result.Last := Left.Last + 1; 108 109 Result.Reference := new Wide_Wide_String (1 .. Result.Last); 110 111 Result.Reference (1 .. Result.Last - 1) := 112 Left.Reference (1 .. Left.Last); 113 Result.Reference (Result.Last) := Right; 114 115 return Result; 116 end "&"; 117 118 function "&" 119 (Left : Wide_Wide_Character; 120 Right : Unbounded_Wide_Wide_String) return Unbounded_Wide_Wide_String 121 is 122 Result : Unbounded_Wide_Wide_String; 123 124 begin 125 Result.Last := Right.Last + 1; 126 127 Result.Reference := new Wide_Wide_String (1 .. Result.Last); 128 Result.Reference (1) := Left; 129 Result.Reference (2 .. Result.Last) := 130 Right.Reference (1 .. Right.Last); 131 return Result; 132 end "&"; 133 134 --------- 135 -- "*" -- 136 --------- 137 138 function "*" 139 (Left : Natural; 140 Right : Wide_Wide_Character) return Unbounded_Wide_Wide_String 141 is 142 Result : Unbounded_Wide_Wide_String; 143 144 begin 145 Result.Last := Left; 146 147 Result.Reference := new Wide_Wide_String (1 .. Left); 148 for J in Result.Reference'Range loop 149 Result.Reference (J) := Right; 150 end loop; 151 152 return Result; 153 end "*"; 154 155 function "*" 156 (Left : Natural; 157 Right : Wide_Wide_String) return Unbounded_Wide_Wide_String 158 is 159 Len : constant Natural := Right'Length; 160 K : Positive; 161 Result : Unbounded_Wide_Wide_String; 162 163 begin 164 Result.Last := Left * Len; 165 166 Result.Reference := new Wide_Wide_String (1 .. Result.Last); 167 168 K := 1; 169 for J in 1 .. Left loop 170 Result.Reference (K .. K + Len - 1) := Right; 171 K := K + Len; 172 end loop; 173 174 return Result; 175 end "*"; 176 177 function "*" 178 (Left : Natural; 179 Right : Unbounded_Wide_Wide_String) return Unbounded_Wide_Wide_String 180 is 181 Len : constant Natural := Right.Last; 182 K : Positive; 183 Result : Unbounded_Wide_Wide_String; 184 185 begin 186 Result.Last := Left * Len; 187 188 Result.Reference := new Wide_Wide_String (1 .. Result.Last); 189 190 K := 1; 191 for J in 1 .. Left loop 192 Result.Reference (K .. K + Len - 1) := 193 Right.Reference (1 .. Right.Last); 194 K := K + Len; 195 end loop; 196 197 return Result; 198 end "*"; 199 200 --------- 201 -- "<" -- 202 --------- 203 204 function "<" 205 (Left : Unbounded_Wide_Wide_String; 206 Right : Unbounded_Wide_Wide_String) return Boolean 207 is 208 begin 209 return 210 Left.Reference (1 .. Left.Last) < Right.Reference (1 .. Right.Last); 211 end "<"; 212 213 function "<" 214 (Left : Unbounded_Wide_Wide_String; 215 Right : Wide_Wide_String) return Boolean 216 is 217 begin 218 return Left.Reference (1 .. Left.Last) < Right; 219 end "<"; 220 221 function "<" 222 (Left : Wide_Wide_String; 223 Right : Unbounded_Wide_Wide_String) return Boolean 224 is 225 begin 226 return Left < Right.Reference (1 .. Right.Last); 227 end "<"; 228 229 ---------- 230 -- "<=" -- 231 ---------- 232 233 function "<=" 234 (Left : Unbounded_Wide_Wide_String; 235 Right : Unbounded_Wide_Wide_String) return Boolean 236 is 237 begin 238 return 239 Left.Reference (1 .. Left.Last) <= Right.Reference (1 .. Right.Last); 240 end "<="; 241 242 function "<=" 243 (Left : Unbounded_Wide_Wide_String; 244 Right : Wide_Wide_String) return Boolean 245 is 246 begin 247 return Left.Reference (1 .. Left.Last) <= Right; 248 end "<="; 249 250 function "<=" 251 (Left : Wide_Wide_String; 252 Right : Unbounded_Wide_Wide_String) return Boolean 253 is 254 begin 255 return Left <= Right.Reference (1 .. Right.Last); 256 end "<="; 257 258 --------- 259 -- "=" -- 260 --------- 261 262 function "=" 263 (Left : Unbounded_Wide_Wide_String; 264 Right : Unbounded_Wide_Wide_String) return Boolean 265 is 266 begin 267 return 268 Left.Reference (1 .. Left.Last) = Right.Reference (1 .. Right.Last); 269 end "="; 270 271 function "=" 272 (Left : Unbounded_Wide_Wide_String; 273 Right : Wide_Wide_String) return Boolean 274 is 275 begin 276 return Left.Reference (1 .. Left.Last) = Right; 277 end "="; 278 279 function "=" 280 (Left : Wide_Wide_String; 281 Right : Unbounded_Wide_Wide_String) return Boolean 282 is 283 begin 284 return Left = Right.Reference (1 .. Right.Last); 285 end "="; 286 287 --------- 288 -- ">" -- 289 --------- 290 291 function ">" 292 (Left : Unbounded_Wide_Wide_String; 293 Right : Unbounded_Wide_Wide_String) return Boolean 294 is 295 begin 296 return 297 Left.Reference (1 .. Left.Last) > Right.Reference (1 .. Right.Last); 298 end ">"; 299 300 function ">" 301 (Left : Unbounded_Wide_Wide_String; 302 Right : Wide_Wide_String) return Boolean 303 is 304 begin 305 return Left.Reference (1 .. Left.Last) > Right; 306 end ">"; 307 308 function ">" 309 (Left : Wide_Wide_String; 310 Right : Unbounded_Wide_Wide_String) return Boolean 311 is 312 begin 313 return Left > Right.Reference (1 .. Right.Last); 314 end ">"; 315 316 ---------- 317 -- ">=" -- 318 ---------- 319 320 function ">=" 321 (Left : Unbounded_Wide_Wide_String; 322 Right : Unbounded_Wide_Wide_String) return Boolean 323 is 324 begin 325 return 326 Left.Reference (1 .. Left.Last) >= Right.Reference (1 .. Right.Last); 327 end ">="; 328 329 function ">=" 330 (Left : Unbounded_Wide_Wide_String; 331 Right : Wide_Wide_String) return Boolean 332 is 333 begin 334 return Left.Reference (1 .. Left.Last) >= Right; 335 end ">="; 336 337 function ">=" 338 (Left : Wide_Wide_String; 339 Right : Unbounded_Wide_Wide_String) return Boolean 340 is 341 begin 342 return Left >= Right.Reference (1 .. Right.Last); 343 end ">="; 344 345 ------------ 346 -- Adjust -- 347 ------------ 348 349 procedure Adjust (Object : in out Unbounded_Wide_Wide_String) is 350 begin 351 -- Copy string, except we do not copy the statically allocated null 352 -- string, since it can never be deallocated. Note that we do not copy 353 -- extra string room here to avoid dragging unused allocated memory. 354 355 if Object.Reference /= Null_Wide_Wide_String'Access then 356 Object.Reference := 357 new Wide_Wide_String'(Object.Reference (1 .. Object.Last)); 358 end if; 359 end Adjust; 360 361 ------------ 362 -- Append -- 363 ------------ 364 365 procedure Append 366 (Source : in out Unbounded_Wide_Wide_String; 367 New_Item : Unbounded_Wide_Wide_String) 368 is 369 begin 370 Realloc_For_Chunk (Source, New_Item.Last); 371 Source.Reference (Source.Last + 1 .. Source.Last + New_Item.Last) := 372 New_Item.Reference (1 .. New_Item.Last); 373 Source.Last := Source.Last + New_Item.Last; 374 end Append; 375 376 procedure Append 377 (Source : in out Unbounded_Wide_Wide_String; 378 New_Item : Wide_Wide_String) 379 is 380 begin 381 Realloc_For_Chunk (Source, New_Item'Length); 382 Source.Reference (Source.Last + 1 .. Source.Last + New_Item'Length) := 383 New_Item; 384 Source.Last := Source.Last + New_Item'Length; 385 end Append; 386 387 procedure Append 388 (Source : in out Unbounded_Wide_Wide_String; 389 New_Item : Wide_Wide_Character) 390 is 391 begin 392 Realloc_For_Chunk (Source, 1); 393 Source.Reference (Source.Last + 1) := New_Item; 394 Source.Last := Source.Last + 1; 395 end Append; 396 397 ----------- 398 -- Count -- 399 ----------- 400 401 function Count 402 (Source : Unbounded_Wide_Wide_String; 403 Pattern : Wide_Wide_String; 404 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping := 405 Wide_Wide_Maps.Identity) return Natural 406 is 407 begin 408 return 409 Wide_Wide_Search.Count 410 (Source.Reference (1 .. Source.Last), Pattern, Mapping); 411 end Count; 412 413 function Count 414 (Source : Unbounded_Wide_Wide_String; 415 Pattern : Wide_Wide_String; 416 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping_Function) 417 return Natural 418 is 419 begin 420 return 421 Wide_Wide_Search.Count 422 (Source.Reference (1 .. Source.Last), Pattern, Mapping); 423 end Count; 424 425 function Count 426 (Source : Unbounded_Wide_Wide_String; 427 Set : Wide_Wide_Maps.Wide_Wide_Character_Set) return Natural 428 is 429 begin 430 return 431 Wide_Wide_Search.Count 432 (Source.Reference (1 .. Source.Last), Set); 433 end Count; 434 435 ------------ 436 -- Delete -- 437 ------------ 438 439 function Delete 440 (Source : Unbounded_Wide_Wide_String; 441 From : Positive; 442 Through : Natural) return Unbounded_Wide_Wide_String 443 is 444 begin 445 return 446 To_Unbounded_Wide_Wide_String 447 (Wide_Wide_Fixed.Delete 448 (Source.Reference (1 .. Source.Last), From, Through)); 449 end Delete; 450 451 procedure Delete 452 (Source : in out Unbounded_Wide_Wide_String; 453 From : Positive; 454 Through : Natural) 455 is 456 begin 457 if From > Through then 458 null; 459 460 elsif From < Source.Reference'First or else Through > Source.Last then 461 raise Index_Error; 462 463 else 464 declare 465 Len : constant Natural := Through - From + 1; 466 467 begin 468 Source.Reference (From .. Source.Last - Len) := 469 Source.Reference (Through + 1 .. Source.Last); 470 Source.Last := Source.Last - Len; 471 end; 472 end if; 473 end Delete; 474 475 ------------- 476 -- Element -- 477 ------------- 478 479 function Element 480 (Source : Unbounded_Wide_Wide_String; 481 Index : Positive) return Wide_Wide_Character 482 is 483 begin 484 if Index <= Source.Last then 485 return Source.Reference (Index); 486 else 487 raise Strings.Index_Error; 488 end if; 489 end Element; 490 491 -------------- 492 -- Finalize -- 493 -------------- 494 495 procedure Finalize (Object : in out Unbounded_Wide_Wide_String) is 496 procedure Deallocate is 497 new Ada.Unchecked_Deallocation 498 (Wide_Wide_String, Wide_Wide_String_Access); 499 500 begin 501 -- Note: Don't try to free statically allocated null string 502 503 if Object.Reference /= Null_Wide_Wide_String'Access then 504 Deallocate (Object.Reference); 505 Object.Reference := Null_Unbounded_Wide_Wide_String.Reference; 506 Object.Last := 0; 507 end if; 508 end Finalize; 509 510 ---------------- 511 -- Find_Token -- 512 ---------------- 513 514 procedure Find_Token 515 (Source : Unbounded_Wide_Wide_String; 516 Set : Wide_Wide_Maps.Wide_Wide_Character_Set; 517 From : Positive; 518 Test : Strings.Membership; 519 First : out Positive; 520 Last : out Natural) 521 is 522 begin 523 Wide_Wide_Search.Find_Token 524 (Source.Reference (From .. Source.Last), Set, Test, First, Last); 525 end Find_Token; 526 527 procedure Find_Token 528 (Source : Unbounded_Wide_Wide_String; 529 Set : Wide_Wide_Maps.Wide_Wide_Character_Set; 530 Test : Strings.Membership; 531 First : out Positive; 532 Last : out Natural) 533 is 534 begin 535 Wide_Wide_Search.Find_Token 536 (Source.Reference (1 .. Source.Last), Set, Test, First, Last); 537 end Find_Token; 538 539 ---------- 540 -- Free -- 541 ---------- 542 543 procedure Free (X : in out Wide_Wide_String_Access) is 544 procedure Deallocate is 545 new Ada.Unchecked_Deallocation 546 (Wide_Wide_String, Wide_Wide_String_Access); 547 548 begin 549 -- Note: Do not try to free statically allocated null string 550 551 if X /= Null_Unbounded_Wide_Wide_String.Reference then 552 Deallocate (X); 553 end if; 554 end Free; 555 556 ---------- 557 -- Head -- 558 ---------- 559 560 function Head 561 (Source : Unbounded_Wide_Wide_String; 562 Count : Natural; 563 Pad : Wide_Wide_Character := Wide_Wide_Space) 564 return Unbounded_Wide_Wide_String 565 is 566 begin 567 return To_Unbounded_Wide_Wide_String 568 (Wide_Wide_Fixed.Head 569 (Source.Reference (1 .. Source.Last), Count, Pad)); 570 end Head; 571 572 procedure Head 573 (Source : in out Unbounded_Wide_Wide_String; 574 Count : Natural; 575 Pad : Wide_Wide_Character := Wide_Wide_Space) 576 is 577 Old : Wide_Wide_String_Access := Source.Reference; 578 begin 579 Source.Reference := 580 new Wide_Wide_String' 581 (Wide_Wide_Fixed.Head 582 (Source.Reference (1 .. Source.Last), Count, Pad)); 583 Source.Last := Source.Reference'Length; 584 Free (Old); 585 end Head; 586 587 ----------- 588 -- Index -- 589 ----------- 590 591 function Index 592 (Source : Unbounded_Wide_Wide_String; 593 Pattern : Wide_Wide_String; 594 Going : Strings.Direction := Strings.Forward; 595 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping := 596 Wide_Wide_Maps.Identity) return Natural 597 is 598 begin 599 return 600 Wide_Wide_Search.Index 601 (Source.Reference (1 .. Source.Last), Pattern, Going, Mapping); 602 end Index; 603 604 function Index 605 (Source : Unbounded_Wide_Wide_String; 606 Pattern : Wide_Wide_String; 607 Going : Direction := Forward; 608 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping_Function) 609 return Natural 610 is 611 begin 612 return 613 Wide_Wide_Search.Index 614 (Source.Reference (1 .. Source.Last), Pattern, Going, Mapping); 615 end Index; 616 617 function Index 618 (Source : Unbounded_Wide_Wide_String; 619 Set : Wide_Wide_Maps.Wide_Wide_Character_Set; 620 Test : Strings.Membership := Strings.Inside; 621 Going : Strings.Direction := Strings.Forward) return Natural 622 is 623 begin 624 return Wide_Wide_Search.Index 625 (Source.Reference (1 .. Source.Last), Set, Test, Going); 626 end Index; 627 628 function Index 629 (Source : Unbounded_Wide_Wide_String; 630 Pattern : Wide_Wide_String; 631 From : Positive; 632 Going : Direction := Forward; 633 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping := 634 Wide_Wide_Maps.Identity) return Natural 635 is 636 begin 637 return 638 Wide_Wide_Search.Index 639 (Source.Reference (1 .. Source.Last), Pattern, From, Going, Mapping); 640 end Index; 641 642 function Index 643 (Source : Unbounded_Wide_Wide_String; 644 Pattern : Wide_Wide_String; 645 From : Positive; 646 Going : Direction := Forward; 647 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping_Function) 648 return Natural 649 is 650 begin 651 return 652 Wide_Wide_Search.Index 653 (Source.Reference (1 .. Source.Last), Pattern, From, Going, Mapping); 654 end Index; 655 656 function Index 657 (Source : Unbounded_Wide_Wide_String; 658 Set : Wide_Wide_Maps.Wide_Wide_Character_Set; 659 From : Positive; 660 Test : Membership := Inside; 661 Going : Direction := Forward) return Natural 662 is 663 begin 664 return 665 Wide_Wide_Search.Index 666 (Source.Reference (1 .. Source.Last), Set, From, Test, Going); 667 end Index; 668 669 function Index_Non_Blank 670 (Source : Unbounded_Wide_Wide_String; 671 Going : Strings.Direction := Strings.Forward) return Natural 672 is 673 begin 674 return 675 Wide_Wide_Search.Index_Non_Blank 676 (Source.Reference (1 .. Source.Last), Going); 677 end Index_Non_Blank; 678 679 function Index_Non_Blank 680 (Source : Unbounded_Wide_Wide_String; 681 From : Positive; 682 Going : Direction := Forward) return Natural 683 is 684 begin 685 return 686 Wide_Wide_Search.Index_Non_Blank 687 (Source.Reference (1 .. Source.Last), From, Going); 688 end Index_Non_Blank; 689 690 ---------------- 691 -- Initialize -- 692 ---------------- 693 694 procedure Initialize (Object : in out Unbounded_Wide_Wide_String) is 695 begin 696 Object.Reference := Null_Unbounded_Wide_Wide_String.Reference; 697 Object.Last := 0; 698 end Initialize; 699 700 ------------ 701 -- Insert -- 702 ------------ 703 704 function Insert 705 (Source : Unbounded_Wide_Wide_String; 706 Before : Positive; 707 New_Item : Wide_Wide_String) return Unbounded_Wide_Wide_String 708 is 709 begin 710 return 711 To_Unbounded_Wide_Wide_String 712 (Wide_Wide_Fixed.Insert 713 (Source.Reference (1 .. Source.Last), Before, New_Item)); 714 end Insert; 715 716 procedure Insert 717 (Source : in out Unbounded_Wide_Wide_String; 718 Before : Positive; 719 New_Item : Wide_Wide_String) 720 is 721 begin 722 if Before not in Source.Reference'First .. Source.Last + 1 then 723 raise Index_Error; 724 end if; 725 726 Realloc_For_Chunk (Source, New_Item'Length); 727 728 Source.Reference 729 (Before + New_Item'Length .. Source.Last + New_Item'Length) := 730 Source.Reference (Before .. Source.Last); 731 732 Source.Reference (Before .. Before + New_Item'Length - 1) := New_Item; 733 Source.Last := Source.Last + New_Item'Length; 734 end Insert; 735 736 ------------ 737 -- Length -- 738 ------------ 739 740 function Length (Source : Unbounded_Wide_Wide_String) return Natural is 741 begin 742 return Source.Last; 743 end Length; 744 745 --------------- 746 -- Overwrite -- 747 --------------- 748 749 function Overwrite 750 (Source : Unbounded_Wide_Wide_String; 751 Position : Positive; 752 New_Item : Wide_Wide_String) return Unbounded_Wide_Wide_String 753 is 754 begin 755 return 756 To_Unbounded_Wide_Wide_String 757 (Wide_Wide_Fixed.Overwrite 758 (Source.Reference (1 .. Source.Last), Position, New_Item)); 759 end Overwrite; 760 761 procedure Overwrite 762 (Source : in out Unbounded_Wide_Wide_String; 763 Position : Positive; 764 New_Item : Wide_Wide_String) 765 is 766 NL : constant Natural := New_Item'Length; 767 begin 768 if Position <= Source.Last - NL + 1 then 769 Source.Reference (Position .. Position + NL - 1) := New_Item; 770 else 771 declare 772 Old : Wide_Wide_String_Access := Source.Reference; 773 begin 774 Source.Reference := new Wide_Wide_String' 775 (Wide_Wide_Fixed.Overwrite 776 (Source.Reference (1 .. Source.Last), Position, New_Item)); 777 Source.Last := Source.Reference'Length; 778 Free (Old); 779 end; 780 end if; 781 end Overwrite; 782 783 ----------------------- 784 -- Realloc_For_Chunk -- 785 ----------------------- 786 787 procedure Realloc_For_Chunk 788 (Source : in out Unbounded_Wide_Wide_String; 789 Chunk_Size : Natural) 790 is 791 Growth_Factor : constant := 32; 792 -- The growth factor controls how much extra space is allocated when 793 -- we have to increase the size of an allocated unbounded string. By 794 -- allocating extra space, we avoid the need to reallocate on every 795 -- append, particularly important when a string is built up by repeated 796 -- append operations of small pieces. This is expressed as a factor so 797 -- 32 means add 1/32 of the length of the string as growth space. 798 799 Min_Mul_Alloc : constant := Standard'Maximum_Alignment; 800 -- Allocation will be done by a multiple of Min_Mul_Alloc This causes 801 -- no memory loss as most (all?) malloc implementations are obliged to 802 -- align the returned memory on the maximum alignment as malloc does not 803 -- know the target alignment. 804 805 S_Length : constant Natural := Source.Reference'Length; 806 807 begin 808 if Chunk_Size > S_Length - Source.Last then 809 declare 810 New_Size : constant Positive := 811 S_Length + Chunk_Size + (S_Length / Growth_Factor); 812 813 New_Rounded_Up_Size : constant Positive := 814 ((New_Size - 1) / Min_Mul_Alloc + 1) * Min_Mul_Alloc; 815 816 Tmp : constant Wide_Wide_String_Access := 817 new Wide_Wide_String (1 .. New_Rounded_Up_Size); 818 819 begin 820 Tmp (1 .. Source.Last) := Source.Reference (1 .. Source.Last); 821 Free (Source.Reference); 822 Source.Reference := Tmp; 823 end; 824 end if; 825 end Realloc_For_Chunk; 826 827 --------------------- 828 -- Replace_Element -- 829 --------------------- 830 831 procedure Replace_Element 832 (Source : in out Unbounded_Wide_Wide_String; 833 Index : Positive; 834 By : Wide_Wide_Character) 835 is 836 begin 837 if Index <= Source.Last then 838 Source.Reference (Index) := By; 839 else 840 raise Strings.Index_Error; 841 end if; 842 end Replace_Element; 843 844 ------------------- 845 -- Replace_Slice -- 846 ------------------- 847 848 function Replace_Slice 849 (Source : Unbounded_Wide_Wide_String; 850 Low : Positive; 851 High : Natural; 852 By : Wide_Wide_String) return Unbounded_Wide_Wide_String 853 is 854 begin 855 return To_Unbounded_Wide_Wide_String 856 (Wide_Wide_Fixed.Replace_Slice 857 (Source.Reference (1 .. Source.Last), Low, High, By)); 858 end Replace_Slice; 859 860 procedure Replace_Slice 861 (Source : in out Unbounded_Wide_Wide_String; 862 Low : Positive; 863 High : Natural; 864 By : Wide_Wide_String) 865 is 866 Old : Wide_Wide_String_Access := Source.Reference; 867 begin 868 Source.Reference := new Wide_Wide_String' 869 (Wide_Wide_Fixed.Replace_Slice 870 (Source.Reference (1 .. Source.Last), Low, High, By)); 871 Source.Last := Source.Reference'Length; 872 Free (Old); 873 end Replace_Slice; 874 875 ------------------------------------ 876 -- Set_Unbounded_Wide_Wide_String -- 877 ------------------------------------ 878 879 procedure Set_Unbounded_Wide_Wide_String 880 (Target : out Unbounded_Wide_Wide_String; 881 Source : Wide_Wide_String) 882 is 883 begin 884 Target.Last := Source'Length; 885 Target.Reference := new Wide_Wide_String (1 .. Source'Length); 886 Target.Reference.all := Source; 887 end Set_Unbounded_Wide_Wide_String; 888 889 ----------- 890 -- Slice -- 891 ----------- 892 893 function Slice 894 (Source : Unbounded_Wide_Wide_String; 895 Low : Positive; 896 High : Natural) return Wide_Wide_String 897 is 898 begin 899 -- Note: test of High > Length is in accordance with AI95-00128 900 901 if Low > Source.Last + 1 or else High > Source.Last then 902 raise Index_Error; 903 else 904 return Source.Reference (Low .. High); 905 end if; 906 end Slice; 907 908 ---------- 909 -- Tail -- 910 ---------- 911 912 function Tail 913 (Source : Unbounded_Wide_Wide_String; 914 Count : Natural; 915 Pad : Wide_Wide_Character := Wide_Wide_Space) 916 return Unbounded_Wide_Wide_String is 917 begin 918 return To_Unbounded_Wide_Wide_String 919 (Wide_Wide_Fixed.Tail 920 (Source.Reference (1 .. Source.Last), Count, Pad)); 921 end Tail; 922 923 procedure Tail 924 (Source : in out Unbounded_Wide_Wide_String; 925 Count : Natural; 926 Pad : Wide_Wide_Character := Wide_Wide_Space) 927 is 928 Old : Wide_Wide_String_Access := Source.Reference; 929 begin 930 Source.Reference := new Wide_Wide_String' 931 (Wide_Wide_Fixed.Tail 932 (Source.Reference (1 .. Source.Last), Count, Pad)); 933 Source.Last := Source.Reference'Length; 934 Free (Old); 935 end Tail; 936 937 ----------------------------------- 938 -- To_Unbounded_Wide_Wide_String -- 939 ----------------------------------- 940 941 function To_Unbounded_Wide_Wide_String 942 (Source : Wide_Wide_String) return Unbounded_Wide_Wide_String 943 is 944 Result : Unbounded_Wide_Wide_String; 945 begin 946 Result.Last := Source'Length; 947 Result.Reference := new Wide_Wide_String (1 .. Source'Length); 948 Result.Reference.all := Source; 949 return Result; 950 end To_Unbounded_Wide_Wide_String; 951 952 function To_Unbounded_Wide_Wide_String 953 (Length : Natural) return Unbounded_Wide_Wide_String 954 is 955 Result : Unbounded_Wide_Wide_String; 956 begin 957 Result.Last := Length; 958 Result.Reference := new Wide_Wide_String (1 .. Length); 959 return Result; 960 end To_Unbounded_Wide_Wide_String; 961 962 ------------------------- 963 -- To_Wide_Wide_String -- 964 ------------------------- 965 966 function To_Wide_Wide_String 967 (Source : Unbounded_Wide_Wide_String) return Wide_Wide_String 968 is 969 begin 970 return Source.Reference (1 .. Source.Last); 971 end To_Wide_Wide_String; 972 973 --------------- 974 -- Translate -- 975 --------------- 976 977 function Translate 978 (Source : Unbounded_Wide_Wide_String; 979 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping) 980 return Unbounded_Wide_Wide_String 981 is 982 begin 983 return 984 To_Unbounded_Wide_Wide_String 985 (Wide_Wide_Fixed.Translate 986 (Source.Reference (1 .. Source.Last), Mapping)); 987 end Translate; 988 989 procedure Translate 990 (Source : in out Unbounded_Wide_Wide_String; 991 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping) 992 is 993 begin 994 Wide_Wide_Fixed.Translate (Source.Reference (1 .. Source.Last), Mapping); 995 end Translate; 996 997 function Translate 998 (Source : Unbounded_Wide_Wide_String; 999 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping_Function) 1000 return Unbounded_Wide_Wide_String 1001 is 1002 begin 1003 return 1004 To_Unbounded_Wide_Wide_String 1005 (Wide_Wide_Fixed.Translate 1006 (Source.Reference (1 .. Source.Last), Mapping)); 1007 end Translate; 1008 1009 procedure Translate 1010 (Source : in out Unbounded_Wide_Wide_String; 1011 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping_Function) 1012 is 1013 begin 1014 Wide_Wide_Fixed.Translate (Source.Reference (1 .. Source.Last), Mapping); 1015 end Translate; 1016 1017 ---------- 1018 -- Trim -- 1019 ---------- 1020 1021 function Trim 1022 (Source : Unbounded_Wide_Wide_String; 1023 Side : Trim_End) return Unbounded_Wide_Wide_String 1024 is 1025 begin 1026 return 1027 To_Unbounded_Wide_Wide_String 1028 (Wide_Wide_Fixed.Trim (Source.Reference (1 .. Source.Last), Side)); 1029 end Trim; 1030 1031 procedure Trim 1032 (Source : in out Unbounded_Wide_Wide_String; 1033 Side : Trim_End) 1034 is 1035 Old : Wide_Wide_String_Access := Source.Reference; 1036 begin 1037 Source.Reference := 1038 new Wide_Wide_String' 1039 (Wide_Wide_Fixed.Trim (Source.Reference (1 .. Source.Last), Side)); 1040 Source.Last := Source.Reference'Length; 1041 Free (Old); 1042 end Trim; 1043 1044 function Trim 1045 (Source : Unbounded_Wide_Wide_String; 1046 Left : Wide_Wide_Maps.Wide_Wide_Character_Set; 1047 Right : Wide_Wide_Maps.Wide_Wide_Character_Set) 1048 return Unbounded_Wide_Wide_String 1049 is 1050 begin 1051 return 1052 To_Unbounded_Wide_Wide_String 1053 (Wide_Wide_Fixed.Trim 1054 (Source.Reference (1 .. Source.Last), Left, Right)); 1055 end Trim; 1056 1057 procedure Trim 1058 (Source : in out Unbounded_Wide_Wide_String; 1059 Left : Wide_Wide_Maps.Wide_Wide_Character_Set; 1060 Right : Wide_Wide_Maps.Wide_Wide_Character_Set) 1061 is 1062 Old : Wide_Wide_String_Access := Source.Reference; 1063 begin 1064 Source.Reference := 1065 new Wide_Wide_String' 1066 (Wide_Wide_Fixed.Trim 1067 (Source.Reference (1 .. Source.Last), Left, Right)); 1068 Source.Last := Source.Reference'Length; 1069 Free (Old); 1070 end Trim; 1071 1072 --------------------- 1073 -- Unbounded_Slice -- 1074 --------------------- 1075 1076 function Unbounded_Slice 1077 (Source : Unbounded_Wide_Wide_String; 1078 Low : Positive; 1079 High : Natural) return Unbounded_Wide_Wide_String 1080 is 1081 begin 1082 if Low > Source.Last + 1 or else High > Source.Last then 1083 raise Index_Error; 1084 else 1085 return 1086 To_Unbounded_Wide_Wide_String (Source.Reference.all (Low .. High)); 1087 end if; 1088 end Unbounded_Slice; 1089 1090 procedure Unbounded_Slice 1091 (Source : Unbounded_Wide_Wide_String; 1092 Target : out Unbounded_Wide_Wide_String; 1093 Low : Positive; 1094 High : Natural) 1095 is 1096 begin 1097 if Low > Source.Last + 1 or else High > Source.Last then 1098 raise Index_Error; 1099 else 1100 Target := 1101 To_Unbounded_Wide_Wide_String (Source.Reference.all (Low .. High)); 1102 end if; 1103 end Unbounded_Slice; 1104 1105end Ada.Strings.Wide_Wide_Unbounded; 1106