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