home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / adav313.zip / gnat-3_13p-os2-bin-20010916.zip / emx / gnatlib / a-strbou.adb < prev    next >
Text File  |  2000-07-19  |  55KB  |  1,785 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT RUNTIME COMPONENTS                          --
  4. --                                                                          --
  5. --                  A D A . S T R I N G S . B O U N D E D                   --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.20 $
  10. --                                                                          --
  11. --          Copyright (C) 1992-2000 Free Software Foundation, Inc.          --
  12. --                                                                          --
  13. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  21. -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
  22. -- MA 02111-1307, USA.                                                      --
  23. --                                                                          --
  24. -- As a special exception,  if other files  instantiate  generics from this --
  25. -- unit, or you link  this unit with other files  to produce an executable, --
  26. -- this  unit  does not  by itself cause  the resulting  executable  to  be --
  27. -- covered  by the  GNU  General  Public  License.  This exception does not --
  28. -- however invalidate  any other reasons why  the executable file  might be --
  29. -- covered by the  GNU Public License.                                      --
  30. --                                                                          --
  31. -- GNAT was originally developed  by the GNAT team at  New York University. --
  32. -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
  33. --                                                                          --
  34. ------------------------------------------------------------------------------
  35.  
  36. with Ada.Strings.Maps;   use Ada.Strings.Maps;
  37. with Ada.Strings.Search;
  38.  
  39. package body Ada.Strings.Bounded is
  40.  
  41.    package body Generic_Bounded_Length is
  42.  
  43.       ---------
  44.       -- "=" --
  45.       ---------
  46.  
  47.       function "=" (Left, Right : in Bounded_String) return Boolean is
  48.       begin
  49.          return Left.Length = Right.Length
  50.            and then Left.Data (1 .. Left.Length) =
  51.                     Right.Data (1 .. Right.Length);
  52.       end "=";
  53.  
  54.       function "="  (Left : in Bounded_String; Right : in String)
  55.          return Boolean is
  56.       begin
  57.          return Left.Length = Right'Length
  58.            and then Left.Data (1 .. Left.Length) = Right;
  59.       end "=";
  60.  
  61.       function "="  (Left : in String; Right : in Bounded_String)
  62.          return Boolean is
  63.       begin
  64.          return Left'Length = Right.Length
  65.            and then Left = Right.Data (1 .. Right.Length);
  66.       end "=";
  67.  
  68.       ---------
  69.       -- "<" --
  70.       ---------
  71.  
  72.       function "<" (Left, Right : in Bounded_String) return Boolean is
  73.       begin
  74.          return Left.Data (1 .. Left.Length) < Right.Data (1 .. Right.Length);
  75.       end "<";
  76.  
  77.       function "<"
  78.         (Left  : in Bounded_String;
  79.          Right : in String)
  80.          return  Boolean
  81.       is
  82.       begin
  83.          return Left.Data (1 .. Left.Length) < Right;
  84.       end "<";
  85.  
  86.       function "<"
  87.         (Left  : in String;
  88.          Right : in Bounded_String)
  89.          return  Boolean
  90.       is
  91.       begin
  92.          return Left < Right.Data (1 .. Right.Length);
  93.       end "<";
  94.  
  95.       ----------
  96.       -- "<=" --
  97.       ----------
  98.  
  99.       function "<=" (Left, Right : in Bounded_String) return Boolean is
  100.       begin
  101.          return Left.Data (1 .. Left.Length) <= Right.Data (1 .. Right.Length);
  102.       end "<=";
  103.  
  104.       function "<="
  105.         (Left  : in Bounded_String;
  106.          Right : in String)
  107.          return  Boolean
  108.       is
  109.       begin
  110.          return Left.Data (1 .. Left.Length) <= Right;
  111.       end "<=";
  112.  
  113.       function "<="
  114.         (Left  : in String;
  115.          Right : in Bounded_String)
  116.          return  Boolean
  117.       is
  118.       begin
  119.          return Left <= Right.Data (1 .. Right.Length);
  120.       end "<=";
  121.  
  122.       ---------
  123.       -- ">" --
  124.       ---------
  125.  
  126.       function ">" (Left, Right : in Bounded_String) return Boolean is
  127.       begin
  128.          return Left.Data (1 .. Left.Length) > Right.Data (1 .. Right.Length);
  129.       end ">";
  130.  
  131.       function ">"
  132.         (Left  : in Bounded_String;
  133.          Right : in String)
  134.          return  Boolean
  135.       is
  136.       begin
  137.          return Left.Data (1 .. Left.Length) > Right;
  138.       end ">";
  139.  
  140.       function ">"
  141.         (Left  : in String;
  142.          Right : in Bounded_String)
  143.          return  Boolean
  144.       is
  145.       begin
  146.          return Left > Right.Data (1 .. Right.Length);
  147.       end ">";
  148.  
  149.       ----------
  150.       -- ">=" --
  151.       ----------
  152.  
  153.       function ">=" (Left, Right : in Bounded_String) return Boolean is
  154.       begin
  155.          return Left.Data (1 .. Left.Length) >= Right.Data (1 .. Right.Length);
  156.       end ">=";
  157.  
  158.       function ">="
  159.         (Left  : in Bounded_String;
  160.          Right : in String)
  161.          return  Boolean
  162.       is
  163.       begin
  164.          return Left.Data (1 .. Left.Length) >= Right;
  165.       end ">=";
  166.  
  167.       function ">="
  168.         (Left  : in String;
  169.          Right : in Bounded_String)
  170.          return  Boolean
  171.       is
  172.       begin
  173.          return Left >= Right.Data (1 .. Right.Length);
  174.       end ">=";
  175.  
  176.       ---------
  177.       -- "*" --
  178.       ---------
  179.  
  180.       function "*"
  181.         (Left  : in Natural;
  182.          Right : in Character)
  183.          return  Bounded_String
  184.       is
  185.          Result : Bounded_String;
  186.  
  187.       begin
  188.          if Left > Max_Length then
  189.             raise Ada.Strings.Length_Error;
  190.          else
  191.             Result.Length := Left;
  192.  
  193.             for J in 1 .. Left loop
  194.                Result.Data (J) := Right;
  195.             end loop;
  196.          end if;
  197.  
  198.          return Result;
  199.       end "*";
  200.  
  201.       function "*"
  202.         (Left  : in Natural;
  203.          Right : in String)
  204.          return  Bounded_String
  205.       is
  206.          Result : Bounded_String;
  207.          Pos    : Positive         := 1;
  208.          Rlen   : constant Natural := Right'Length;
  209.          Nlen   : constant Natural := Left * Rlen;
  210.  
  211.       begin
  212.          if Nlen > Max_Length then
  213.             raise Ada.Strings.Index_Error;
  214.          else
  215.             Result.Length := Nlen;
  216.  
  217.             if Nlen > 0 then
  218.                for J in 1 .. Left loop
  219.                   Result.Data (Pos .. Pos + Rlen - 1) := Right;
  220.                   Pos := Pos + Rlen;
  221.                end loop;
  222.             end if;
  223.          end if;
  224.  
  225.          return Result;
  226.       end "*";
  227.  
  228.       function "*"
  229.         (Left  : in Natural;
  230.          Right : in Bounded_String)
  231.          return  Bounded_String
  232.       is
  233.          Result : Bounded_String;
  234.          Pos    : Positive := 1;
  235.          Rlen   : constant Length_Range := Right.Length;
  236.          Nlen   : constant Natural      := Left * Rlen;
  237.  
  238.       begin
  239.          if Nlen > Max_Length then
  240.             raise Ada.Strings.Length_Error;
  241.  
  242.          else
  243.             Result.Length := Nlen;
  244.  
  245.             if Nlen > 0 then
  246.                for J in 1 .. Left loop
  247.                   Result.Data (Pos .. Pos + Rlen - 1) :=
  248.                     Right.Data (1 .. Rlen);
  249.                   Pos := Pos + Rlen;
  250.                end loop;
  251.             end if;
  252.          end if;
  253.  
  254.          return Result;
  255.       end "*";
  256.  
  257.       ---------
  258.       -- "&" --
  259.       ---------
  260.  
  261.       function "&"
  262.         (Left  : in Bounded_String;
  263.          Right : in Bounded_String)
  264.          return  Bounded_String
  265.       is
  266.          Result : Bounded_String;
  267.          Llen   : constant Length_Range := Left.Length;
  268.          Rlen   : constant Length_Range := Right.Length;
  269.          Nlen   : constant Natural      := Llen + Rlen;
  270.  
  271.       begin
  272.          if Nlen > Max_Length then
  273.             raise Ada.Strings.Length_Error;
  274.          else
  275.             Result.Length := Nlen;
  276.             Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
  277.             Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
  278.          end if;
  279.  
  280.          return Result;
  281.       end "&";
  282.  
  283.       function "&"
  284.         (Left  : in Bounded_String;
  285.          Right : in String)
  286.          return  Bounded_String
  287.       is
  288.          Result : Bounded_String;
  289.          Llen   : constant Length_Range := Left.Length;
  290.  
  291.          Nlen   : constant Natural      := Llen + Right'Length;
  292.  
  293.       begin
  294.          if Nlen > Max_Length then
  295.             raise Ada.Strings.Length_Error;
  296.          else
  297.             Result.Length := Nlen;
  298.             Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
  299.             Result.Data (Llen + 1 .. Nlen) := Right;
  300.          end if;
  301.          return Result;
  302.       end "&";
  303.  
  304.       function "&"
  305.         (Left  : in String;
  306.          Right : in Bounded_String)
  307.          return  Bounded_String
  308.       is
  309.          Result : Bounded_String;
  310.          Llen   : constant Length_Range := Left'Length;
  311.          Rlen   : constant Length_Range := Right.Length;
  312.          Nlen   : constant Natural      := Llen + Rlen;
  313.  
  314.       begin
  315.          if Nlen > Max_Length then
  316.             raise Ada.Strings.Length_Error;
  317.          else
  318.             Result.Length := Nlen;
  319.             Result.Data (1 .. Llen) := Left;
  320.             Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
  321.          end if;
  322.  
  323.          return Result;
  324.       end "&";
  325.  
  326.       function "&"
  327.         (Left  : in Bounded_String;
  328.          Right : in Character)
  329.          return  Bounded_String
  330.       is
  331.          Result : Bounded_String;
  332.          Llen   : constant Length_Range := Left.Length;
  333.  
  334.       begin
  335.          if Llen = Max_Length then
  336.             raise Ada.Strings.Length_Error;
  337.          else
  338.             Result.Length := Llen + 1;
  339.             Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
  340.             Result.Data (Result.Length) := Right;
  341.          end if;
  342.  
  343.          return Result;
  344.       end "&";
  345.  
  346.       function "&"
  347.         (Left  : in Character;
  348.          Right : in Bounded_String)
  349.          return  Bounded_String
  350.       is
  351.          Result : Bounded_String;
  352.          Rlen   : Length_Range := Right.Length;
  353.  
  354.       begin
  355.          if Rlen = Max_Length then
  356.             raise Ada.Strings.Length_Error;
  357.          else
  358.             Result.Length := Rlen + 1;
  359.             Result.Data (1) := Left;
  360.             Result.Data (2 .. Result.Length) := Right.Data (1 .. Rlen);
  361.          end if;
  362.  
  363.          return Result;
  364.       end "&";
  365.  
  366.       ------------
  367.       -- Append --
  368.       ------------
  369.  
  370.       --  Case of Bounded_String and Bounded_String
  371.  
  372.       function Append
  373.         (Left, Right : in Bounded_String;
  374.          Drop        : in Strings.Truncation  := Strings.Error)
  375.          return        Bounded_String
  376.       is
  377.          Result : Bounded_String;
  378.          Llen   : constant Length_Range := Left.Length;
  379.          Rlen   : constant Length_Range := Right.Length;
  380.          Nlen   : constant Natural      := Llen + Rlen;
  381.  
  382.       begin
  383.          if Nlen <= Max_Length then
  384.             Result.Length := Nlen;
  385.             Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
  386.             Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
  387.  
  388.          else
  389.             Result.Length := Max_Length;
  390.  
  391.             case Drop is
  392.                when Strings.Right =>
  393.                   if Llen >= Max_Length then -- only case is Llen = Max_Length
  394.                      Result.Data := Left.Data;
  395.  
  396.                   else
  397.                      Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
  398.                      Result.Data (Llen + 1 .. Max_Length) :=
  399.                        Right.Data (1 .. Max_Length - Llen);
  400.                   end if;
  401.  
  402.                when Strings.Left =>
  403.                   if Rlen >= Max_Length then -- only case is Rlen = Max_Length
  404.                      Result.Data := Right.Data;
  405.  
  406.                   else
  407.                      Result.Data (1 .. Max_Length - Rlen) :=
  408.                        Left.Data (Llen - (Max_Length - Rlen - 1) .. Llen);
  409.                      Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
  410.                        Right.Data (1 .. Rlen);
  411.                   end if;
  412.  
  413.                when Strings.Error =>
  414.                   raise Ada.Strings.Length_Error;
  415.             end case;
  416.          end if;
  417.  
  418.          return Result;
  419.       end Append;
  420.  
  421.       procedure Append
  422.         (Source   : in out Bounded_String;
  423.          New_Item : in Bounded_String;
  424.          Drop     : in Truncation  := Error)
  425.       is
  426.          Llen   : constant Length_Range := Source.Length;
  427.          Rlen   : constant Length_Range := New_Item.Length;
  428.          Nlen   : constant Natural      := Llen + Rlen;
  429.  
  430.       begin
  431.          if Nlen <= Max_Length then
  432.             Source.Length := Nlen;
  433.             Source.Data (Llen + 1 .. Nlen) := New_Item.Data (1 .. Rlen);
  434.  
  435.          else
  436.             Source.Length := Max_Length;
  437.  
  438.             case Drop is
  439.                when Strings.Right =>
  440.                   if Llen < Max_Length then
  441.                      Source.Data (Llen + 1 .. Max_Length) :=
  442.                        New_Item.Data (1 .. Max_Length - Llen);
  443.                   end if;
  444.  
  445.                when Strings.Left =>
  446.                   if Rlen >= Max_Length then -- only case is Rlen = Max_Length
  447.                      Source.Data := New_Item.Data;
  448.  
  449.                   else
  450.                      Source.Data (1 .. Max_Length - Rlen) :=
  451.                        Source.Data (Llen - (Max_Length - Rlen - 1) .. Llen);
  452.                      Source.Data (Max_Length - Rlen + 1 .. Max_Length) :=
  453.                        New_Item.Data (1 .. Rlen);
  454.                   end if;
  455.  
  456.                when Strings.Error =>
  457.                   raise Ada.Strings.Length_Error;
  458.             end case;
  459.          end if;
  460.  
  461.       end Append;
  462.  
  463.       --  Case of Bounded_String and String
  464.  
  465.       function Append
  466.         (Left  : in Bounded_String;
  467.          Right : in String;
  468.          Drop  : in Strings.Truncation := Strings.Error)
  469.          return  Bounded_String
  470.       is
  471.          Result : Bounded_String;
  472.          Llen   : constant Length_Range := Left.Length;
  473.          Rlen   : constant Length_Range := Right'Length;
  474.          Nlen   : constant Natural      := Llen + Rlen;
  475.  
  476.       begin
  477.          if Nlen <= Max_Length then
  478.             Result.Length := Nlen;
  479.             Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
  480.             Result.Data (Llen + 1 .. Nlen) := Right;
  481.  
  482.          else
  483.             Result.Length := Max_Length;
  484.  
  485.             case Drop is
  486.                when Strings.Right =>
  487.                   if Llen >= Max_Length then -- only case is Llen = Max_Length
  488.                      Result.Data := Left.Data;
  489.  
  490.                   else
  491.                      Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
  492.                      Result.Data (Llen + 1 .. Max_Length) :=
  493.                        Right (Right'First .. Right'First - 1 +
  494.                                               Max_Length - Llen);
  495.  
  496.                   end if;
  497.  
  498.                when Strings.Left =>
  499.                   if Rlen >= Max_Length then
  500.                      Result.Data (1 .. Max_Length) :=
  501.                        Right (Right'Last - (Max_Length - 1) .. Right'Last);
  502.  
  503.                   else
  504.                      Result.Data (1 .. Max_Length - Rlen) :=
  505.                        Left.Data (Llen - (Max_Length - Rlen - 1) .. Llen);
  506.                      Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
  507.                        Right;
  508.                   end if;
  509.  
  510.                when Strings.Error =>
  511.                   raise Ada.Strings.Length_Error;
  512.             end case;
  513.          end if;
  514.  
  515.          return Result;
  516.       end Append;
  517.  
  518.       procedure Append
  519.         (Source   : in out Bounded_String;
  520.          New_Item : in String;
  521.          Drop     : in Truncation  := Error)
  522.       is
  523.          Llen   : constant Length_Range := Source.Length;
  524.          Rlen   : constant Length_Range := New_Item'Length;
  525.          Nlen   : constant Natural      := Llen + Rlen;
  526.  
  527.       begin
  528.          if Nlen <= Max_Length then
  529.             Source.Length := Nlen;
  530.             Source.Data (Llen + 1 .. Nlen) := New_Item;
  531.  
  532.          else
  533.             Source.Length := Max_Length;
  534.  
  535.             case Drop is
  536.                when Strings.Right =>
  537.                   if Llen < Max_Length then
  538.                      Source.Data (Llen + 1 .. Max_Length) :=
  539.                        New_Item (New_Item'First ..
  540.                                        New_Item'First - 1 + Max_Length - Llen);
  541.                   end if;
  542.  
  543.                when Strings.Left =>
  544.                   if Rlen >= Max_Length then
  545.                      Source.Data (1 .. Max_Length) :=
  546.                        New_Item (New_Item'Last - (Max_Length - 1) ..
  547.                                                                 New_Item'Last);
  548.  
  549.                   else
  550.                      Source.Data (1 .. Max_Length - Rlen) :=
  551.                        Source.Data (Llen - (Max_Length - Rlen - 1) .. Llen);
  552.                      Source.Data (Max_Length - Rlen + 1 .. Max_Length) :=
  553.                        New_Item;
  554.                   end if;
  555.  
  556.                when Strings.Error =>
  557.                   raise Ada.Strings.Length_Error;
  558.             end case;
  559.          end if;
  560.  
  561.       end Append;
  562.  
  563.       --  Case of String and Bounded_String
  564.  
  565.       function Append
  566.         (Left  : in String;
  567.          Right : in Bounded_String;
  568.          Drop  : in Strings.Truncation := Strings.Error)
  569.          return  Bounded_String
  570.       is
  571.          Result : Bounded_String;
  572.          Llen   : constant Length_Range := Left'Length;
  573.          Rlen   : constant Length_Range := Right.Length;
  574.          Nlen   : constant Natural      := Llen + Rlen;
  575.  
  576.       begin
  577.          if Nlen <= Max_Length then
  578.             Result.Length := Nlen;
  579.             Result.Data (1 .. Llen) := Left;
  580.             Result.Data (Llen + 1 .. Llen + Rlen) := Right.Data (1 .. Rlen);
  581.  
  582.          else
  583.             Result.Length := Max_Length;
  584.  
  585.             case Drop is
  586.                when Strings.Right =>
  587.                   if Llen >= Max_Length then
  588.                      Result.Data (1 .. Max_Length) :=
  589.                         Left (Left'First .. Left'First + (Max_Length - 1));
  590.  
  591.                   else
  592.                      Result.Data (1 .. Llen) := Left;
  593.                      Result.Data (Llen + 1 .. Max_Length) :=
  594.                        Right.Data (1 .. Max_Length - Llen);
  595.                   end if;
  596.  
  597.                when Strings.Left =>
  598.                   if Rlen >= Max_Length then
  599.                      Result.Data (1 .. Max_Length) :=
  600.                        Right.Data (Rlen - (Max_Length - 1) .. Rlen);
  601.  
  602.                   else
  603.                      Result.Data (1 .. Max_Length - Rlen) :=
  604.                        Left (Left'Last - (Max_Length - Rlen - 1) .. Left'Last);
  605.                      Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
  606.                        Right.Data (1 .. Rlen);
  607.                   end if;
  608.  
  609.                when Strings.Error =>
  610.                   raise Ada.Strings.Length_Error;
  611.             end case;
  612.          end if;
  613.  
  614.          return Result;
  615.       end Append;
  616.  
  617.       --  Case of Bounded_String and Character
  618.  
  619.       function Append
  620.         (Left  : in Bounded_String;
  621.          Right : in Character;
  622.          Drop  : in Strings.Truncation := Strings.Error)
  623.          return  Bounded_String
  624.       is
  625.          Result : Bounded_String;
  626.          Llen   : constant Length_Range := Left.Length;
  627.  
  628.       begin
  629.          if Llen  < Max_Length then
  630.             Result.Length := Llen + 1;
  631.             Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
  632.             Result.Data (Llen + 1) := Right;
  633.             return Result;
  634.  
  635.          else
  636.             case Drop is
  637.                when Strings.Right =>
  638.                   return Left;
  639.  
  640.                when Strings.Left =>
  641.                   Result.Length := Max_Length;
  642.                   Result.Data (1 .. Max_Length - 1) :=
  643.                     Left.Data (2 .. Max_Length);
  644.                   Result.Data (Max_Length) := Right;
  645.                   return Result;
  646.  
  647.                when Strings.Error =>
  648.                   raise Ada.Strings.Length_Error;
  649.             end case;
  650.          end if;
  651.       end Append;
  652.  
  653.       procedure Append
  654.         (Source   : in out Bounded_String;
  655.          New_Item : in Character;
  656.          Drop     : in Truncation  := Error)
  657.       is
  658.          Llen   : constant Length_Range := Source.Length;
  659.  
  660.       begin
  661.          if Llen  < Max_Length then
  662.             Source.Length := Llen + 1;
  663.             Source.Data (Llen + 1) := New_Item;
  664.  
  665.          else
  666.             Source.Length := Max_Length;
  667.  
  668.             case Drop is
  669.                when Strings.Right =>
  670.                   null;
  671.  
  672.                when Strings.Left =>
  673.                   Source.Data (1 .. Max_Length - 1) :=
  674.                     Source.Data (2 .. Max_Length);
  675.                   Source.Data (Max_Length) := New_Item;
  676.  
  677.                when Strings.Error =>
  678.                   raise Ada.Strings.Length_Error;
  679.             end case;
  680.          end if;
  681.  
  682.       end Append;
  683.  
  684.       --  Case of Character and Bounded_String
  685.  
  686.       function Append
  687.         (Left  : in Character;
  688.          Right : in Bounded_String;
  689.          Drop  : in Strings.Truncation := Strings.Error)
  690.          return  Bounded_String
  691.       is
  692.          Result : Bounded_String;
  693.          Rlen   : constant Length_Range := Right.Length;
  694.  
  695.       begin
  696.          if Rlen < Max_Length then
  697.             Result.Length := Rlen + 1;
  698.             Result.Data (1) := Left;
  699.             Result.Data (2 .. Rlen + 1) := Right.Data (1 .. Rlen);
  700.             return Result;
  701.  
  702.          else
  703.             case Drop is
  704.                when Strings.Right =>
  705.                   Result.Length := Max_Length;
  706.                   Result.Data (1) := Left;
  707.                   Result.Data (2 .. Max_Length) :=
  708.                     Right.Data (1 .. Max_Length - 1);
  709.                   return Result;
  710.  
  711.                when Strings.Left =>
  712.                   return Right;
  713.  
  714.                when Strings.Error =>
  715.                   raise Ada.Strings.Length_Error;
  716.             end case;
  717.          end if;
  718.       end Append;
  719.  
  720.       -----------
  721.       -- Count --
  722.       -----------
  723.  
  724.       function Count
  725.         (Source   : in Bounded_String;
  726.          Pattern  : in String;
  727.          Mapping  : in Maps.Character_Mapping := Maps.Identity)
  728.          return     Natural
  729.       is
  730.       begin
  731.          return
  732.            Search.Count (Source.Data (1 .. Source.Length), Pattern, Mapping);
  733.       end Count;
  734.  
  735.       function Count
  736.         (Source   : in Bounded_String;
  737.          Pattern  : in String;
  738.          Mapping  : in Maps.Character_Mapping_Function)
  739.          return     Natural
  740.       is
  741.       begin
  742.          return
  743.            Search.Count (Source.Data (1 .. Source.Length), Pattern, Mapping);
  744.       end Count;
  745.  
  746.       function Count
  747.         (Source : in Bounded_String;
  748.          Set    : in Maps.Character_Set)
  749.          return   Natural
  750.       is
  751.       begin
  752.          return Search.Count (Source.Data (1 .. Source.Length), Set);
  753.       end Count;
  754.  
  755.       ------------
  756.       -- Delete --
  757.       ------------
  758.  
  759.       function Delete
  760.         (Source  : in Bounded_String;
  761.          From    : in Positive;
  762.          Through : in Natural)
  763.          return    Bounded_String
  764.       is
  765.          Slen       : constant Natural := Source.Length;
  766.          Num_Delete : constant Integer := Through - From + 1;
  767.          Result     : Bounded_String;
  768.  
  769.       begin
  770.          if Num_Delete <= 0 then
  771.             return Source;
  772.  
  773.          elsif From > Slen + 1 then
  774.             raise Ada.Strings.Index_Error;
  775.  
  776.          elsif Through >= Slen then
  777.             Result.Length := From - 1;
  778.             Result.Data (1 .. From - 1) := Source.Data (1 .. From - 1);
  779.             return Result;
  780.  
  781.          else
  782.             Result.Length := Slen - Num_Delete;
  783.             Result.Data (1 .. From - 1) := Source.Data (1 .. From - 1);
  784.             Result.Data (From .. Result.Length) :=
  785.               Source.Data (Through + 1 .. Slen);
  786.             return Result;
  787.          end if;
  788.       end Delete;
  789.  
  790.       procedure Delete
  791.         (Source  : in out Bounded_String;
  792.          From    : in Positive;
  793.          Through : in Natural)
  794.       is
  795.          Slen       : constant Natural := Source.Length;
  796.          Num_Delete : constant Integer := Through - From + 1;
  797.  
  798.       begin
  799.          if Num_Delete <= 0 then
  800.             return;
  801.  
  802.          elsif From > Slen + 1 then
  803.             raise Ada.Strings.Index_Error;
  804.  
  805.          elsif Through >= Slen then
  806.             Source.Length := From - 1;
  807.  
  808.          else
  809.             Source.Length := Slen - Num_Delete;
  810.             Source.Data (From .. Source.Length) :=
  811.               Source.Data (Through + 1 .. Slen);
  812.          end if;
  813.       end Delete;
  814.  
  815.       -------------
  816.       -- Element --
  817.       -------------
  818.  
  819.       function Element
  820.         (Source : in Bounded_String;
  821.          Index  : in Positive)
  822.          return   Character
  823.       is
  824.       begin
  825.          if Index in 1 .. Source.Length then
  826.             return Source.Data (Index);
  827.          else
  828.             raise Strings.Index_Error;
  829.          end if;
  830.       end Element;
  831.  
  832.       ----------------
  833.       -- Find_Token --
  834.       ----------------
  835.  
  836.       procedure Find_Token
  837.         (Source : in Bounded_String;
  838.          Set    : in Maps.Character_Set;
  839.          Test   : in Strings.Membership;
  840.          First  : out Positive;
  841.          Last   : out Natural)
  842.       is
  843.       begin
  844.          Search.Find_Token
  845.            (Source.Data (1 .. Source.Length), Set, Test, First, Last);
  846.       end Find_Token;
  847.  
  848.  
  849.       ----------
  850.       -- Head --
  851.       ----------
  852.  
  853.       function Head
  854.         (Source : in Bounded_String;
  855.          Count  : in Natural;
  856.          Pad    : in Character := Space;
  857.          Drop   : in Strings.Truncation := Strings.Error)
  858.          return   Bounded_String
  859.       is
  860.          Result : Bounded_String;
  861.          Slen   : constant Natural := Source.Length;
  862.          Npad   : constant Integer := Count - Slen;
  863.  
  864.       begin
  865.          if Npad <= 0 then
  866.             Result.Length := Count;
  867.             Result.Data (1 .. Count) := Source.Data (1 .. Count);
  868.  
  869.          elsif Count <= Max_Length then
  870.             Result.Length := Count;
  871.             Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
  872.             Result.Data (Slen + 1 .. Count) := (others => Pad);
  873.  
  874.          else
  875.             Result.Length := Max_Length;
  876.  
  877.             case Drop is
  878.                when Strings.Right =>
  879.                   Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
  880.                   Result.Data (Slen + 1 .. Max_Length) := (others => Pad);
  881.  
  882.                when Strings.Left =>
  883.                   if Npad >= Max_Length then
  884.                      Result.Data := (others => Pad);
  885.  
  886.                   else
  887.                      Result.Data (1 .. Max_Length - Npad) :=
  888.                        Source.Data (Count - Max_Length + 1 .. Slen);
  889.                      Result.Data (Max_Length - Npad + 1 .. Max_Length) :=
  890.                        (others => Pad);
  891.                   end if;
  892.  
  893.                when Strings.Error =>
  894.                   raise Ada.Strings.Length_Error;
  895.             end case;
  896.          end if;
  897.  
  898.          return Result;
  899.       end Head;
  900.  
  901.       procedure Head
  902.         (Source : in out Bounded_String;
  903.          Count  : in Natural;
  904.          Pad    : in Character  := Space;
  905.          Drop   : in Truncation := Error)
  906.       is
  907.          Slen   : constant Natural := Source.Length;
  908.          Npad   : constant Integer := Count - Slen;
  909.          Temp   : String (1 .. Max_Length);
  910.  
  911.       begin
  912.          if Npad <= 0 then
  913.             Source.Length := Count;
  914.  
  915.          elsif Count <= Max_Length then
  916.             Source.Length := Count;
  917.             Source.Data (Slen + 1 .. Count) := (others => Pad);
  918.  
  919.          else
  920.             Source.Length := Max_Length;
  921.  
  922.             case Drop is
  923.                when Strings.Right =>
  924.                   Source.Data (Slen + 1 .. Max_Length) := (others => Pad);
  925.  
  926.                when Strings.Left =>
  927.                   if Npad > Max_Length then
  928.                      Source.Data := (others => Pad);
  929.  
  930.                   else
  931.                      Temp := Source.Data;
  932.                      Source.Data (1 .. Max_Length - Npad) :=
  933.                        Temp (Count - Max_Length + 1 .. Slen);
  934.  
  935.                      for J in Max_Length - Npad + 1 .. Max_Length loop
  936.                         Source.Data (J) := Pad;
  937.                      end loop;
  938.                   end if;
  939.  
  940.                when Strings.Error =>
  941.                   raise Ada.Strings.Length_Error;
  942.             end case;
  943.          end if;
  944.  
  945.       end Head;
  946.  
  947.       -----------
  948.       -- Index --
  949.       -----------
  950.  
  951.       function Index
  952.         (Source   : in Bounded_String;
  953.          Pattern  : in String;
  954.          Going    : in Strings.Direction := Strings.Forward;
  955.          Mapping  : in Maps.Character_Mapping := Maps.Identity)
  956.          return     Natural
  957.       is
  958.       begin
  959.          return Search.Index
  960.            (Source.Data (1 .. Source.Length), Pattern, Going, Mapping);
  961.       end Index;
  962.  
  963.       function Index
  964.         (Source   : in Bounded_String;
  965.          Pattern  : in String;
  966.          Going    : in Direction := Forward;
  967.          Mapping  : in Maps.Character_Mapping_Function)
  968.          return     Natural
  969.       is
  970.       begin
  971.          return Search.Index
  972.            (Source.Data (1 .. Source.Length), Pattern, Going, Mapping);
  973.       end Index;
  974.  
  975.       function Index
  976.         (Source : in Bounded_String;
  977.          Set    : in Maps.Character_Set;
  978.          Test   : in Strings.Membership := Strings.Inside;
  979.          Going  : in Strings.Direction  := Strings.Forward)
  980.          return   Natural
  981.       is
  982.       begin
  983.          return Search.Index
  984.            (Source.Data (1 .. Source.Length), Set, Test, Going);
  985.       end Index;
  986.  
  987.       ---------------------
  988.       -- Index_Non_Blank --
  989.       ---------------------
  990.  
  991.       function Index_Non_Blank
  992.         (Source : in Bounded_String;
  993.          Going  : in Strings.Direction := Strings.Forward)
  994.          return   Natural
  995.       is
  996.       begin
  997.          return
  998.            Search.Index_Non_Blank (Source.Data (1 .. Source.Length), Going);
  999.       end Index_Non_Blank;
  1000.  
  1001.       ------------
  1002.       -- Insert --
  1003.       ------------
  1004.  
  1005.       function Insert
  1006.         (Source   : in Bounded_String;
  1007.          Before   : in Positive;
  1008.          New_Item : in String;
  1009.          Drop     : in Strings.Truncation := Strings.Error)
  1010.          return     Bounded_String
  1011.       is
  1012.          Slen    : constant Natural := Source.Length;
  1013.          Nlen    : constant Natural := New_Item'Length;
  1014.          Tlen    : constant Natural := Slen + Nlen;
  1015.          Blen    : constant Natural := Before - 1;
  1016.          Alen    : constant Integer := Slen - Blen;
  1017.          Droplen : constant Integer := Tlen - Max_Length;
  1018.          Result  : Bounded_String;
  1019.  
  1020.          --  Tlen is the length of the total string before possible truncation.
  1021.          --  Blen, Alen are the lengths of the before and after pieces of the
  1022.          --  source string.
  1023.  
  1024.       begin
  1025.          if Alen < 0 then
  1026.             raise Ada.Strings.Index_Error;
  1027.  
  1028.          elsif Droplen <= 0 then
  1029.             Result.Length := Tlen;
  1030.             Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
  1031.             Result.Data (Before .. Before + Nlen - 1) := New_Item;
  1032.             Result.Data (Before + Nlen .. Tlen) :=
  1033.               Source.Data (Before .. Slen);
  1034.  
  1035.          else
  1036.             Result.Length := Max_Length;
  1037.  
  1038.             case Drop is
  1039.                when Strings.Right =>
  1040.                   Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
  1041.  
  1042.                   if Droplen > Alen then
  1043.                      Result.Data (Before .. Max_Length) :=
  1044.                        New_Item (New_Item'First
  1045.                                    .. New_Item'First + Max_Length - Before);
  1046.                   else
  1047.                      Result.Data (Before .. Before + Nlen - 1) := New_Item;
  1048.                      Result.Data (Before + Nlen .. Max_Length) :=
  1049.                        Source.Data (Before .. Slen - Droplen);
  1050.                   end if;
  1051.  
  1052.                when Strings.Left =>
  1053.                   Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
  1054.                     Source.Data (Before .. Slen);
  1055.  
  1056.                   if Droplen >= Blen then
  1057.                      Result.Data (1 .. Max_Length - Alen) :=
  1058.                        New_Item (New_Item'Last - (Max_Length - Alen) + 1
  1059.                                    .. New_Item'Last);
  1060.                   else
  1061.                      Result.Data
  1062.                        (Blen - Droplen + 1 .. Max_Length - Alen) :=
  1063.                          New_Item;
  1064.                      Result.Data (1 .. Blen - Droplen) :=
  1065.                        Source.Data (Droplen + 1 .. Blen);
  1066.                   end if;
  1067.  
  1068.                when Strings.Error =>
  1069.                   raise Ada.Strings.Length_Error;
  1070.             end case;
  1071.          end if;
  1072.  
  1073.          return Result;
  1074.       end Insert;
  1075.  
  1076.       procedure Insert
  1077.         (Source   : in out Bounded_String;
  1078.          Before   : in Positive;
  1079.          New_Item : in String;
  1080.          Drop     : in Strings.Truncation := Strings.Error)
  1081.       is
  1082.       begin
  1083.          --  We do a double copy here because this is one of the situations
  1084.          --  in which we move data to the right, and at least at the moment,
  1085.          --  GNAT is not handling such cases correctly ???
  1086.  
  1087.          Source := Insert (Source, Before, New_Item, Drop);
  1088.       end Insert;
  1089.  
  1090.       ------------
  1091.       -- Length --
  1092.       ------------
  1093.  
  1094.       function Length (Source : in Bounded_String) return Length_Range is
  1095.       begin
  1096.          return Source.Length;
  1097.       end Length;
  1098.  
  1099.       ---------------
  1100.       -- Overwrite --
  1101.       ---------------
  1102.  
  1103.       function Overwrite
  1104.         (Source    : in Bounded_String;
  1105.          Position  : in Positive;
  1106.          New_Item  : in String;
  1107.          Drop      : in Strings.Truncation := Strings.Error)
  1108.          return      Bounded_String
  1109.       is
  1110.          Result  : Bounded_String;
  1111.          Endpos  : constant Natural  := Position + New_Item'Length - 1;
  1112.          Slen    : constant Natural  := Source.Length;
  1113.          Droplen : Natural;
  1114.  
  1115.       begin
  1116.          if Position > Slen + 1 then
  1117.             raise Ada.Strings.Index_Error;
  1118.  
  1119.          elsif New_Item'Length = 0 then
  1120.             return Source;
  1121.  
  1122.          elsif Endpos <= Slen then
  1123.             Result.Length := Source.Length;
  1124.             Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
  1125.             Result.Data (Position .. Endpos) := New_Item;
  1126.             return Result;
  1127.  
  1128.          elsif Endpos <= Max_Length then
  1129.             Result.Length := Endpos;
  1130.             Result.Data (1 .. Position - 1) := Source.Data (1 .. Position - 1);
  1131.             Result.Data (Position .. Endpos) := New_Item;
  1132.             return Result;
  1133.  
  1134.          else
  1135.             Result.Length := Max_Length;
  1136.             Droplen := Endpos - Max_Length;
  1137.  
  1138.             case Drop is
  1139.                when Strings.Right =>
  1140.                   Result.Data (1 .. Position - 1) :=
  1141.                     Source.Data (1 .. Position - 1);
  1142.  
  1143.                   Result.Data (Position .. Max_Length) :=
  1144.                     New_Item (New_Item'First .. New_Item'Last - Droplen);
  1145.                   return Result;
  1146.  
  1147.                when Strings.Left =>
  1148.                   if New_Item'Length >= Max_Length then
  1149.                      Result.Data (1 .. Max_Length) :=
  1150.                         New_Item (New_Item'Last - Max_Length + 1 ..
  1151.                                   New_Item'Last);
  1152.                      return Result;
  1153.  
  1154.                   else
  1155.                      Result.Data (1 .. Max_Length - New_Item'Length) :=
  1156.                        Source.Data (Droplen + 1 .. Position - 1);
  1157.                      Result.Data
  1158.                        (Max_Length - New_Item'Length + 1 .. Max_Length) :=
  1159.                          New_Item;
  1160.                      return Result;
  1161.                   end if;
  1162.  
  1163.                when Strings.Error =>
  1164.                   raise Ada.Strings.Length_Error;
  1165.             end case;
  1166.          end if;
  1167.       end Overwrite;
  1168.  
  1169.       procedure Overwrite
  1170.         (Source    : in out Bounded_String;
  1171.          Position  : in Positive;
  1172.          New_Item  : in String;
  1173.          Drop      : in Strings.Truncation := Strings.Error)
  1174.       is
  1175.          Endpos  : constant Positive := Position + New_Item'Length - 1;
  1176.          Slen    : constant Natural  := Source.Length;
  1177.          Droplen : Natural;
  1178.  
  1179.       begin
  1180.          if Position > Slen + 1 then
  1181.             raise Ada.Strings.Index_Error;
  1182.  
  1183.          elsif Endpos <= Slen then
  1184.             Source.Data (Position .. Endpos) := New_Item;
  1185.  
  1186.          elsif Endpos <= Max_Length then
  1187.             Source.Data (Position .. Endpos) := New_Item;
  1188.             Source.Length := Endpos;
  1189.  
  1190.          else
  1191.             Source.Length := Max_Length;
  1192.             Droplen := Endpos - Max_Length;
  1193.  
  1194.             case Drop is
  1195.                when Strings.Right =>
  1196.                   Source.Data (Position .. Max_Length) :=
  1197.                     New_Item (New_Item'First .. New_Item'Last - Droplen);
  1198.  
  1199.                when Strings.Left =>
  1200.                   if New_Item'Length > Max_Length then
  1201.                      Source.Data (1 .. Max_Length) :=
  1202.                         New_Item (New_Item'Last - Max_Length + 1 ..
  1203.                                   New_Item'Last);
  1204.  
  1205.                   else
  1206.                      Source.Data (1 .. Max_Length - New_Item'Length) :=
  1207.                        Source.Data (Droplen + 1 .. Position - 1);
  1208.  
  1209.                      Source.Data
  1210.                        (Max_Length - New_Item'Length + 1 .. Max_Length) :=
  1211.                          New_Item;
  1212.                   end if;
  1213.  
  1214.                when Strings.Error =>
  1215.                   raise Ada.Strings.Length_Error;
  1216.             end case;
  1217.          end if;
  1218.       end Overwrite;
  1219.  
  1220.       ---------------------
  1221.       -- Replace_Element --
  1222.       ---------------------
  1223.  
  1224.       procedure Replace_Element
  1225.         (Source : in out Bounded_String;
  1226.          Index  : in Positive;
  1227.          By     : in Character)
  1228.       is
  1229.       begin
  1230.          if Index <= Source.Length then
  1231.             Source.Data (Index) := By;
  1232.          else
  1233.             raise Ada.Strings.Index_Error;
  1234.          end if;
  1235.       end Replace_Element;
  1236.  
  1237.       -------------------
  1238.       -- Replace_Slice --
  1239.       -------------------
  1240.  
  1241.       function Replace_Slice
  1242.         (Source   : in Bounded_String;
  1243.          Low      : in Positive;
  1244.          High     : in Natural;
  1245.          By       : in String;
  1246.          Drop     : in Strings.Truncation := Strings.Error)
  1247.          return     Bounded_String
  1248.       is
  1249.          Slen : constant Natural := Source.Length;
  1250.  
  1251.       begin
  1252.          if Low > Slen + 1 then
  1253.             raise Strings.Index_Error;
  1254.  
  1255.          elsif High < Low then
  1256.             return Insert (Source, Low, By, Drop);
  1257.  
  1258.          else
  1259.             declare
  1260.                Blen    : constant Natural := Natural'Max (0, Low - 1);
  1261.                Alen    : constant Natural := Natural'Max (0, Slen - High);
  1262.                Tlen    : constant Natural := Blen + By'Length + Alen;
  1263.                Droplen : constant Integer := Tlen - Max_Length;
  1264.                Result  : Bounded_String;
  1265.  
  1266.                --  Tlen is the total length of the result string before any
  1267.                --  truncation. Blen and Alen are the lengths of the pieces
  1268.                --  of the original string that end up in the result string
  1269.                --  before and after the replaced slice.
  1270.  
  1271.             begin
  1272.                if Droplen <= 0 then
  1273.                   Result.Length := Tlen;
  1274.                   Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
  1275.                   Result.Data (Low .. Low + By'Length - 1) := By;
  1276.                   Result.Data (Low + By'Length .. Tlen) :=
  1277.                     Source.Data (High + 1 .. Slen);
  1278.  
  1279.                else
  1280.                   Result.Length := Max_Length;
  1281.  
  1282.                   case Drop is
  1283.                      when Strings.Right =>
  1284.                         Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
  1285.  
  1286.                         if Droplen > Alen then
  1287.                            Result.Data (Low .. Max_Length) :=
  1288.                              By (By'First .. By'First + Max_Length - Low);
  1289.                         else
  1290.                            Result.Data (Low .. Low + By'Length - 1) := By;
  1291.                            Result.Data (Low + By'Length .. Max_Length) :=
  1292.                              Source.Data (High + 1 .. Slen - Droplen);
  1293.                         end if;
  1294.  
  1295.                      when Strings.Left =>
  1296.                         Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
  1297.                           Source.Data (High + 1 .. Slen);
  1298.  
  1299.                         if Droplen >= Blen then
  1300.                            Result.Data (1 .. Max_Length - Alen) :=
  1301.                              By (By'Last - (Max_Length - Alen) + 1 .. By'Last);
  1302.                         else
  1303.                            Result.Data
  1304.                              (Blen - Droplen + 1 .. Max_Length - Alen) := By;
  1305.                            Result.Data (1 .. Blen - Droplen) :=
  1306.                              Source.Data (Droplen + 1 .. Blen);
  1307.                         end if;
  1308.  
  1309.                      when Strings.Error =>
  1310.                         raise Ada.Strings.Length_Error;
  1311.                   end case;
  1312.                end if;
  1313.  
  1314.                return Result;
  1315.             end;
  1316.          end if;
  1317.       end Replace_Slice;
  1318.  
  1319.       procedure Replace_Slice
  1320.         (Source   : in out Bounded_String;
  1321.          Low      : in Positive;
  1322.          High     : in Natural;
  1323.          By       : in String;
  1324.          Drop     : in Strings.Truncation := Strings.Error)
  1325.       is
  1326.       begin
  1327.          --  We do a double copy here because this is one of the situations
  1328.          --  in which we move data to the right, and at least at the moment,
  1329.          --  GNAT is not handling such cases correctly ???
  1330.  
  1331.          Source := Replace_Slice (Source, Low, High, By, Drop);
  1332.       end Replace_Slice;
  1333.  
  1334.       ---------------
  1335.       -- Replicate --
  1336.       ---------------
  1337.  
  1338.       function Replicate
  1339.         (Count : in Natural;
  1340.          Item  : in Character;
  1341.          Drop  : in Strings.Truncation := Strings.Error)
  1342.          return  Bounded_String
  1343.       is
  1344.          Result : Bounded_String;
  1345.  
  1346.       begin
  1347.          if Count <= Max_Length then
  1348.             Result.Length := Count;
  1349.  
  1350.          elsif Drop = Strings.Error then
  1351.             raise Ada.Strings.Length_Error;
  1352.  
  1353.          else
  1354.             Result.Length := Max_Length;
  1355.          end if;
  1356.  
  1357.          Result.Data (1 .. Result.Length) := (others => Item);
  1358.          return Result;
  1359.       end Replicate;
  1360.  
  1361.       function Replicate
  1362.         (Count : in Natural;
  1363.          Item  : in String;
  1364.          Drop  : in Strings.Truncation := Strings.Error)
  1365.          return  Bounded_String
  1366.       is
  1367.          Length : constant Integer := Count * Item'Length;
  1368.          Result : Bounded_String;
  1369.          Indx   : Positive;
  1370.  
  1371.       begin
  1372.          if Length <= Max_Length then
  1373.             Result.Length := Length;
  1374.  
  1375.             if Length > 0 then
  1376.                Indx := 1;
  1377.  
  1378.                for J in 1 .. Count loop
  1379.                   Result.Data (Indx .. Indx + Item'Length - 1) := Item;
  1380.                   Indx := Indx + Item'Length;
  1381.                end loop;
  1382.             end if;
  1383.  
  1384.          else
  1385.             Result.Length := Max_Length;
  1386.  
  1387.             case Drop is
  1388.                when Strings.Right =>
  1389.                   Indx := 1;
  1390.  
  1391.                   while Indx + Item'Length <= Max_Length + 1 loop
  1392.                      Result.Data (Indx .. Indx + Item'Length - 1) := Item;
  1393.                      Indx := Indx + Item'Length;
  1394.                   end loop;
  1395.  
  1396.                   Result.Data (Indx .. Max_Length) :=
  1397.                     Item (Item'First .. Item'First + Max_Length - Indx);
  1398.  
  1399.                when Strings.Left =>
  1400.                   Indx := Max_Length;
  1401.  
  1402.                   while Indx - Item'Length >= 1 loop
  1403.                      Result.Data (Indx - (Item'Length - 1) .. Indx) := Item;
  1404.                      Indx := Indx - Item'Length;
  1405.                   end loop;
  1406.  
  1407.                   Result.Data (1 .. Indx) :=
  1408.                     Item (Item'Last - Indx + 1 .. Item'Last);
  1409.  
  1410.                when Strings.Error =>
  1411.                   raise Ada.Strings.Length_Error;
  1412.             end case;
  1413.          end if;
  1414.  
  1415.          return Result;
  1416.       end Replicate;
  1417.  
  1418.       function Replicate
  1419.         (Count : in Natural;
  1420.          Item  : in Bounded_String;
  1421.          Drop  : in Strings.Truncation := Strings.Error)
  1422.          return  Bounded_String
  1423.       is
  1424.       begin
  1425.          return Replicate (Count, Item.Data (1 .. Item.Length), Drop);
  1426.       end Replicate;
  1427.  
  1428.       -----------
  1429.       -- Slice --
  1430.       -----------
  1431.  
  1432.       function Slice
  1433.         (Source : Bounded_String;
  1434.          Low    : Positive;
  1435.          High   : Natural)
  1436.          return   String
  1437.       is
  1438.       begin
  1439.          --  Note: test of High > Length is in accordance with AI95-00128
  1440.  
  1441.          if Low > Source.Length + 1 or else High > Source.Length then
  1442.             raise Index_Error;
  1443.  
  1444.          else
  1445.             declare
  1446.                Result : String (1 .. High - Low + 1);
  1447.  
  1448.             begin
  1449.                Result := Source.Data (Low .. High);
  1450.                return Result;
  1451.             end;
  1452.          end if;
  1453.       end Slice;
  1454.  
  1455.       ----------
  1456.       -- Tail --
  1457.       ----------
  1458.  
  1459.       function Tail
  1460.         (Source : in Bounded_String;
  1461.          Count  : in Natural;
  1462.          Pad    : in Character := Space;
  1463.          Drop   : in Strings.Truncation := Strings.Error)
  1464.          return   Bounded_String
  1465.       is
  1466.          Result : Bounded_String;
  1467.          Slen   : constant Natural := Source.Length;
  1468.          Npad   : constant Integer := Count - Slen;
  1469.  
  1470.       begin
  1471.          if Npad <= 0 then
  1472.             Result.Length := Count;
  1473.             Result.Data (1 .. Count) :=
  1474.               Source.Data (Slen - (Count - 1) .. Slen);
  1475.  
  1476.          elsif Count <= Max_Length then
  1477.             Result.Length := Count;
  1478.             Result.Data (1 .. Npad) := (others => Pad);
  1479.             Result.Data (Npad + 1 .. Count) := Source.Data (1 .. Slen);
  1480.  
  1481.          else
  1482.             Result.Length := Max_Length;
  1483.  
  1484.             case Drop is
  1485.                when Strings.Right =>
  1486.                   if Npad >= Max_Length then
  1487.                      Result.Data := (others => Pad);
  1488.  
  1489.                   else
  1490.                      Result.Data (1 .. Npad) := (others => Pad);
  1491.                      Result.Data (Npad + 1 .. Max_Length) :=
  1492.                        Source.Data (1 .. Max_Length - Npad);
  1493.                   end if;
  1494.  
  1495.                when Strings.Left =>
  1496.                   Result.Data (1 .. Max_Length - Slen) := (others => Pad);
  1497.                   Result.Data (Max_Length - Slen + 1 .. Max_Length) :=
  1498.                     Source.Data (1 .. Slen);
  1499.  
  1500.                when Strings.Error =>
  1501.                   raise Ada.Strings.Length_Error;
  1502.             end case;
  1503.          end if;
  1504.  
  1505.          return Result;
  1506.       end Tail;
  1507.  
  1508.       procedure Tail
  1509.         (Source : in out Bounded_String;
  1510.          Count  : in Natural;
  1511.          Pad    : in Character  := Space;
  1512.          Drop   : in Truncation := Error)
  1513.       is
  1514.          Slen   : constant Natural := Source.Length;
  1515.          Npad   : constant Integer := Count - Slen;
  1516.          Temp   : String (1 .. Max_Length) := Source.Data;
  1517.  
  1518.       begin
  1519.          if Npad <= 0 then
  1520.             Source.Length := Count;
  1521.             Source.Data (1 .. Count) :=
  1522.               Temp (Slen - (Count - 1) .. Slen);
  1523.  
  1524.          elsif Count <= Max_Length then
  1525.             Source.Length := Count;
  1526.             Source.Data (1 .. Npad) := (others => Pad);
  1527.             Source.Data (Npad + 1 .. Count) := Temp (1 .. Slen);
  1528.  
  1529.          else
  1530.             Source.Length := Max_Length;
  1531.  
  1532.             case Drop is
  1533.                when Strings.Right =>
  1534.                   if Npad >= Max_Length then
  1535.                      Source.Data := (others => Pad);
  1536.  
  1537.                   else
  1538.                      Source.Data (1 .. Npad) := (others => Pad);
  1539.                      Source.Data (Npad + 1 .. Max_Length) :=
  1540.                        Temp (1 .. Max_Length - Npad);
  1541.                   end if;
  1542.  
  1543.                when Strings.Left =>
  1544.                   for J in 1 .. Max_Length - Slen loop
  1545.                      Source.Data (J) := Pad;
  1546.                   end loop;
  1547.  
  1548.                   Source.Data (Max_Length - Slen + 1 .. Max_Length) :=
  1549.                     Temp (1 .. Slen);
  1550.  
  1551.                when Strings.Error =>
  1552.                   raise Ada.Strings.Length_Error;
  1553.             end case;
  1554.          end if;
  1555.  
  1556.       end Tail;
  1557.  
  1558.       -----------------------
  1559.       -- To_Bounded_String --
  1560.       -----------------------
  1561.  
  1562.       function To_Bounded_String
  1563.         (Source : in String;
  1564.          Drop   : in Strings.Truncation := Strings.Error)
  1565.          return   Bounded_String
  1566.       is
  1567.          Slen   : constant Natural := Source'Length;
  1568.          Result : Bounded_String;
  1569.  
  1570.       begin
  1571.          if Slen <= Max_Length then
  1572.             Result.Length := Slen;
  1573.             Result.Data (1 .. Slen) := Source;
  1574.  
  1575.          else
  1576.             case Drop is
  1577.                when Strings.Right =>
  1578.                   Result.Length := Max_Length;
  1579.                   Result.Data (1 .. Max_Length) :=
  1580.                     Source (Source'First .. Source'First - 1 + Max_Length);
  1581.  
  1582.                when Strings.Left =>
  1583.                   Result.Length := Max_Length;
  1584.                   Result.Data (1 .. Max_Length) :=
  1585.                     Source (Source'Last - (Max_Length - 1) .. Source'Last);
  1586.  
  1587.                when Strings.Error =>
  1588.                   raise Ada.Strings.Length_Error;
  1589.             end case;
  1590.          end if;
  1591.  
  1592.          return Result;
  1593.       end To_Bounded_String;
  1594.  
  1595.       ---------------
  1596.       -- To_String --
  1597.       ---------------
  1598.  
  1599.       function To_String (Source : in Bounded_String) return String is
  1600.       begin
  1601.          return Source.Data (1 .. Source.Length);
  1602.       end To_String;
  1603.  
  1604.       ---------------
  1605.       -- Translate --
  1606.       ---------------
  1607.  
  1608.       function Translate
  1609.         (Source  : in Bounded_String;
  1610.          Mapping : in Maps.Character_Mapping)
  1611.          return    Bounded_String
  1612.       is
  1613.          Result : Bounded_String;
  1614.  
  1615.       begin
  1616.          Result.Length := Source.Length;
  1617.  
  1618.          for J in 1 .. Source.Length loop
  1619.             Result.Data (J) := Value (Mapping, Source.Data (J));
  1620.          end loop;
  1621.  
  1622.          return Result;
  1623.       end Translate;
  1624.  
  1625.       procedure Translate
  1626.         (Source  : in out Bounded_String;
  1627.          Mapping : in Maps.Character_Mapping)
  1628.       is
  1629.       begin
  1630.          for J in 1 .. Source.Length loop
  1631.             Source.Data (J) := Value (Mapping, Source.Data (J));
  1632.          end loop;
  1633.       end Translate;
  1634.  
  1635.       function Translate
  1636.         (Source  : in Bounded_String;
  1637.          Mapping : in Maps.Character_Mapping_Function)
  1638.          return Bounded_String
  1639.       is
  1640.          Result : Bounded_String;
  1641.  
  1642.       begin
  1643.          Result.Length := Source.Length;
  1644.  
  1645.          for J in 1 .. Source.Length loop
  1646.             Result.Data (J) := Mapping.all (Source.Data (J));
  1647.          end loop;
  1648.  
  1649.          return Result;
  1650.       end Translate;
  1651.  
  1652.       procedure Translate
  1653.         (Source  : in out Bounded_String;
  1654.          Mapping : in Maps.Character_Mapping_Function)
  1655.       is
  1656.       begin
  1657.          for J in 1 .. Source.Length loop
  1658.             Source.Data (J) := Mapping.all (Source.Data (J));
  1659.          end loop;
  1660.       end Translate;
  1661.  
  1662.       ----------
  1663.       -- Trim --
  1664.       ----------
  1665.  
  1666.       function Trim (Source : in Bounded_String; Side : in Trim_End)
  1667.          return Bounded_String
  1668.       is
  1669.          Result : Bounded_String;
  1670.          Last   : Natural := Source.Length;
  1671.          First  : Positive := 1;
  1672.  
  1673.       begin
  1674.          if Side = Left or else Side = Both then
  1675.             while First <= Last and then Source.Data (First) = ' ' loop
  1676.                First := First + 1;
  1677.             end loop;
  1678.          end if;
  1679.  
  1680.          if Side = Right or else Side = Both then
  1681.             while Last >= First and then Source.Data (Last) = ' ' loop
  1682.                Last := Last - 1;
  1683.             end loop;
  1684.          end if;
  1685.  
  1686.          Result.Length := Last - First + 1;
  1687.          Result.Data (1 .. Result.Length) := Source.Data (First .. Last);
  1688.          return Result;
  1689.  
  1690.       end Trim;
  1691.  
  1692.       procedure Trim
  1693.         (Source : in out Bounded_String;
  1694.          Side   : in Trim_End)
  1695.       is
  1696.          Last   : Length_Range := Source.Length;
  1697.          First  : Positive     := 1;
  1698.          Temp   : String (1 .. Max_Length);
  1699.  
  1700.       begin
  1701.          Temp (1 .. Last) := Source.Data (1 .. Last);
  1702.  
  1703.          if Side = Left or else Side = Both then
  1704.             while First <= Last and then Temp (First) = ' ' loop
  1705.                First := First + 1;
  1706.             end loop;
  1707.          end if;
  1708.  
  1709.          if Side = Right or else Side = Both then
  1710.             while Last >= First and then Temp (Last) = ' ' loop
  1711.                Last := Last - 1;
  1712.             end loop;
  1713.          end if;
  1714.  
  1715.          Source := Null_Bounded_String;
  1716.          Source.Length := Last - First + 1;
  1717.          Source.Data (1 .. Source.Length) := Temp (First .. Last);
  1718.  
  1719.       end Trim;
  1720.  
  1721.       function Trim
  1722.         (Source : in Bounded_String;
  1723.          Left   : in Maps.Character_Set;
  1724.          Right  : in Maps.Character_Set)
  1725.          return   Bounded_String
  1726.       is
  1727.          Result : Bounded_String;
  1728.  
  1729.       begin
  1730.          for First in 1 .. Source.Length loop
  1731.             if not Is_In (Source.Data (First), Left) then
  1732.                for Last in reverse First .. Source.Length loop
  1733.                   if not Is_In (Source.Data (Last), Right) then
  1734.                      Result.Length := Last - First + 1;
  1735.                      Result.Data (1 .. Result.Length) :=
  1736.                         Source.Data (First .. Last);
  1737.                      return Result;
  1738.                   end if;
  1739.                end loop;
  1740.             end if;
  1741.          end loop;
  1742.  
  1743.          Result.Length := 0;
  1744.          return Result;
  1745.       end Trim;
  1746.  
  1747.       procedure Trim
  1748.         (Source : in out Bounded_String;
  1749.          Left   : in Maps.Character_Set;
  1750.          Right  : in Maps.Character_Set)
  1751.       is
  1752.       begin
  1753.          for First in 1 .. Source.Length loop
  1754.             if not Is_In (Source.Data (First), Left) then
  1755.                for Last in reverse First .. Source.Length loop
  1756.                   if not Is_In (Source.Data (Last), Right) then
  1757.                      if First = 1 then
  1758.                         Source.Length := Last;
  1759.                         return;
  1760.                      else
  1761.                         Source.Length := Last - First + 1;
  1762.                         Source.Data (1 .. Source.Length) :=
  1763.                           Source.Data (First .. Last);
  1764.  
  1765.                         for J in Source.Length + 1 .. Max_Length loop
  1766.                            Source.Data (J) := ASCII.NUL;
  1767.                         end loop;
  1768.  
  1769.                         return;
  1770.                      end if;
  1771.                   end if;
  1772.                end loop;
  1773.  
  1774.                Source.Length := 0;
  1775.                return;
  1776.             end if;
  1777.          end loop;
  1778.  
  1779.          Source.Length := 0;
  1780.       end Trim;
  1781.  
  1782.    end Generic_Bounded_Length;
  1783.  
  1784. end Ada.Strings.Bounded;
  1785.