OSDN Git Service

2007-09-21 Olivier Hainque <hainque@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / a-strunb.adb
index bf492eb..d7b5eb1 100644 (file)
@@ -1,12 +1,12 @@
 ------------------------------------------------------------------------------
 --                                                                          --
---                          GNAT RUNTIME COMPONENTS                         --
+--                         GNAT RUN-TIME COMPONENTS                         --
 --                                                                          --
---                A D A . S T R I N G S . U N B O U N D E D                 --
+--                 A D A . S T R I N G S . U N B O U N D E D                --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2005 Free Software Foundation, Inc.          --
+--          Copyright (C) 1992-2007, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -16,8 +16,8 @@
 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
 -- for  more details.  You should have  received  a copy of the GNU General --
 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
--- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
--- MA 02111-1307, USA.                                                      --
+-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
+-- Boston, MA 02110-1301, USA.                                              --
 --                                                                          --
 -- As a special exception,  if other files  instantiate  generics from this --
 -- unit, or you link  this unit with other files  to produce an executable, --
@@ -623,7 +623,6 @@ package body Ada.Strings.Unbounded is
         (Source.Reference (1 .. Source.Last), Pattern, From, Going, Mapping);
    end Index;
 
-
    function Index
      (Source  : Unbounded_String;
       Set     : Maps.Character_Set;
@@ -691,7 +690,7 @@ package body Ada.Strings.Unbounded is
          raise Index_Error;
       end if;
 
-      Realloc_For_Chunk (Source, New_Item'Size);
+      Realloc_For_Chunk (Source, New_Item'Length);
 
       Source.Reference
         (Before +  New_Item'Length .. Source.Last + New_Item'Length) :=
@@ -755,17 +754,36 @@ package body Ada.Strings.Unbounded is
      (Source     : in out Unbounded_String;
       Chunk_Size : Natural)
    is
-      Growth_Factor : constant := 50;
-      S_Length      : constant Natural := Source.Reference'Length;
+      Growth_Factor : constant := 32;
+      --  The growth factor controls how much extra space is allocated when
+      --  we have to increase the size of an allocated unbounded string. By
+      --  allocating extra space, we avoid the need to reallocate on every
+      --  append, particularly important when a string is built up by repeated
+      --  append operations of small pieces. This is expressed as a factor so
+      --  32 means add 1/32 of the length of the string as growth space.
+
+      Min_Mul_Alloc : constant := Standard'Maximum_Alignment;
+      --  Allocation will be done by a multiple of Min_Mul_Alloc This causes
+      --  no memory loss as most (all?) malloc implementations are obliged to
+      --  align the returned memory on the maximum alignment as malloc does not
+      --  know the target alignment.
+
+      S_Length : constant Natural := Source.Reference'Length;
 
    begin
       if Chunk_Size > S_Length - Source.Last then
          declare
-            Alloc_Chunk_Size : constant Positive :=
-                                 Chunk_Size + (S_Length / Growth_Factor);
-            Tmp : String_Access;
+            New_Size : constant Positive :=
+                         S_Length + Chunk_Size + (S_Length / Growth_Factor);
+
+            New_Rounded_Up_Size : constant Positive :=
+                                    ((New_Size - 1) / Min_Mul_Alloc + 1) *
+                                       Min_Mul_Alloc;
+
+            Tmp : constant String_Access :=
+                    new String (1 .. New_Rounded_Up_Size);
+
          begin
-            Tmp := new String (1 .. S_Length + Alloc_Chunk_Size);
             Tmp (1 .. Source.Last) := Source.Reference (1 .. Source.Last);
             Free (Source.Reference);
             Source.Reference := Tmp;
@@ -829,10 +847,12 @@ package body Ada.Strings.Unbounded is
      (Target : out Unbounded_String;
       Source : String)
    is
+      Old : String_Access := Target.Reference;
    begin
       Target.Last          := Source'Length;
       Target.Reference     := new String (1 .. Source'Length);
       Target.Reference.all := Source;
+      Free (Old);
    end Set_Unbounded_String;
 
    -----------