source: trunk/Packages/Common/URI.pas

Last change on this file was 75, checked in by chronos, 6 months ago
  • Modified: Removed U prefix from unit names.
  • Modified: Updated Common package.
File size: 8.7 KB
Line 
1unit URI;
2
3// Date: 2011-04-04
4
5interface
6
7uses
8 Classes, SysUtils;
9
10const
11 URIPathSeparator = '/';
12
13type
14
15 { TPath }
16
17 TPath = class
18 private
19 function GetAsString: string;
20 procedure SetAsString(AValue: string);
21 public
22 Items: TStringList;
23 IsAbsolute: Boolean;
24 DirSeparator: string;
25 procedure Assign(Source: TPath);
26 constructor Create;
27 destructor Destroy; override;
28 property AsString: string read GetAsString write SetAsString;
29 end;
30
31 { TFileName }
32
33 TFileNamePart = (fnpDrive, fnpDirectory, fnpName, fnpExtension);
34 TFileNameParts = set of TFileNamePart;
35
36 TFileName = class
37 private
38 public
39 Drive: string;
40 Directory: TPath;
41 Name: string;
42 Extension: string;
43 function Combine(Parts: TFileNameParts = [fnpDrive, fnpDirectory, fnpName, fnpExtension]): string;
44 procedure Parse(AValue: string);
45 procedure Assign(Source: TFileName);
46 constructor Create;
47 destructor Destroy; override;
48 end;
49
50 { TURI }
51
52 TURI = class(TPersistent)
53 private
54 function GetAsString: string;
55 procedure SetAsString(Value: string);
56 public
57 Scheme: string;
58 Authority: string;
59 Path: TFileName;
60 Query: string;
61 Fragment: string;
62 constructor Create;
63 procedure Clear;
64 destructor Destroy; override;
65 procedure Assign(Source: TPersistent); override;
66 property AsString: string read GetAsString write SetAsString;
67 end;
68
69 { TURL }
70
71 TURL = class(TURI)
72 private
73 function GetAsString: string;
74 procedure SetAsString(Value: string);
75 public
76 UserName: string;
77 Password: string;
78 Host: string;
79 Port: Word;
80 constructor Create;
81 destructor Destroy; override;
82 property AsString: string read GetAsString write SetAsString;
83 end;
84
85
86implementation
87
88function LeftCutString(var Source: string; out Output: string; Delimiter: string; Allowed: string = ''): Boolean;
89var
90 I: Integer;
91 Matched: Boolean;
92begin
93 I := 1;
94 Matched := True;
95 while (I < Length(Source)) and Matched do begin
96 Matched := True;
97 if (Source[I] = Delimiter) then Matched := False;
98 //for J := 1 to Length(Allowed) do
99 // if Source[I] = Allowed[J] then Matched := True;
100 if Matched then Inc(I);
101 end;
102 if (Delimiter = Copy(Source, I, Length(Delimiter))) or (I = Length(Source)) then begin
103 Output := Copy(Source, 1, I - 1);
104 Delete(Source, 1, Length(Output) + Length(Delimiter));
105 Result := True;
106 end else begin
107 Output := '';
108 Result := False;
109 end;
110end;
111
112function RightCutString(var Source: string; out Output: string; Delimiter: string; Allowed: string = ''): Boolean;
113var
114 I: Integer;
115 Matched: Boolean;
116begin
117 I := Length(Source);
118 Matched := True;
119 while (I > 0) and Matched do begin
120 Matched := True;
121 if (Source[I] = Delimiter) then Matched := False;
122 //for J := 1 to Length(Allowed) do
123 // if Source[I] = Allowed[J] then Matched := True;
124 if Matched then Dec(I);
125 end;
126 if (Delimiter = Copy(Source, I - Length(Delimiter) + 1, Length(Delimiter))) or (I = 0) then begin
127 Output := Copy(Source, I + 1, Length(Source) - I);
128 Delete(Source, I, Length(Output) + Length(Delimiter));
129 Result := True;
130 end else begin
131 Output := '';
132 Result := False;
133 end;
134end;
135
136{ TPath }
137
138function TPath.GetAsString: string;
139var
140 I: Integer;
141begin
142 if IsAbsolute then Result := DirSeparator
143 else Result := '';
144 for I := 0 to Items.Count - 1 do
145 Result := Result + Items[I] + DirSeparator;
146end;
147
148procedure TPath.SetAsString(AValue: string);
149var
150 Name: string;
151begin
152 Items.Clear;
153 if Length(AValue) > 0 then begin
154 if AValue[1] = DirSeparator then begin
155 IsAbsolute := True;
156 Delete(AValue, 1, 1);
157 end else IsAbsolute := False;
158 while Pos(DirSeparator, AValue) > 0 do begin
159 Name := Copy(AValue, 1, Pos(DirSeparator, AValue) - 1);
160 Delete(AValue, 1, Pos(DirSeparator, AValue));
161 Items.Add(Name);
162 end;
163 if Length(AValue) > 0 then
164 Items.Add(AValue);
165 end else IsAbsolute := False;
166end;
167
168procedure TPath.Assign(Source: TPath);
169begin
170 IsAbsolute := Source.IsAbsolute;
171 Items.Assign(Source.Items);
172 DirSeparator := Source.DirSeparator;
173end;
174
175constructor TPath.Create;
176begin
177 Items := TStringList.Create;
178 DirSeparator := DirectorySeparator;
179end;
180
181destructor TPath.Destroy;
182begin
183 Items.Free;
184 inherited;
185end;
186
187{ TURI }
188
189function TURI.GetAsString: string;
190begin
191 Result := '';
192 if Scheme <> '' then Result := Scheme + ':';
193 if Path.Combine <> '' then begin
194 Result := Result + '//' + Authority;
195 if Scheme = 'file' then Result := Result + URIPathSeparator;
196 Result := Result + Path.Combine;
197 end;
198 if Query <> '' then Result := Result + '?' + Query;
199 if Fragment <> '' then Result := Result + '#' + Fragment;
200end;
201
202procedure TURI.SetAsString(Value: string);
203begin
204 LeftCutString(Value, Scheme, ':');
205 if Copy(Value, 1, 2) = '//' then begin
206 Value := Copy(Value, 3, Length(Value));
207 LeftCutString(Value, Authority, URIPathSeparator);
208 end;
209 RightCutString(Value, Fragment, '#');
210 RightCutString(Value, Query, '?', '=&');
211 //if Scheme = 'file' then Delete(Value, 1, 1); // Remove beginning slash
212 Path.Parse(Value);
213end;
214
215constructor TURI.Create;
216begin
217 Path := TFileName.Create;
218 Path.Directory.DirSeparator := URIPathSeparator;
219end;
220
221procedure TURI.Clear;
222begin
223 Scheme := '';
224 Authority := '';
225 Path.Parse('');
226 Fragment := '';
227 Query := '';
228end;
229
230destructor TURI.Destroy;
231begin
232 Path.Free;
233 inherited;
234end;
235
236procedure TURI.Assign(Source: TPersistent);
237begin
238 if Source is TURI then begin
239 Scheme := TURI(Source).Scheme;
240 Authority := TURI(Source).Authority;
241 Path.Assign(TURI(Source).Path);
242 Fragment := TURI(Source).Fragment;
243 Query := TURI(Source).Query;
244 end else inherited;
245end;
246
247{ TURL }
248
249function TURL.GetAsString: string;
250begin
251 Result := '';
252 if Scheme <> '' then Result := Scheme + '://';
253 if UserName <> '' then begin
254 Result := Result + UserName;
255 if UserName <> '' then Result := Result + ':' + Password;
256 Result := Result + '@';
257 end;
258 if Host <> '' then Result := Result + Host;
259 if Port <> 0 then Result := Result + ':' + IntToStr(Port);
260 if Path.Combine <> '' then Result := Result + Path.Combine;
261 if Query <> '' then Result := Result + '?' + Query;
262 if Fragment <> '' then Result := Result + '#' + Fragment;
263end;
264
265procedure TURL.SetAsString(Value: string);
266var
267 HostAddr: string;
268 HostPort: string;
269 TempPath: string;
270begin
271 LeftCutString(Value, Scheme, '://');
272 if LeftCutString(Value, UserName, ':') then LeftCutString(Value, Password, '@')
273 else LeftCutString(Value, UserName, '@');
274 RightCutString(Value, Fragment, '#');
275 RightCutString(Value, Query, '?', '=&');
276 if LeftCutString(Value, HostAddr, ':', '.') then begin
277 LeftCutString(Value, HostPort, '');
278 Port := StrToInt(HostPort);
279 end else LeftCutString(Value, HostAddr, '', '.');
280 Host := HostAddr;
281 LeftCutString(Value, TempPath, '', URIPathSeparator + '.');
282 Path.Parse(TempPath);
283end;
284
285constructor TURL.Create;
286begin
287
288end;
289
290destructor TURL.Destroy;
291begin
292 inherited;
293end;
294
295{ TFileName }
296
297function TFileName.Combine(Parts: TFileNameParts): string;
298begin
299 Result := '';
300 if (fnpDrive in Parts) and (Drive <> '') then Result := Result + Drive;
301 if (fnpDirectory in Parts) and (Directory.AsString <> '') then
302 Result := Result + Directory.AsString;
303 if (fnpName in Parts) then Result := Result + Name;
304 if (fnpExtension in Parts) and (Extension <> '') then
305 Result := Result + Extension;
306end;
307
308procedure TFileName.Parse(AValue: string);
309begin
310 if Pos(ExtensionSeparator, AValue) > 0 then begin
311 RightCutString(AValue, Extension, ExtensionSeparator);
312 Extension := ExtensionSeparator + Extension;
313 end else Extension := '';
314 if Pos(Directory.DirSeparator, AValue) > 0 then
315 RightCutString(AValue, Name, Directory.DirSeparator)
316 else begin
317 Name := AValue;
318 AValue := '';
319 end;
320 if Pos(DriveSeparator, AValue) > 0 then begin
321 LeftCutString(AValue, Drive, DriveSeparator);
322 Drive := Drive + DriveSeparator;
323 end else Drive := '';
324 if (Drive <> '') and (AValue = '') then
325 Directory.AsString := Directory.DirSeparator
326 else Directory.AsString := AValue;
327end;
328
329procedure TFileName.Assign(Source: TFileName);
330begin
331 Name := Source.Name;
332 Extension := Source.Extension;
333 Drive := Source.Drive;
334 Directory.Assign(Source.Directory);
335end;
336
337constructor TFileName.Create;
338begin
339 Directory := TPath.Create;
340end;
341
342destructor TFileName.Destroy;
343begin
344 Directory.Free;
345 inherited;
346end;
347
348end.
Note: See TracBrowser for help on using the repository browser.