uri_ada_2.0.0_02a0780d/src/uri_ada.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
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
with Ada.Containers.Indefinite_Ordered_Maps;
with Ada.Strings.Fixed;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

with GNAT.Regpat;

package body URI_Ada is

   package Part_Maps is
     new Ada.Containers.Indefinite_Ordered_Maps (Parts, String);

   subtype Part_Map is Part_Maps.Map;

   -----------
   -- Crack --
   -----------

   --  ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
   --   12            3  4          5       6  7        8 9
   --
   --  scheme    = $2
   --  authority = $4
   --  path      = $5
   --  query     = $7
   --  fragment  = $9

   function Crack (This : String) return Part_Map is
      use GNAT.Regpat;

      Cracker : constant Pattern_Matcher :=
                  Compile
                    ("^\s*(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#([^\s]*))?",
                     Case_Insensitive + Single_Line);

      Matches : Match_Array (0 .. 9) := (others => No_Match);

      function Part (I : Positive) return String
      is (if Matches (I) /= No_Match
          then This (Matches (I).First .. Matches (I).Last)
          else "");

   begin
      Match (Cracker, This, Matches);

      return Map : Part_Map do
         Map.Insert (Scheme,    Part (2));
         Map.Insert (Authority, Part (4));
         Map.Insert (Path,      Part (5));
         Map.Insert (Query,     Part (7));
         Map.Insert (Fragment,  Part (9));
      end return;
   end Crack;

   -------------
   -- Extract --
   -------------

   function Extract (This : String; Part : Parts) return String
   is (Extract (This, First => Part, Last => Part));

   -------------
   -- Extract --
   -------------

   function Extract (This : String; First, Last : Parts) return String
   is
      Slice : Unbounded_String;
      Parts : constant Part_Map := Crack (This);
   begin
      for I in First .. Last loop
         if Parts.Contains (I) then

            -- prefixes

            if I /= First and then Parts (I) /= "" and then Slice /= "" then
               case I is
               when Scheme    => null;
               when Authority => Append (Slice, "//");
               when Path      => null;
               when Query     => Append (Slice, "?");
               when Fragment  => Append (Slice, "#");
               end case;
            end if;

            Append (Slice, Parts (I));

            -- postfixes

            if I = Scheme and then Parts (I) /= "" and then Extract (This, Authority, Last) /= "" then
               Append (Slice, ":");
            end if;

         end if;
      end loop;

      return To_String (Slice);
   end Extract;

   ----------------------
   -- User_Or_Password --
   ----------------------

   function User_Or_Password (This : Authority_String; Return_User : Boolean)
                              return String
   is
   begin

      --  Early there is none

      if not (for Some Char of This => Char = '@') then
         return "";
      end if;

      declare
         use Ada.Strings;
         Both : constant String :=
                  This (This'First .. Fixed.Index (This, "@") - 1);
         Colon : constant Integer := Fixed.Index (Both, ":");

         User  : constant String := (if Colon not in Both'Range
                                     then Both
                                     else Both (Both'First .. Colon - 1));
         Pass  : constant String := (if Colon in Both'Range
                                     then Both (Colon + 1 .. Both'Last)
                                     else "");
      begin
         if Return_User then
            return User;
         else
            return Pass;
         end if;
      end;
   end User_Or_Password;

   ----------
   -- User --
   ----------

   function User (This : Authority_String) return String
   is (User_Or_Password (This, True));

   --------------
   -- Password --
   --------------

   function Password (This : Authority_String) return String
   is (User_Or_Password (This, False));

end URI_Ada;