1
2
3
4
5
6 using System;
7 using System.Collections;
8
9 namespace System.Net.Http
10 {
11 public class UriException : Exception
12 {
13 public nothrow UriException(const string& message_) : base(message_)
14 {
15 }
16 }
17
18 public class Authority
19 {
20 public enum Flags : sbyte
21 {
22 none = 0, hasUserInfo = 1 << 0
23 }
24 public nothrow Authority() : flags(Flags.none), port(-1)
25 {
26 }
27 public inline nothrow Flags operator|(Flags left, Flags right) const
28 {
29 return cast<Flags>(cast<sbyte>(left) | cast<sbyte>(right));
30 }
31 public inline nothrow Flags operator&(Flags left, Flags right) const
32 {
33 return cast<Flags>(cast<sbyte>(left) & cast<sbyte>(right));
34 }
35 public inline nothrow Flags operator~(Flags f) const
36 {
37 return cast<Flags>(~cast<sbyte>(f));
38 }
39 public inline nothrow bool GetFlag(Flags flag) const
40 {
41 return (flags & flag) != Flags.none;
42 }
43 public inline nothrow void SetFlag(Flags flag)
44 {
45 flags = cast<Flags>(flags | flag);
46 }
47 public inline nothrow void ResetFlag(Flags flag)
48 {
49 flags = cast<Flags>(flags & ~flag);
50 }
51 public inline nothrow const string& UserInfo() const
52 {
53 return userInfo;
54 }
55 public nothrow void SetUserInfo(const string& userInfo_)
56 {
57 userInfo = userInfo_;
58 SetFlag(Flags.hasUserInfo);
59 }
60 public inline nothrow const string& Host() const
61 {
62 return host;
63 }
64 public nothrow void SetHost(const string& host_)
65 {
66 host = host_;
67 }
68 public inline nothrow int Port() const
69 {
70 return port;
71 }
72 public nothrow void SetPort(int port_)
73 {
74 port = port_;
75 }
76 public nothrow string ToString() const
77 {
78 string result;
79 if (GetFlag(Flags.hasUserInfo))
80 {
81 result.Append(userInfo).Append('@');
82 }
83 result.Append(host);
84 if (port != -1)
85 {
86 result.Append(':').Append(ToString(port));
87 }
88 return result;
89 }
90 private Flags flags;
91 private string userInfo;
92 private string host;
93 private int port;
94 }
95
96 public class UriReference
97 {
98 public enum Flags : sbyte
99 {
100 none = 0, asterisk = 1 << 0, hasAuthority = 1 << 1, hasQuery = 1 << 2, hasFragment = 1 << 3
101 }
102 public nothrow UriReference()
103 {
104 }
105 public UriReference(const string& uri)
106 {
107 UriLexer lexer(ToUtf32(uri), "", 0);
108 UriReference that = Uri.Parse(lexer);
109 Swap(flags, that.flags);
110 Swap(scheme, that.scheme);
111 Swap(authority, that.authority);
112 Swap(path, that.path);
113 Swap(query, that.query);
114 Swap(fragment, that.fragment);
115 }
116 public inline nothrow bool IsAbsolute() const
117 {
118 return !scheme.IsEmpty();
119 }
120 public inline nothrow bool IsRelative() const
121 {
122 return !IsAbsolute();
123 }
124 public static UriReference Combine(const UriReference& baseUri, const UriReference& relativeUri)
125 {
126 if (!baseUri.IsAbsolute())
127 {
128 throw UriException("base URI not absolute");
129 }
130 if (relativeUri.IsAbsolute())
131 {
132 return relativeUri;
133 }
134 string basePath = "/";
135 if (!baseUri.Path().IsEmpty())
136 {
137 if (baseUri.Path().StartsWith("/"))
138 {
139 basePath = baseUri.Path();
140 }
141 else
142 {
143 basePath = "/" + baseUri.Path();
144 }
145 }
146 UriReference combined;
147 combined.SetFlags(baseUri.GetFlags());
148 combined.SetScheme(baseUri.Scheme());
149 if (baseUri.GetFlag(Flags.hasAuthority))
150 {
151 combined.SetAuthority(baseUri.GetAuthority());
152 }
153 combined.SetPath(GetFullNetPath(CombineNetPath(basePath, relativeUri.Path())));
154 if (relativeUri.GetFlag(Flags.hasQuery))
155 {
156 combined.SetQuery(relativeUri.Query());
157 }
158 if (relativeUri.GetFlag(Flags.hasFragment))
159 {
160 combined.SetFragment(relativeUri.Fragment());
161 }
162 return combined;
163 }
164 public string ToString() const
165 {
166 if (GetFlag(Flags.asterisk))
167 {
168 return "*";
169 }
170 else
171 {
172 string result;
173 if (!scheme.IsEmpty())
174 {
175 result.Append(scheme).Append(':');
176 if (GetFlag(Flags.hasAuthority))
177 {
178 result.Append(authority.ToString());
179 }
180 }
181 result.Append(path);
182 if (GetFlag(Flags.hasQuery))
183 {
184 result.Append('?').Append(query);
185 }
186 if (GetFlag(Flags.hasFragment))
187 {
188 result.Append('#').Append(fragment);
189 }
190 return result;
191 }
192 }
193 public inline nothrow Flags GetFlags() const
194 {
195 return flags;
196 }
197 public inline nothrow void SetFlags(Flags flags_)
198 {
199 flags = flags_;
200 }
201 public inline nothrow bool GetFlag(Flags flag) const
202 {
203 return cast<Flags>(cast<sbyte>(flags) & cast<sbyte>(flag)) != Flags.none;
204 }
205 public inline nothrow void SetFlag(Flags flag)
206 {
207 flags = cast<Flags>(cast<sbyte>(flags) | cast<sbyte>(flag));
208 }
209 public inline nothrow void ResetFlag(Flags flag)
210 {
211 flags = cast<Flags>(cast<sbyte>(flags) & ~cast<sbyte>(flag));
212 }
213 public inline nothrow const string& Scheme() const
214 {
215 return scheme;
216 }
217 public nothrow void SetScheme(const string& scheme_)
218 {
219 scheme = scheme_;
220 }
221 public inline nothrow const Authority& GetAuthority() const
222 {
223 return authority;
224 }
225 public nothrow void SetAuthority(const Authority& authority_)
226 {
227 authority = authority_;
228 SetFlag(Flags.hasAuthority);
229 }
230 public inline nothrow const string& Path() const
231 {
232 return path;
233 }
234 public nothrow void SetPath(const string& path_)
235 {
236 path = path_;
237 }
238 public inline nothrow const string& Query() const
239 {
240 return query;
241 }
242 public nothrow void SetQuery(const string& query_)
243 {
244 query = query_;
245 SetFlag(Flags.hasQuery);
246 }
247 public inline nothrow const string& Fragment() const
248 {
249 return fragment;
250 }
251 public nothrow void SetFragment(const string& fragment_)
252 {
253 fragment = fragment_;
254 SetFlag(Flags.hasFragment);
255 }
256 private Flags flags;
257 private string scheme;
258 private Authority authority;
259 private string path;
260 private string query;
261 private string fragment;
262 }
263
264 public nothrow string CombineNetPath(const string& left, const string& right)
265 {
266 string combined;
267 if (left.IsEmpty())
268 {
269 combined = right;
270 }
271 else if (right.IsEmpty())
272 {
273 combined = left;
274 }
275 else
276 {
277 if (right.StartsWith("/"))
278 {
279 combined = right;
280 }
281 else
282 {
283 combined.Append(left);
284 if (!left.EndsWith("/"))
285 {
286 combined.Append('/');
287 }
288 combined.Append(right);
289 }
290 }
291 return combined;
292 }
293
294 public string GetFullNetPath(const string& path)
295 {
296 List<string> components = path.Split('/');
297 long w = 0;
298 long n = components.Count();
299 for (long i = 0; i < n; ++i;)
300 {
301 string c = components[i];
302 if (i == 0 || !c.IsEmpty() && c != ".")
303 {
304 if (c == "..")
305 {
306 --w;
307 if (w < 0)
308 {
309 throw UriException("invalid path '" + path + "'");
310 }
311 }
312 else
313 {
314 if (w != i)
315 {
316 components[w] = components[i];
317 }
318 ++w;
319 }
320 }
321 }
322 if (w == 0)
323 {
324 return "/";
325 }
326 else
327 {
328 string result;
329 for (long i = 0; i < w; ++i;)
330 {
331 if (i != 0)
332 {
333 result.Append('/');
334 }
335 result.Append(components[i]);
336 }
337 if (result.IsEmpty())
338 {
339 return "/";
340 }
341 else
342 {
343 return result;
344 }
345 }
346 }
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597 }