source: trunk/Packages/Common/UURI.pas

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