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-stwima.adb < prev    next >
Text File  |  2000-07-19  |  21KB  |  759 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT RUNTIME COMPONENTS                          --
  4. --                                                                          --
  5. --                A D A . S T R I N G S . W I D E _ M A P S                 --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.17 $                             --
  10. --                                                                          --
  11. --          Copyright (C) 1992-1998 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 Unchecked_Deallocation;
  37.  
  38. package body Ada.Strings.Wide_Maps is
  39.  
  40.    ---------
  41.    -- "=" --
  42.    ---------
  43.  
  44.    --  The sorted, discontiguous form is canonical, so equality can be used
  45.  
  46.    function "=" (Left, Right : in Wide_Character_Set) return Boolean is
  47.    begin
  48.       return Left.Set.all = Right.Set.all;
  49.    end "=";
  50.  
  51.    ---------
  52.    -- "-" --
  53.    ---------
  54.  
  55.    function "-"
  56.      (Left, Right : in Wide_Character_Set)
  57.       return        Wide_Character_Set
  58.    is
  59.       LS : constant Wide_Character_Ranges_Access := Left.Set;
  60.       RS : constant Wide_Character_Ranges_Access := Right.Set;
  61.  
  62.       Result : Wide_Character_Ranges (1 .. LS'Last + RS'Last);
  63.       --  Each range on the right can generate at least one more range in
  64.       --  the result, by splitting one of the left operand ranges.
  65.  
  66.       N  : Natural := 0;
  67.       R  : Natural := 1;
  68.       L  : Natural := 1;
  69.  
  70.       Left_Low : Wide_Character;
  71.       --  Left_Low is lowest character of the L'th range not yet dealt with
  72.  
  73.    begin
  74.       if LS'Last = 0 or else RS'Last = 0 then
  75.          return Left;
  76.       end if;
  77.  
  78.       Left_Low := LS (L).Low;
  79.       while R <= RS'Last loop
  80.  
  81.          --  If next right range is below current left range, skip it
  82.  
  83.          if RS (R).High < Left_Low then
  84.             R := R + 1;
  85.  
  86.          --  If next right range above current left range, copy remainder
  87.          --  of the left range to the result
  88.  
  89.          elsif RS (R).Low > LS (L).High then
  90.             N := N + 1;
  91.             Result (N).Low  := Left_Low;
  92.             Result (N).High := LS (L).High;
  93.             L := L + 1;
  94.             exit when L > LS'Last;
  95.             Left_Low := LS (L).Low;
  96.  
  97.          else
  98.             --  Next right range overlaps bottom of left range
  99.  
  100.             if RS (R).Low <= Left_Low then
  101.  
  102.                --  Case of right range complete overlaps left range
  103.  
  104.                if RS (R).High >= LS (L).High then
  105.                   L := L + 1;
  106.                   exit when L > LS'Last;
  107.                   Left_Low := LS (L).Low;
  108.  
  109.                --  Case of right range eats lower part of left range
  110.  
  111.                else
  112.                   Left_Low := Wide_Character'Succ (RS (R).High);
  113.                   R := R + 1;
  114.                end if;
  115.  
  116.             --  Next right range overlaps some of left range, but not bottom
  117.  
  118.             else
  119.                N := N + 1;
  120.                Result (N).Low  := Left_Low;
  121.                Result (N).High := Wide_Character'Pred (RS (R).Low);
  122.  
  123.                --  Case of right range splits left range
  124.  
  125.                if RS (R).High < LS (L).High then
  126.                   Left_Low := Wide_Character'Succ (RS (R).High);
  127.                   R := R + 1;
  128.  
  129.                --  Case of right range overlaps top of left range
  130.  
  131.                else
  132.                   L := L + 1;
  133.                   exit when L > LS'Last;
  134.                   Left_Low := LS (L).Low;
  135.                end if;
  136.             end if;
  137.          end if;
  138.       end loop;
  139.  
  140.       --  Copy remainder of left ranges to result
  141.  
  142.       if L <= LS'Last then
  143.          N := N + 1;
  144.          Result (N).Low  := Left_Low;
  145.          Result (N).High := LS (L).High;
  146.  
  147.          loop
  148.             L := L + 1;
  149.             exit when L > LS'Last;
  150.             N := N + 1;
  151.             Result (N) := LS (L);
  152.          end loop;
  153.       end if;
  154.  
  155.       return (AF.Controlled with
  156.               Set => new Wide_Character_Ranges'(Result (1 .. N)));
  157.    end "-";
  158.  
  159.    -----------
  160.    -- "and" --
  161.    -----------
  162.  
  163.    function "and"
  164.      (Left, Right : in Wide_Character_Set)
  165.       return        Wide_Character_Set
  166.    is
  167.       LS : constant Wide_Character_Ranges_Access := Left.Set;
  168.       RS : constant Wide_Character_Ranges_Access := Right.Set;
  169.  
  170.       Result : Wide_Character_Ranges (1 .. LS'Last + RS'Last);
  171.       N      : Natural := 0;
  172.       L, R   : Natural := 1;
  173.  
  174.    begin
  175.       --  Loop to search for overlapping character ranges
  176.  
  177.       while L <= LS'Last and then R <= RS'Last loop
  178.  
  179.          if LS (L).High < RS (R).Low then
  180.             L := L + 1;
  181.  
  182.          elsif RS (R).High < LS (L).Low then
  183.             R := R + 1;
  184.  
  185.          --  Here we have LS (L).High >= RS (R).Low
  186.          --           and RS (R).High >= LS (L).Low
  187.          --  so we have an overlapping range
  188.  
  189.          else
  190.             N := N + 1;
  191.             Result (N).Low := Wide_Character'Max (LS (L).Low,  RS (R).Low);
  192.             Result (N).High :=
  193.               Wide_Character'Min (LS (L).High, RS (R).High);
  194.  
  195.             if RS (R).High = LS (L).High then
  196.                L := L + 1;
  197.                R := R + 1;
  198.             elsif RS (R).High < LS (L).High then
  199.                R := R + 1;
  200.             else
  201.                L := L + 1;
  202.             end if;
  203.          end if;
  204.       end loop;
  205.  
  206.       return (AF.Controlled with
  207.               Set       => new Wide_Character_Ranges'(Result (1 .. N)));
  208.    end "and";
  209.  
  210.    -----------
  211.    -- "not" --
  212.    -----------
  213.  
  214.    function "not"
  215.      (Right  : in Wide_Character_Set)
  216.       return Wide_Character_Set
  217.    is
  218.       RS : constant Wide_Character_Ranges_Access := Right.Set;
  219.  
  220.       Result : Wide_Character_Ranges (1 .. RS'Last + 1);
  221.       N      : Natural := 0;
  222.  
  223.    begin
  224.       if RS'Last = 0 then
  225.          N := 1;
  226.          Result (1) := (Low  => Wide_Character'First,
  227.                         High => Wide_Character'Last);
  228.  
  229.       else
  230.          if RS (1).Low /= Wide_Character'First then
  231.             N := N + 1;
  232.             Result (N).Low  := Wide_Character'First;
  233.             Result (N).High := Wide_Character'Pred (RS (1).Low);
  234.          end if;
  235.  
  236.          for K in 1 .. RS'Last - 1 loop
  237.             N := N + 1;
  238.             Result (N).Low  := Wide_Character'Succ (RS (K).High);
  239.             Result (N).High := Wide_Character'Pred (RS (K + 1).Low);
  240.          end loop;
  241.  
  242.          if RS (RS'Last).High /= Wide_Character'Last then
  243.             N := N + 1;
  244.             Result (N).Low  := Wide_Character'Succ (RS (RS'Last).High);
  245.             Result (N).High := Wide_Character'Last;
  246.          end if;
  247.       end if;
  248.  
  249.       return (AF.Controlled with
  250.               Set => new Wide_Character_Ranges'(Result (1 .. N)));
  251.    end "not";
  252.  
  253.    ----------
  254.    -- "or" --
  255.    ----------
  256.  
  257.    function "or"
  258.      (Left, Right : in Wide_Character_Set)
  259.       return        Wide_Character_Set
  260.    is
  261.       LS : constant Wide_Character_Ranges_Access := Left.Set;
  262.       RS : constant Wide_Character_Ranges_Access := Right.Set;
  263.  
  264.       Result : Wide_Character_Ranges (1 .. LS'Last + RS'Last);
  265.       N      : Natural;
  266.       L, R   : Natural;
  267.  
  268.    begin
  269.       N := 0;
  270.       L := 1;
  271.       R := 1;
  272.  
  273.       --  Loop through ranges in output file
  274.  
  275.       loop
  276.          --  If no left ranges left, copy next right range
  277.  
  278.          if L > LS'Last then
  279.             exit when R > RS'Last;
  280.             N := N + 1;
  281.             Result (N) := RS (R);
  282.             R := R + 1;
  283.  
  284.          --  If no right ranges left, copy next left range
  285.  
  286.          elsif R > RS'Last then
  287.             N := N + 1;
  288.             Result (N) := LS (L);
  289.             L := L + 1;
  290.  
  291.          else
  292.             --  We have two ranges, choose lower one
  293.  
  294.             N := N + 1;
  295.  
  296.             if LS (L).Low <= RS (R).Low then
  297.                Result (N) := LS (L);
  298.                L := L + 1;
  299.             else
  300.                Result (N) := RS (R);
  301.                R := R + 1;
  302.             end if;
  303.  
  304.             --  Loop to collapse ranges into last range
  305.  
  306.             loop
  307.                --  Collapse next length range into current result range
  308.                --  if possible.
  309.  
  310.                if L <= LS'Last
  311.                  and then LS (L).Low <= Wide_Character'Succ (Result (N).High)
  312.                then
  313.                   Result (N).High :=
  314.                     Wide_Character'Max (Result (N).High, LS (L).High);
  315.                   L := L + 1;
  316.  
  317.                --  Collapse next right range into current result range
  318.                --  if possible
  319.  
  320.                elsif R <= RS'Last
  321.                  and then RS (R).Low <=
  322.                             Wide_Character'Succ (Result (N).High)
  323.                then
  324.                   Result (N).High :=
  325.                     Wide_Character'Max (Result (N).High, RS (R).High);
  326.                   R := R + 1;
  327.  
  328.                --  If neither range collapses, then done with this range
  329.  
  330.                else
  331.                   exit;
  332.                end if;
  333.             end loop;
  334.          end if;
  335.       end loop;
  336.  
  337.       return (AF.Controlled with
  338.               Set => new Wide_Character_Ranges'(Result (1 .. N)));
  339.    end "or";
  340.  
  341.    -----------
  342.    -- "xor" --
  343.    -----------
  344.  
  345.    function "xor"
  346.      (Left, Right : in Wide_Character_Set)
  347.       return        Wide_Character_Set
  348.    is
  349.    begin
  350.       return (Left or Right) - (Left and Right);
  351.    end "xor";
  352.  
  353.    ------------
  354.    -- Adjust --
  355.    ------------
  356.  
  357.    procedure Adjust (Object : in out Wide_Character_Mapping) is
  358.    begin
  359.       Object.Map := new Wide_Character_Mapping_Values'(Object.Map.all);
  360.    end Adjust;
  361.  
  362.    procedure Adjust (Object : in out Wide_Character_Set) is
  363.    begin
  364.       Object.Set := new Wide_Character_Ranges'(Object.Set.all);
  365.    end Adjust;
  366.  
  367.    --------------
  368.    -- Finalize --
  369.    --------------
  370.  
  371.    procedure Finalize (Object : in out Wide_Character_Mapping) is
  372.  
  373.       procedure Free is new Unchecked_Deallocation
  374.         (Wide_Character_Mapping_Values,
  375.          Wide_Character_Mapping_Values_Access);
  376.  
  377.    begin
  378.       if Object.Map /=  Null_Map'Unrestricted_Access then
  379.          Free (Object.Map);
  380.       end if;
  381.    end Finalize;
  382.  
  383.    procedure Finalize (Object : in out Wide_Character_Set) is
  384.  
  385.       procedure Free is new Unchecked_Deallocation
  386.         (Wide_Character_Ranges,
  387.          Wide_Character_Ranges_Access);
  388.  
  389.    begin
  390.       if Object.Set /= Null_Range'Unrestricted_Access then
  391.          Free (Object.Set);
  392.       end if;
  393.    end Finalize;
  394.  
  395.    ----------------
  396.    -- Initialize --
  397.    ----------------
  398.  
  399.    procedure Initialize (Object : in out Wide_Character_Mapping) is
  400.    begin
  401.       Object := Identity;
  402.    end Initialize;
  403.  
  404.    procedure Initialize (Object : in out Wide_Character_Set) is
  405.    begin
  406.       Object := Null_Set;
  407.    end Initialize;
  408.  
  409.    -----------
  410.    -- Is_In --
  411.    -----------
  412.  
  413.    function Is_In
  414.      (Element : in Wide_Character;
  415.       Set     : in Wide_Character_Set)
  416.       return    Boolean
  417.    is
  418.       L, R, M : Natural;
  419.       SS      : constant Wide_Character_Ranges_Access := Set.Set;
  420.  
  421.    begin
  422.       L := 1;
  423.       R := SS'Last;
  424.  
  425.       --  Binary search loop. The invariant is that if Element is in any of
  426.       --  of the constituent ranges it is in one between Set (L) and Set (R).
  427.  
  428.       loop
  429.          if L > R then
  430.             return False;
  431.  
  432.          else
  433.             M := (L + R) / 2;
  434.  
  435.             if Element > SS (M).High then
  436.                L := M + 1;
  437.             elsif Element < SS (M).Low then
  438.                R := M - 1;
  439.             else
  440.                return True;
  441.             end if;
  442.          end if;
  443.       end loop;
  444.    end Is_In;
  445.  
  446.    ---------------
  447.    -- Is_Subset --
  448.    ---------------
  449.  
  450.    function Is_Subset
  451.      (Elements : in Wide_Character_Set;
  452.       Set      : in Wide_Character_Set)
  453.       return     Boolean
  454.    is
  455.       ES : constant Wide_Character_Ranges_Access := Elements.Set;
  456.       SS : constant Wide_Character_Ranges_Access := Set.Set;
  457.  
  458.       S  : Positive := 1;
  459.       E  : Positive := 1;
  460.  
  461.    begin
  462.       loop
  463.          --  If no more element ranges, done, and result is true
  464.  
  465.          if E > ES'Last then
  466.             return True;
  467.  
  468.          --  If more element ranges, but no more set ranges, result is false
  469.  
  470.          elsif S > SS'Last then
  471.             return False;
  472.  
  473.          --  Remove irrelevant set range
  474.  
  475.          elsif SS (S).High < ES (E).Low then
  476.             S := S + 1;
  477.  
  478.          --  Get rid of element range that is properly covered by set
  479.  
  480.          elsif SS (S).Low <= ES (E).Low
  481.             and then ES (E).High <= SS (S).High
  482.          then
  483.             E := E + 1;
  484.  
  485.          --  Otherwise we have a non-covered element range, result is false
  486.  
  487.          else
  488.             return False;
  489.          end if;
  490.       end loop;
  491.    end Is_Subset;
  492.  
  493.    ---------------
  494.    -- To_Domain --
  495.    ---------------
  496.  
  497.    function To_Domain
  498.      (Map  : in Wide_Character_Mapping)
  499.       return Wide_Character_Sequence
  500.    is
  501.    begin
  502.       return Map.Map.Domain;
  503.    end To_Domain;
  504.  
  505.    ----------------
  506.    -- To_Mapping --
  507.    ----------------
  508.  
  509.    function To_Mapping
  510.      (From, To : in Wide_Character_Sequence)
  511.       return     Wide_Character_Mapping
  512.    is
  513.       Domain : Wide_Character_Sequence (1 .. From'Length);
  514.       Rangev : Wide_Character_Sequence (1 .. To'Length);
  515.       N      : Natural := 0;
  516.  
  517.    begin
  518.       if From'Length /= To'Length then
  519.          raise Translation_Error;
  520.  
  521.       else
  522.          pragma Warnings (Off); -- apparent uninit use of Domain
  523.  
  524.          for J in From'Range loop
  525.             for M in 1 .. N loop
  526.                if From (J) = Domain (M) then
  527.                   raise Translation_Error;
  528.                elsif From (J) < Domain (M) then
  529.                   Domain (M + 1 .. N + 1) := Domain (M .. N);
  530.                   Rangev (M + 1 .. N + 1) := Rangev (M .. N);
  531.                   Domain (M) := From (J);
  532.                   Rangev (M) := To   (J);
  533.                   goto Continue;
  534.                end if;
  535.             end loop;
  536.  
  537.             Domain (N + 1) := From (J);
  538.             Rangev (N + 1) := To   (J);
  539.  
  540.             <<Continue>>
  541.                N := N + 1;
  542.          end loop;
  543.  
  544.          pragma Warnings (On);
  545.  
  546.          return (AF.Controlled with
  547.                  Map => new Wide_Character_Mapping_Values'(
  548.                           Length => N,
  549.                           Domain => Domain (1 .. N),
  550.                           Rangev => Rangev (1 .. N)));
  551.       end if;
  552.    end To_Mapping;
  553.  
  554.    --------------
  555.    -- To_Range --
  556.    --------------
  557.  
  558.    function To_Range
  559.      (Map  : in Wide_Character_Mapping)
  560.       return Wide_Character_Sequence
  561.    is
  562.    begin
  563.       return Map.Map.Rangev;
  564.    end To_Range;
  565.  
  566.    ---------------
  567.    -- To_Ranges --
  568.    ---------------
  569.  
  570.    function To_Ranges
  571.      (Set :  in Wide_Character_Set)
  572.       return Wide_Character_Ranges
  573.    is
  574.    begin
  575.       return Set.Set.all;
  576.    end To_Ranges;
  577.  
  578.    -----------------
  579.    -- To_Sequence --
  580.    -----------------
  581.  
  582.    function To_Sequence
  583.      (Set  : in Wide_Character_Set)
  584.       return Wide_Character_Sequence
  585.    is
  586.       SS : constant Wide_Character_Ranges_Access := Set.Set;
  587.  
  588.       Result : Wide_String (Positive range 1 .. 2 ** 16);
  589.       N      : Natural := 0;
  590.  
  591.    begin
  592.       for J in SS'Range loop
  593.          for K in SS (J).Low .. SS (J).High loop
  594.             N := N + 1;
  595.             Result (N) := K;
  596.          end loop;
  597.       end loop;
  598.  
  599.       return Result (1 .. N);
  600.    end To_Sequence;
  601.  
  602.    ------------
  603.    -- To_Set --
  604.    ------------
  605.  
  606.    --  Case of multiple range input
  607.  
  608.    function To_Set
  609.      (Ranges : in Wide_Character_Ranges)
  610.       return   Wide_Character_Set
  611.    is
  612.       Result : Wide_Character_Ranges (Ranges'Range);
  613.       N      : Natural := 0;
  614.       J      : Natural;
  615.  
  616.    begin
  617.       --  The output of To_Set is required to be sorted by increasing Low
  618.       --  values, and discontiguous, so first we sort them as we enter them,
  619.       --  using a simple insertion sort.
  620.  
  621.       pragma Warnings (Off);
  622.       --  Kill bogus warning on Result being uninitialized
  623.  
  624.       for J in Ranges'Range loop
  625.          for K in 1 .. N loop
  626.             if Ranges (J).Low < Result (K).Low then
  627.                Result (K + 1 .. N + 1) := Result (K .. N);
  628.                Result (K) := Ranges (J);
  629.                goto Continue;
  630.             end if;
  631.          end loop;
  632.  
  633.          Result (N + 1) := Ranges (J);
  634.  
  635.          <<Continue>>
  636.             N := N + 1;
  637.       end loop;
  638.  
  639.       pragma Warnings (On);
  640.  
  641.       --  Now collapse any contiguous or overlapping ranges
  642.  
  643.       J := 1;
  644.       while J < N loop
  645.          if Result (J).High < Result (J).Low then
  646.             N := N - 1;
  647.             Result (J .. N) := Result (J + 1 .. N + 1);
  648.  
  649.          elsif Wide_Character'Succ (Result (J).High) >= Result (J + 1).Low then
  650.             Result (J).High :=
  651.               Wide_Character'Max (Result (J).High, Result (J + 1).High);
  652.  
  653.             N := N - 1;
  654.             Result (J + 1 .. N) := Result (J + 2 .. N + 1);
  655.  
  656.          else
  657.             J := J + 1;
  658.          end if;
  659.       end loop;
  660.  
  661.       if Result (N).High < Result (N).Low then
  662.          N := N - 1;
  663.       end if;
  664.  
  665.       return (AF.Controlled with
  666.               Set => new Wide_Character_Ranges'(Result (1 .. N)));
  667.    end To_Set;
  668.  
  669.    --  Case of single range input
  670.  
  671.    function To_Set
  672.      (Span : in Wide_Character_Range)
  673.       return Wide_Character_Set
  674.    is
  675.    begin
  676.       if Span.Low > Span.High then
  677.          return Null_Set;
  678.          --  This is safe, because there is no procedure with parameter
  679.          --  Wide_Character_Set of mode "out" or "in out".
  680.  
  681.       else
  682.          return (AF.Controlled with
  683.                  Set => new Wide_Character_Ranges'(1 => Span));
  684.       end if;
  685.    end To_Set;
  686.  
  687.    --  Case of wide string input
  688.  
  689.    function To_Set
  690.      (Sequence : in Wide_Character_Sequence)
  691.       return     Wide_Character_Set
  692.    is
  693.       R : Wide_Character_Ranges (1 .. Sequence'Length);
  694.  
  695.    begin
  696.       for J in R'Range loop
  697.          R (J) := (Sequence (J), Sequence (J));
  698.       end loop;
  699.  
  700.       return To_Set (R);
  701.    end To_Set;
  702.  
  703.    --  Case of single wide character input
  704.  
  705.    function To_Set
  706.      (Singleton : in Wide_Character)
  707.       return      Wide_Character_Set
  708.    is
  709.    begin
  710.       return
  711.         (AF.Controlled with
  712.          Set => new Wide_Character_Ranges' (1 => (Singleton, Singleton)));
  713.    end To_Set;
  714.  
  715.    -----------
  716.    -- Value --
  717.    -----------
  718.  
  719.    function Value
  720.      (Map     : in Wide_Character_Mapping;
  721.       Element : in Wide_Character)
  722.       return    Wide_Character
  723.    is
  724.       L, R, M : Natural;
  725.  
  726.       MV : constant Wide_Character_Mapping_Values_Access := Map.Map;
  727.  
  728.    begin
  729.       L := 1;
  730.       R := MV.Domain'Last;
  731.  
  732.       --  Binary search loop
  733.  
  734.       loop
  735.          --  If not found, identity
  736.  
  737.          if L > R then
  738.             return Element;
  739.  
  740.          --  Otherwise do binary divide
  741.  
  742.          else
  743.             M := (L + R) / 2;
  744.  
  745.             if Element < MV.Domain (M) then
  746.                R := M - 1;
  747.  
  748.             elsif Element > MV.Domain (M) then
  749.                L := M + 1;
  750.  
  751.             else --  Element = MV.Domain (M) then
  752.                return MV.Rangev (M);
  753.             end if;
  754.          end if;
  755.       end loop;
  756.    end Value;
  757.  
  758. end Ada.Strings.Wide_Maps;
  759.