rejuvenation_23.0.0_507c1f00/src/rejuvenation-nested.adb

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
with Ada.Assertions;        use Ada.Assertions;
with Ada.Strings.Fixed;     use Ada.Strings.Fixed;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

package body Rejuvenation.Nested is

   function Remove_Nested_Flags
     (Source : String; On_Flag : String; Off_Flag : String;
      Depth  : Natural := 0) return String
   is

      function Next_Flag_Location
        (From : Positive; Flag : String) return Positive;
      function Next_Flag_Location
        (From : Positive; Flag : String) return Positive
      is
         I : constant Natural := Index (Source, Flag, From);
      begin
         return (if I = 0 then Source'Last + 1 else I);
      end Next_Flag_Location;

      function Next_On_Flag_Location (From : Positive) return Positive is
        (Next_Flag_Location (From, On_Flag));

      function Next_Off_Flag_Location (From : Positive) return Positive is
        (Next_Flag_Location (From, Off_Flag));

      Current_Location : Natural          := Source'First;
      Current_Depth    : Natural          := Depth;
      On_Location      : Positive := Next_On_Flag_Location (Current_Location);
      Off_Location     : Positive := Next_Off_Flag_Location (Current_Location);
      Final            : Unbounded_String := Null_Unbounded_String;
   begin
      loop
         if On_Location > Source'Last and then Off_Location > Source'Last then
            Assert
              (Check   => Current_Depth = 0,
               Message =>
                 "Unexpectedly at Current_Depth " & Current_Depth'Image);

            Append (Final, Source (Current_Location .. Source'Last));
            return To_String (Final);
         elsif On_Location < Off_Location then
            declare
               Next_Location : constant Positive :=
                 On_Location + On_Flag'Length;
               Last : constant Positive :=
                 (if Current_Depth = 0 then Next_Location - 1
                  else On_Location - 1);
            begin
               Current_Depth := Current_Depth + 1;
               Append (Final, Source (Current_Location .. Last));
               Current_Location := Next_Location;
               Assert
                 (Check   => Current_Location <= Off_Location,
                  Message => "Invariant violated");
               On_Location := Next_On_Flag_Location (Current_Location);
            end;
         else
            Assert
              (Check   => Off_Location < On_Location,
               Message => "On and Off token can't occur at same location");
            declare
               Next_Location : constant Positive :=
                 Off_Location + Off_Flag'Length;
               Last : constant Positive :=
                 (if Current_Depth = 1 then Next_Location - 1
                  else Off_Location - 1);
            begin
               Assert
                 (Check   => Current_Depth > 0,
                  Message =>
                    "Current_Depth is zero at offset " & Off_Location'Image);
               Current_Depth := Current_Depth - 1;
               Append (Final, Source (Current_Location .. Last));
               Current_Location := Next_Location;
               Assert
                 (Check   => Current_Location <= On_Location,
                  Message => "Invariant violated");
               Off_Location := Next_Off_Flag_Location (Current_Location);
            end;
         end if;
      end loop;
   end Remove_Nested_Flags;
end Rejuvenation.Nested;