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;
|