OSDN Git Service

Minor reformatting.
[pf3gnuchains/gcc-fork.git] / gcc / ada / a-strunb.adb
index 13422c9..7634e65 100644 (file)
@@ -1,30 +1,28 @@
 ------------------------------------------------------------------------------
 --                                                                          --
---                         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-2001 Free Software Foundation, Inc.          --
+--          Copyright (C) 1992-2009, 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- --
--- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
--- 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.                                                      --
+-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
 --                                                                          --
--- As a special exception,  if other files  instantiate  generics from this --
--- unit, or you link  this unit with other files  to produce an executable, --
--- this  unit  does not  by itself cause  the resulting  executable  to  be --
--- covered  by the  GNU  General  Public  License.  This exception does not --
--- however invalidate  any other reasons why  the executable file  might be --
--- covered by the  GNU Public License.                                      --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception,   --
+-- version 3.1, as published by the Free Software Foundation.               --
+--                                                                          --
+-- You should have received a copy of the GNU General Public License and    --
+-- a copy of the GCC Runtime Library Exception along with this program;     --
+-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
+-- <http://www.gnu.org/licenses/>.                                          --
 --                                                                          --
 -- GNAT was originally developed  by the GNAT team at  New York University. --
 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
@@ -43,78 +41,95 @@ package body Ada.Strings.Unbounded is
    -- "&" --
    ---------
 
-   function "&" (Left, Right : Unbounded_String) return Unbounded_String is
-      L_Length : constant Integer := Left.Reference.all'Length;
-      R_Length : constant Integer := Right.Reference.all'Length;
-      Length   : constant Integer :=  L_Length + R_Length;
+   function "&"
+     (Left  : Unbounded_String;
+      Right : Unbounded_String) return Unbounded_String
+   is
+      L_Length : constant Natural := Left.Last;
+      R_Length : constant Natural := Right.Last;
       Result   : Unbounded_String;
 
    begin
-      Result.Reference := new String (1 .. Length);
-      Result.Reference.all (1 .. L_Length)          := Left.Reference.all;
-      Result.Reference.all (L_Length + 1 .. Length) := Right.Reference.all;
+      Result.Last := L_Length + R_Length;
+
+      Result.Reference := new String (1 .. Result.Last);
+
+      Result.Reference (1 .. L_Length) :=
+        Left.Reference (1 .. Left.Last);
+      Result.Reference (L_Length + 1 .. Result.Last) :=
+        Right.Reference (1 .. Right.Last);
+
       return Result;
    end "&";
 
    function "&"
      (Left  : Unbounded_String;
-      Right : String)
-      return  Unbounded_String
+      Right : String) return Unbounded_String
    is
-      L_Length : constant Integer := Left.Reference.all'Length;
-      Length   : constant Integer := L_Length +  Right'Length;
+      L_Length : constant Natural := Left.Last;
       Result   : Unbounded_String;
 
    begin
-      Result.Reference := new String (1 .. Length);
-      Result.Reference.all (1 .. L_Length)          := Left.Reference.all;
-      Result.Reference.all (L_Length + 1 .. Length) := Right;
+      Result.Last := L_Length + Right'Length;
+
+      Result.Reference := new String (1 .. Result.Last);
+
+      Result.Reference (1 .. L_Length) := Left.Reference (1 .. Left.Last);
+      Result.Reference (L_Length + 1 .. Result.Last) := Right;
+
       return Result;
    end "&";
 
    function "&"
      (Left  : String;
-      Right : Unbounded_String)
-      return  Unbounded_String
+      Right : Unbounded_String) return Unbounded_String
    is
-      R_Length : constant Integer := Right.Reference.all'Length;
-      Length   : constant Integer := Left'Length + R_Length;
+      R_Length : constant Natural := Right.Last;
       Result   : Unbounded_String;
 
    begin
-      Result.Reference := new String (1 .. Length);
-      Result.Reference.all (1 .. Left'Length)          := Left;
-      Result.Reference.all (Left'Length + 1 .. Length) := Right.Reference.all;
+      Result.Last := Left'Length + R_Length;
+
+      Result.Reference := new String (1 .. Result.Last);
+
+      Result.Reference (1 .. Left'Length) := Left;
+      Result.Reference (Left'Length + 1 .. Result.Last) :=
+        Right.Reference (1 .. Right.Last);
+
       return Result;
    end "&";
 
    function "&"
      (Left  : Unbounded_String;
-      Right : Character)
-      return  Unbounded_String
+      Right : Character) return Unbounded_String
    is
-      Length : constant Integer := Left.Reference.all'Length + 1;
       Result : Unbounded_String;
 
    begin
-      Result.Reference := new String (1 .. Length);
-      Result.Reference.all (1 .. Length - 1) := Left.Reference.all;
-      Result.Reference.all (Length)          := Right;
+      Result.Last := Left.Last + 1;
+
+      Result.Reference := new String (1 .. Result.Last);
+
+      Result.Reference (1 .. Result.Last - 1) :=
+        Left.Reference (1 .. Left.Last);
+      Result.Reference (Result.Last) := Right;
+
       return Result;
    end "&";
 
    function "&"
      (Left  : Character;
-      Right : Unbounded_String)
-      return  Unbounded_String
+      Right : Unbounded_String) return Unbounded_String
    is
-      Length : constant Integer := Right.Reference.all'Length + 1;
       Result : Unbounded_String;
 
    begin
-      Result.Reference := new String (1 .. Length);
-      Result.Reference.all (1)           := Left;
-      Result.Reference.all (2 .. Length) := Right.Reference.all;
+      Result.Last := Right.Last + 1;
+
+      Result.Reference := new String (1 .. Result.Last);
+      Result.Reference (1) := Left;
+      Result.Reference (2 .. Result.Last) :=
+        Right.Reference (1 .. Right.Last);
       return Result;
    end "&";
 
@@ -124,12 +139,13 @@ package body Ada.Strings.Unbounded is
 
    function "*"
      (Left  : Natural;
-      Right : Character)
-      return  Unbounded_String
+      Right : Character) return Unbounded_String
    is
       Result : Unbounded_String;
 
    begin
+      Result.Last   := Left;
+
       Result.Reference := new String (1 .. Left);
       for J in Result.Reference'Range loop
          Result.Reference (J) := Right;
@@ -140,16 +156,21 @@ package body Ada.Strings.Unbounded is
 
    function "*"
      (Left  : Natural;
-      Right : String)
-     return   Unbounded_String
+      Right : String) return Unbounded_String
    is
-      Len    : constant Integer := Right'Length;
+      Len    : constant Natural := Right'Length;
+      K      : Positive;
       Result : Unbounded_String;
 
    begin
-      Result.Reference := new String (1 .. Left * Len);
+      Result.Last := Left * Len;
+
+      Result.Reference := new String (1 .. Result.Last);
+
+      K := 1;
       for J in 1 .. Left loop
-         Result.Reference.all (Len * J - Len + 1 .. Len * J) := Right;
+         Result.Reference (K .. K + Len - 1) := Right;
+         K := K + Len;
       end loop;
 
       return Result;
@@ -157,17 +178,22 @@ package body Ada.Strings.Unbounded is
 
    function "*"
      (Left  : Natural;
-      Right : Unbounded_String)
-      return  Unbounded_String
+      Right : Unbounded_String) return Unbounded_String
    is
-      Len    : constant Integer := Right.Reference.all'Length;
+      Len    : constant Natural := Right.Last;
+      K      : Positive;
       Result : Unbounded_String;
 
    begin
-      Result.Reference := new String (1 .. Left * Len);
-      for I in 1 .. Left loop
-         Result.Reference.all (Len * I - Len + 1 .. Len * I) :=
-           Right.Reference.all;
+      Result.Last := Left * Len;
+
+      Result.Reference := new String (1 .. Result.Last);
+
+      K := 1;
+      for J in 1 .. Left loop
+         Result.Reference (K .. K + Len - 1) :=
+           Right.Reference (1 .. Right.Last);
+         K := K + Len;
       end loop;
 
       return Result;
@@ -177,135 +203,145 @@ package body Ada.Strings.Unbounded is
    -- "<" --
    ---------
 
-   function "<" (Left, Right : in Unbounded_String) return Boolean is
+   function "<"
+     (Left  : Unbounded_String;
+      Right : Unbounded_String) return Boolean
+   is
    begin
-      return Left.Reference.all < Right.Reference.all;
+      return
+        Left.Reference (1 .. Left.Last) < Right.Reference (1 .. Right.Last);
    end "<";
 
    function "<"
-     (Left  : in Unbounded_String;
-      Right : in String)
-      return  Boolean
+     (Left  : Unbounded_String;
+      Right : String) return Boolean
    is
    begin
-      return Left.Reference.all < Right;
+      return Left.Reference (1 .. Left.Last) < Right;
    end "<";
 
    function "<"
-     (Left  : in String;
-      Right : in Unbounded_String)
-      return  Boolean
+     (Left  : String;
+      Right : Unbounded_String) return Boolean
    is
    begin
-      return Left < Right.Reference.all;
+      return Left < Right.Reference (1 .. Right.Last);
    end "<";
 
    ----------
    -- "<=" --
    ----------
 
-   function "<=" (Left, Right : in Unbounded_String) return Boolean is
+   function "<="
+     (Left  : Unbounded_String;
+      Right : Unbounded_String) return Boolean
+   is
    begin
-      return Left.Reference.all <= Right.Reference.all;
+      return
+        Left.Reference (1 .. Left.Last) <= Right.Reference (1 .. Right.Last);
    end "<=";
 
    function "<="
-     (Left  : in Unbounded_String;
-      Right : in String)
-      return  Boolean
+     (Left  : Unbounded_String;
+      Right : String) return Boolean
    is
    begin
-      return Left.Reference.all <= Right;
+      return Left.Reference (1 .. Left.Last) <= Right;
    end "<=";
 
    function "<="
-     (Left  : in String;
-      Right : in Unbounded_String)
-      return  Boolean
+     (Left  : String;
+      Right : Unbounded_String) return Boolean
    is
    begin
-      return Left <= Right.Reference.all;
+      return Left <= Right.Reference (1 .. Right.Last);
    end "<=";
 
    ---------
    -- "=" --
    ---------
 
-   function "=" (Left, Right : in Unbounded_String) return Boolean is
+   function "="
+     (Left  : Unbounded_String;
+      Right : Unbounded_String) return Boolean
+   is
    begin
-      return Left.Reference.all = Right.Reference.all;
+      return
+        Left.Reference (1 .. Left.Last) = Right.Reference (1 .. Right.Last);
    end "=";
 
    function "="
-     (Left  : in Unbounded_String;
-      Right : in String)
-      return  Boolean
+     (Left  : Unbounded_String;
+      Right : String) return Boolean
    is
    begin
-      return Left.Reference.all = Right;
+      return Left.Reference (1 .. Left.Last) = Right;
    end "=";
 
    function "="
-     (Left  : in String;
-      Right : in Unbounded_String)
-      return  Boolean
+     (Left  : String;
+      Right : Unbounded_String) return Boolean
    is
    begin
-      return Left = Right.Reference.all;
+      return Left = Right.Reference (1 .. Right.Last);
    end "=";
 
    ---------
    -- ">" --
    ---------
 
-   function ">"  (Left, Right : in Unbounded_String) return Boolean is
+   function ">"
+     (Left  : Unbounded_String;
+      Right : Unbounded_String) return Boolean
+   is
    begin
-      return Left.Reference.all > Right.Reference.all;
+      return
+        Left.Reference (1 .. Left.Last) > Right.Reference (1 .. Right.Last);
    end ">";
 
    function ">"
-     (Left  : in Unbounded_String;
-      Right : in String)
-      return  Boolean
+     (Left  : Unbounded_String;
+      Right : String) return Boolean
    is
    begin
-      return Left.Reference.all > Right;
+      return Left.Reference (1 .. Left.Last) > Right;
    end ">";
 
    function ">"
-     (Left  : in String;
-      Right : in Unbounded_String)
-      return  Boolean
+     (Left  : String;
+      Right : Unbounded_String) return Boolean
    is
    begin
-      return Left > Right.Reference.all;
+      return Left > Right.Reference (1 .. Right.Last);
    end ">";
 
    ----------
    -- ">=" --
    ----------
 
-   function ">=" (Left, Right : in Unbounded_String) return Boolean is
+   function ">="
+     (Left  : Unbounded_String;
+      Right : Unbounded_String) return Boolean
+   is
    begin
-      return Left.Reference.all >= Right.Reference.all;
+      return
+        Left.Reference (1 .. Left.Last) >= Right.Reference (1 .. Right.Last);
    end ">=";
 
    function ">="
-     (Left  : in Unbounded_String;
-      Right : in String)
-      return  Boolean
+     (Left  : Unbounded_String;
+      Right : String) return Boolean
    is
    begin
-      return Left.Reference.all >= Right;
+      return Left.Reference (1 .. Left.Last) >= Right;
    end ">=";
 
    function ">="
-     (Left  : in String;
-      Right : in Unbounded_String)
-      return  Boolean
+     (Left  : String;
+      Right : Unbounded_String) return Boolean
    is
    begin
-      return Left >= Right.Reference.all;
+      return Left >= Right.Reference (1 .. Right.Last);
    end ">=";
 
    ------------
@@ -315,10 +351,11 @@ package body Ada.Strings.Unbounded is
    procedure Adjust (Object : in out Unbounded_String) is
    begin
       --  Copy string, except we do not copy the statically allocated null
-      --  string, since it can never be deallocated.
+      --  string since it can never be deallocated. Note that we do not copy
+      --  extra string room here to avoid dragging unused allocated memory.
 
       if Object.Reference /= Null_String'Access then
-         Object.Reference := new String'(Object.Reference.all);
+         Object.Reference := new String'(Object.Reference (1 .. Object.Last));
       end if;
    end Adjust;
 
@@ -328,50 +365,34 @@ package body Ada.Strings.Unbounded is
 
    procedure Append
      (Source   : in out Unbounded_String;
-      New_Item : in Unbounded_String)
+      New_Item : Unbounded_String)
    is
-      S_Length : constant Integer := Source.Reference.all'Length;
-      Length   : constant Integer := S_Length + New_Item.Reference.all'Length;
-      Tmp      : String_Access;
-
    begin
-      Tmp := new String (1 .. Length);
-      Tmp (1 .. S_Length) := Source.Reference.all;
-      Tmp (S_Length + 1 .. Length) := New_Item.Reference.all;
-      Free (Source.Reference);
-      Source.Reference := Tmp;
+      Realloc_For_Chunk (Source, New_Item.Last);
+      Source.Reference (Source.Last + 1 .. Source.Last + New_Item.Last) :=
+        New_Item.Reference (1 .. New_Item.Last);
+      Source.Last := Source.Last + New_Item.Last;
    end Append;
 
    procedure Append
      (Source   : in out Unbounded_String;
-      New_Item : in String)
+      New_Item : String)
    is
-      S_Length : constant Integer := Source.Reference.all'Length;
-      Length   : constant Integer := S_Length + New_Item'Length;
-      Tmp      : String_Access;
-
    begin
-      Tmp := new String (1 .. Length);
-      Tmp (1 .. S_Length) := Source.Reference.all;
-      Tmp (S_Length + 1 .. Length) := New_Item;
-      Free (Source.Reference);
-      Source.Reference := Tmp;
+      Realloc_For_Chunk (Source, New_Item'Length);
+      Source.Reference (Source.Last + 1 .. Source.Last + New_Item'Length) :=
+        New_Item;
+      Source.Last := Source.Last + New_Item'Length;
    end Append;
 
    procedure Append
      (Source   : in out Unbounded_String;
-      New_Item : in Character)
+      New_Item : Character)
    is
-      S_Length : constant Integer := Source.Reference.all'Length;
-      Length   : constant Integer := S_Length + 1;
-      Tmp      : String_Access;
-
    begin
-      Tmp := new String (1 .. Length);
-      Tmp (1 .. S_Length) := Source.Reference.all;
-      Tmp (S_Length + 1) := New_Item;
-      Free (Source.Reference);
-      Source.Reference := Tmp;
+      Realloc_For_Chunk (Source, 1);
+      Source.Reference (Source.Last + 1) := New_Item;
+      Source.Last := Source.Last + 1;
    end Append;
 
    -----------
@@ -379,32 +400,31 @@ package body Ada.Strings.Unbounded is
    -----------
 
    function Count
-     (Source   : Unbounded_String;
-      Pattern  : String;
-      Mapping  : Maps.Character_Mapping := Maps.Identity)
-      return     Natural
+     (Source  : Unbounded_String;
+      Pattern : String;
+      Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
    is
    begin
-      return Search.Count (Source.Reference.all, Pattern, Mapping);
+      return
+        Search.Count (Source.Reference (1 .. Source.Last), Pattern, Mapping);
    end Count;
 
    function Count
-     (Source   : in Unbounded_String;
-      Pattern  : in String;
-      Mapping  : in Maps.Character_Mapping_Function)
-      return     Natural
+     (Source  : Unbounded_String;
+      Pattern : String;
+      Mapping : Maps.Character_Mapping_Function) return Natural
    is
    begin
-      return Search.Count (Source.Reference.all, Pattern, Mapping);
+      return
+        Search.Count (Source.Reference (1 .. Source.Last), Pattern, Mapping);
    end Count;
 
    function Count
-     (Source   : Unbounded_String;
-      Set      : Maps.Character_Set)
-      return     Natural
+     (Source : Unbounded_String;
+      Set    : Maps.Character_Set) return Natural
    is
    begin
-      return Search.Count (Source.Reference.all, Set);
+      return Search.Count (Source.Reference (1 .. Source.Last), Set);
    end Count;
 
    ------------
@@ -414,26 +434,36 @@ package body Ada.Strings.Unbounded is
    function Delete
      (Source  : Unbounded_String;
       From    : Positive;
-      Through : Natural)
-      return    Unbounded_String
+      Through : Natural) return Unbounded_String
    is
    begin
       return
         To_Unbounded_String
-          (Fixed.Delete (Source.Reference.all, From, Through));
+          (Fixed.Delete (Source.Reference (1 .. Source.Last), From, Through));
    end Delete;
 
    procedure Delete
      (Source  : in out Unbounded_String;
-      From    : in Positive;
-      Through : in Natural)
+      From    : Positive;
+      Through : Natural)
    is
-      Old : String_Access := Source.Reference;
-
    begin
-      Source.Reference :=
-        new String' (Fixed.Delete (Old.all, From, Through));
-      Free (Old);
+      if From > Through then
+         null;
+
+      elsif From < Source.Reference'First or else Through > Source.Last then
+         raise Index_Error;
+
+      else
+         declare
+            Len : constant Natural := Through - From + 1;
+
+         begin
+            Source.Reference (From .. Source.Last - Len) :=
+              Source.Reference (Through + 1 .. Source.Last);
+            Source.Last := Source.Last - Len;
+         end;
+      end if;
    end Delete;
 
    -------------
@@ -442,12 +472,11 @@ package body Ada.Strings.Unbounded is
 
    function Element
      (Source : Unbounded_String;
-      Index  : Positive)
-      return   Character
+      Index  : Positive) return Character
    is
    begin
-      if Index <= Source.Reference.all'Last then
-         return Source.Reference.all (Index);
+      if Index <= Source.Last then
+         return Source.Reference (Index);
       else
          raise Strings.Index_Error;
       end if;
@@ -467,6 +496,7 @@ package body Ada.Strings.Unbounded is
       if Object.Reference /= Null_String'Access then
          Deallocate (Object.Reference);
          Object.Reference := Null_Unbounded_String.Reference;
+         Object.Last := 0;
       end if;
    end Finalize;
 
@@ -482,7 +512,8 @@ package body Ada.Strings.Unbounded is
       Last   : out Natural)
    is
    begin
-      Search.Find_Token (Source.Reference.all, Set, Test, First, Last);
+      Search.Find_Token
+        (Source.Reference (1 .. Source.Last), Set, Test, First, Last);
    end Find_Token;
 
    ----------
@@ -494,7 +525,7 @@ package body Ada.Strings.Unbounded is
          new Ada.Unchecked_Deallocation (String, String_Access);
 
    begin
-      --  Note: Don't try to free statically allocated null string
+      --  Note: Do not try to free statically allocated null string
 
       if X /= Null_Unbounded_String.Reference then
          Deallocate (X);
@@ -508,23 +539,24 @@ package body Ada.Strings.Unbounded is
    function Head
      (Source : Unbounded_String;
       Count  : Natural;
-      Pad    : Character := Space)
-      return   Unbounded_String
+      Pad    : Character := Space) return Unbounded_String
    is
    begin
-      return
-        To_Unbounded_String (Fixed.Head (Source.Reference.all, Count, Pad));
+      return To_Unbounded_String
+        (Fixed.Head (Source.Reference (1 .. Source.Last), Count, Pad));
    end Head;
 
    procedure Head
      (Source : in out Unbounded_String;
-      Count  : in Natural;
-      Pad    : in Character := Space)
+      Count  : Natural;
+      Pad    : Character := Space)
    is
       Old : String_Access := Source.Reference;
-
    begin
-      Source.Reference := new String'(Fixed.Head (Old.all, Count, Pad));
+      Source.Reference :=
+        new String'(Fixed.Head (Source.Reference (1 .. Source.Last),
+                    Count, Pad));
+      Source.Last := Source.Reference'Length;
       Free (Old);
    end Head;
 
@@ -533,45 +565,93 @@ package body Ada.Strings.Unbounded is
    -----------
 
    function Index
-     (Source   : Unbounded_String;
-      Pattern  : String;
-      Going    : Strings.Direction := Strings.Forward;
-      Mapping  : Maps.Character_Mapping := Maps.Identity)
-      return     Natural
+     (Source  : Unbounded_String;
+      Pattern : String;
+      Going   : Strings.Direction := Strings.Forward;
+      Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
    is
    begin
-      return Search.Index (Source.Reference.all, Pattern, Going, Mapping);
+      return Search.Index
+        (Source.Reference (1 .. Source.Last), Pattern, Going, Mapping);
    end Index;
 
    function Index
-     (Source   : in Unbounded_String;
-      Pattern  : in String;
-      Going    : in Direction := Forward;
-      Mapping  : in Maps.Character_Mapping_Function)
-      return Natural
+     (Source  : Unbounded_String;
+      Pattern : String;
+      Going   : Direction := Forward;
+      Mapping : Maps.Character_Mapping_Function) return Natural
    is
    begin
-      return Search.Index (Source.Reference.all, Pattern, Going, Mapping);
+      return Search.Index
+        (Source.Reference (1 .. Source.Last), Pattern, Going, Mapping);
    end Index;
 
    function Index
      (Source : Unbounded_String;
       Set    : Maps.Character_Set;
       Test   : Strings.Membership := Strings.Inside;
-      Going  : Strings.Direction  := Strings.Forward)
-      return   Natural
+      Going  : Strings.Direction  := Strings.Forward) return Natural
+   is
+   begin
+      return Search.Index
+        (Source.Reference (1 .. Source.Last), Set, Test, Going);
+   end Index;
+
+   function Index
+     (Source  : Unbounded_String;
+      Pattern : String;
+      From    : Positive;
+      Going   : Direction := Forward;
+      Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
+   is
+   begin
+      return Search.Index
+        (Source.Reference (1 .. Source.Last), Pattern, From, Going, Mapping);
+   end Index;
+
+   function Index
+     (Source  : Unbounded_String;
+      Pattern : String;
+      From    : Positive;
+      Going   : Direction := Forward;
+      Mapping : Maps.Character_Mapping_Function) return Natural
+   is
+   begin
+      return Search.Index
+        (Source.Reference (1 .. Source.Last), Pattern, From, Going, Mapping);
+   end Index;
+
+   function Index
+     (Source  : Unbounded_String;
+      Set     : Maps.Character_Set;
+      From    : Positive;
+      Test    : Membership := Inside;
+      Going   : Direction := Forward) return Natural
    is
    begin
-      return Search.Index (Source.Reference.all, Set, Test, Going);
+      return Search.Index
+        (Source.Reference (1 .. Source.Last), Set, From, Test, Going);
    end Index;
 
    function Index_Non_Blank
      (Source : Unbounded_String;
-      Going  : Strings.Direction := Strings.Forward)
-      return   Natural
+      Going  : Strings.Direction := Strings.Forward) return Natural
+   is
+   begin
+      return
+        Search.Index_Non_Blank
+          (Source.Reference (1 .. Source.Last), Going);
+   end Index_Non_Blank;
+
+   function Index_Non_Blank
+     (Source : Unbounded_String;
+      From   : Positive;
+      Going  : Direction := Forward) return Natural
    is
    begin
-      return Search.Index_Non_Blank (Source.Reference.all, Going);
+      return
+        Search.Index_Non_Blank
+          (Source.Reference (1 .. Source.Last), From, Going);
    end Index_Non_Blank;
 
    ----------------
@@ -581,6 +661,7 @@ package body Ada.Strings.Unbounded is
    procedure Initialize (Object : in out Unbounded_String) is
    begin
       Object.Reference := Null_Unbounded_String.Reference;
+      Object.Last      := 0;
    end Initialize;
 
    ------------
@@ -590,26 +671,31 @@ package body Ada.Strings.Unbounded is
    function Insert
      (Source   : Unbounded_String;
       Before   : Positive;
-      New_Item : String)
-      return     Unbounded_String
+      New_Item : String) return Unbounded_String
    is
    begin
-      return
-        To_Unbounded_String
-          (Fixed.Insert (Source.Reference.all, Before, New_Item));
+      return To_Unbounded_String
+        (Fixed.Insert (Source.Reference (1 .. Source.Last), Before, New_Item));
    end Insert;
 
    procedure Insert
      (Source   : in out Unbounded_String;
-      Before   : in Positive;
-      New_Item : in String)
+      Before   : Positive;
+      New_Item : String)
    is
-      Old : String_Access := Source.Reference;
-
    begin
-      Source.Reference :=
-        new String' (Fixed.Insert (Source.Reference.all, Before, New_Item));
-      Free (Old);
+      if Before not in Source.Reference'First .. Source.Last + 1 then
+         raise Index_Error;
+      end if;
+
+      Realloc_For_Chunk (Source, New_Item'Length);
+
+      Source.Reference
+        (Before +  New_Item'Length .. Source.Last + New_Item'Length) :=
+           Source.Reference (Before .. Source.Last);
+
+      Source.Reference (Before .. Before + New_Item'Length - 1) := New_Item;
+      Source.Last := Source.Last + New_Item'Length;
    end Insert;
 
    ------------
@@ -618,7 +704,7 @@ package body Ada.Strings.Unbounded is
 
    function Length (Source : Unbounded_String) return Natural is
    begin
-      return Source.Reference.all'Length;
+      return Source.Last;
    end Length;
 
    ---------------
@@ -626,39 +712,83 @@ package body Ada.Strings.Unbounded is
    ---------------
 
    function Overwrite
-     (Source    : Unbounded_String;
-      Position  : Positive;
-      New_Item  : String)
-      return      Unbounded_String is
-
+     (Source   : Unbounded_String;
+      Position : Positive;
+      New_Item : String) return Unbounded_String
+   is
    begin
       return To_Unbounded_String
-        (Fixed.Overwrite (Source.Reference.all, Position, New_Item));
+        (Fixed.Overwrite
+          (Source.Reference (1 .. Source.Last), Position, New_Item));
    end Overwrite;
 
    procedure Overwrite
      (Source    : in out Unbounded_String;
-      Position  : in Positive;
-      New_Item  : in String)
+      Position  : Positive;
+      New_Item  : String)
    is
-      NL : constant Integer := New_Item'Length;
-
+      NL : constant Natural := New_Item'Length;
    begin
-      if Position <= Source.Reference'Length - NL + 1 then
+      if Position <= Source.Last - NL + 1 then
          Source.Reference (Position .. Position + NL - 1) := New_Item;
-
       else
          declare
             Old : String_Access := Source.Reference;
-
          begin
-            Source.Reference := new
-              String'(Fixed.Overwrite (Old.all, Position, New_Item));
+            Source.Reference := new String'
+              (Fixed.Overwrite
+                (Source.Reference (1 .. Source.Last), Position, New_Item));
+            Source.Last := Source.Reference'Length;
             Free (Old);
          end;
       end if;
    end Overwrite;
 
+   -----------------------
+   -- Realloc_For_Chunk --
+   -----------------------
+
+   procedure Realloc_For_Chunk
+     (Source     : in out Unbounded_String;
+      Chunk_Size : Natural)
+   is
+      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
+            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 (1 .. Source.Last) := Source.Reference (1 .. Source.Last);
+            Free (Source.Reference);
+            Source.Reference := Tmp;
+         end;
+      end if;
+   end Realloc_For_Chunk;
+
    ---------------------
    -- Replace_Element --
    ---------------------
@@ -669,8 +799,8 @@ package body Ada.Strings.Unbounded is
       By     : Character)
    is
    begin
-      if Index <= Source.Reference.all'Last then
-         Source.Reference.all (Index) := By;
+      if Index <= Source.Last then
+         Source.Reference (Index) := By;
       else
          raise Strings.Index_Error;
       end if;
@@ -681,32 +811,48 @@ package body Ada.Strings.Unbounded is
    -------------------
 
    function Replace_Slice
-     (Source   : Unbounded_String;
-      Low      : Positive;
-      High     : Natural;
-      By       : String)
-      return     Unbounded_String
+     (Source : Unbounded_String;
+      Low    : Positive;
+      High   : Natural;
+      By     : String) return Unbounded_String
    is
    begin
-      return
-        To_Unbounded_String
-          (Fixed.Replace_Slice (Source.Reference.all, Low, High, By));
+      return To_Unbounded_String
+        (Fixed.Replace_Slice
+           (Source.Reference (1 .. Source.Last), Low, High, By));
    end Replace_Slice;
 
    procedure Replace_Slice
-     (Source   : in out Unbounded_String;
-      Low      : in Positive;
-      High     : in Natural;
-      By       : in String)
+     (Source : in out Unbounded_String;
+      Low    : Positive;
+      High   : Natural;
+      By     : String)
    is
       Old : String_Access := Source.Reference;
-
    begin
-      Source.Reference :=
-        new String'(Fixed.Replace_Slice (Old.all, Low, High, By));
+      Source.Reference := new String'
+        (Fixed.Replace_Slice
+           (Source.Reference (1 .. Source.Last), Low, High, By));
+      Source.Last := Source.Reference'Length;
       Free (Old);
    end Replace_Slice;
 
+   --------------------------
+   -- Set_Unbounded_String --
+   --------------------------
+
+   procedure Set_Unbounded_String
+     (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;
+
    -----------
    -- Slice --
    -----------
@@ -714,18 +860,15 @@ package body Ada.Strings.Unbounded is
    function Slice
      (Source : Unbounded_String;
       Low    : Positive;
-      High   : Natural)
-      return   String
+      High   : Natural) return String
    is
-      Length : constant Natural := Source.Reference'Length;
-
    begin
       --  Note: test of High > Length is in accordance with AI95-00128
 
-      if Low > Length + 1 or else High > Length then
+      if Low > Source.Last + 1 or else High > Source.Last then
          raise Index_Error;
       else
-         return Source.Reference.all (Low .. High);
+         return Source.Reference (Low .. High);
       end if;
    end Slice;
 
@@ -736,23 +879,22 @@ package body Ada.Strings.Unbounded is
    function Tail
      (Source : Unbounded_String;
       Count  : Natural;
-      Pad    : Character := Space)
-      return   Unbounded_String is
-
+      Pad    : Character := Space) return Unbounded_String is
    begin
-      return
-        To_Unbounded_String (Fixed.Tail (Source.Reference.all, Count, Pad));
+      return To_Unbounded_String
+        (Fixed.Tail (Source.Reference (1 .. Source.Last), Count, Pad));
    end Tail;
 
    procedure Tail
      (Source : in out Unbounded_String;
-      Count  : in Natural;
-      Pad    : in Character := Space)
+      Count  : Natural;
+      Pad    : Character := Space)
    is
       Old : String_Access := Source.Reference;
-
    begin
-      Source.Reference := new String'(Fixed.Tail (Old.all, Count, Pad));
+      Source.Reference := new String'
+        (Fixed.Tail (Source.Reference (1 .. Source.Last), Count, Pad));
+      Source.Last := Source.Reference'Length;
       Free (Old);
    end Tail;
 
@@ -762,7 +904,7 @@ package body Ada.Strings.Unbounded is
 
    function To_String (Source : Unbounded_String) return String is
    begin
-      return Source.Reference.all;
+      return Source.Reference (1 .. Source.Last);
    end To_String;
 
    -------------------------
@@ -771,20 +913,19 @@ package body Ada.Strings.Unbounded is
 
    function To_Unbounded_String (Source : String) return Unbounded_String is
       Result : Unbounded_String;
-
    begin
-      Result.Reference := new String (1 .. Source'Length);
+      Result.Last          := Source'Length;
+      Result.Reference     := new String (1 .. Source'Length);
       Result.Reference.all := Source;
       return Result;
    end To_Unbounded_String;
 
    function To_Unbounded_String
-     (Length : in Natural)
-      return   Unbounded_String
+     (Length : Natural) return Unbounded_String
    is
       Result : Unbounded_String;
-
    begin
+      Result.Last      := Length;
       Result.Reference := new String (1 .. Length);
       return Result;
    end To_Unbounded_String;
@@ -795,12 +936,11 @@ package body Ada.Strings.Unbounded is
 
    function Translate
      (Source  : Unbounded_String;
-      Mapping : Maps.Character_Mapping)
-      return    Unbounded_String
+      Mapping : Maps.Character_Mapping) return Unbounded_String
    is
    begin
-      return
-        To_Unbounded_String (Fixed.Translate (Source.Reference.all, Mapping));
+      return To_Unbounded_String
+        (Fixed.Translate (Source.Reference (1 .. Source.Last), Mapping));
    end Translate;
 
    procedure Translate
@@ -808,25 +948,24 @@ package body Ada.Strings.Unbounded is
       Mapping : Maps.Character_Mapping)
    is
    begin
-      Fixed.Translate (Source.Reference.all, Mapping);
+      Fixed.Translate (Source.Reference (1 .. Source.Last), Mapping);
    end Translate;
 
    function Translate
-     (Source  : in Unbounded_String;
-      Mapping : in Maps.Character_Mapping_Function)
-      return    Unbounded_String
+     (Source  : Unbounded_String;
+      Mapping : Maps.Character_Mapping_Function) return Unbounded_String
    is
    begin
-      return
-        To_Unbounded_String (Fixed.Translate (Source.Reference.all, Mapping));
+      return To_Unbounded_String
+        (Fixed.Translate (Source.Reference (1 .. Source.Last), Mapping));
    end Translate;
 
    procedure Translate
      (Source  : in out Unbounded_String;
-      Mapping : in Maps.Character_Mapping_Function)
+      Mapping : Maps.Character_Mapping_Function)
    is
    begin
-      Fixed.Translate (Source.Reference.all, Mapping);
+      Fixed.Translate (Source.Reference (1 .. Source.Last), Mapping);
    end Translate;
 
    ----------
@@ -834,46 +973,78 @@ package body Ada.Strings.Unbounded is
    ----------
 
    function Trim
-     (Source : in Unbounded_String;
-      Side   : in Trim_End)
-      return   Unbounded_String
+     (Source : Unbounded_String;
+      Side   : Trim_End) return Unbounded_String
    is
    begin
-      return To_Unbounded_String (Fixed.Trim (Source.Reference.all, Side));
+      return To_Unbounded_String
+        (Fixed.Trim (Source.Reference (1 .. Source.Last), Side));
    end Trim;
 
    procedure Trim
      (Source : in out Unbounded_String;
-      Side   : in Trim_End)
+      Side   : Trim_End)
    is
       Old : String_Access := Source.Reference;
-
    begin
-      Source.Reference := new String'(Fixed.Trim (Old.all, Side));
+      Source.Reference := new String'
+        (Fixed.Trim (Source.Reference (1 .. Source.Last), Side));
+      Source.Last      := Source.Reference'Length;
       Free (Old);
    end Trim;
 
    function Trim
-     (Source : in Unbounded_String;
-      Left   : in Maps.Character_Set;
-      Right  : in Maps.Character_Set)
-      return   Unbounded_String
+     (Source : Unbounded_String;
+      Left   : Maps.Character_Set;
+      Right  : Maps.Character_Set) return Unbounded_String
    is
    begin
-      return
-        To_Unbounded_String (Fixed.Trim (Source.Reference.all, Left, Right));
+      return To_Unbounded_String
+        (Fixed.Trim (Source.Reference (1 .. Source.Last), Left, Right));
    end Trim;
 
    procedure Trim
      (Source : in out Unbounded_String;
-      Left   : in Maps.Character_Set;
-      Right  : in Maps.Character_Set)
+      Left   : Maps.Character_Set;
+      Right  : Maps.Character_Set)
    is
       Old : String_Access := Source.Reference;
-
    begin
-      Source.Reference := new String'(Fixed.Trim (Old.all, Left, Right));
+      Source.Reference := new String'
+        (Fixed.Trim (Source.Reference (1 .. Source.Last), Left, Right));
+      Source.Last      := Source.Reference'Length;
       Free (Old);
    end Trim;
 
+   ---------------------
+   -- Unbounded_Slice --
+   ---------------------
+
+   function Unbounded_Slice
+     (Source : Unbounded_String;
+      Low    : Positive;
+      High   : Natural) return Unbounded_String
+   is
+   begin
+      if Low > Source.Last + 1 or else High > Source.Last then
+         raise Index_Error;
+      else
+         return To_Unbounded_String (Source.Reference.all (Low .. High));
+      end if;
+   end Unbounded_Slice;
+
+   procedure Unbounded_Slice
+     (Source : Unbounded_String;
+      Target : out Unbounded_String;
+      Low    : Positive;
+      High   : Natural)
+   is
+   begin
+      if Low > Source.Last + 1 or else High > Source.Last then
+         raise Index_Error;
+      else
+         Target := To_Unbounded_String (Source.Reference.all (Low .. High));
+      end if;
+   end Unbounded_Slice;
+
 end Ada.Strings.Unbounded;