Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
UriHelper.cs
Go to the documentation of this file.
2using System.Text;
3
4namespace System;
5
6internal static class UriHelper
7{
9
10 internal static readonly char[] s_WSchars = new char[4] { ' ', '\n', '\r', '\t' };
11
12 internal static ReadOnlySpan<bool> UnreservedReservedTable => new bool[128]
13 {
14 false, false, false, false, false, false, false, false, false, false,
15 false, false, false, false, false, false, false, false, false, false,
16 false, false, false, false, false, false, false, false, false, false,
17 false, false, false, true, false, true, true, false, true, true,
18 true, true, true, true, true, true, true, true, true, true,
19 true, true, true, true, true, true, true, true, true, true,
20 false, true, false, true, true, true, true, true, true, true,
21 true, true, true, true, true, true, true, true, true, true,
22 true, true, true, true, true, true, true, true, true, true,
23 true, true, false, true, false, true, false, true, true, true,
24 true, true, true, true, true, true, true, true, true, true,
25 true, true, true, true, true, true, true, true, true, true,
26 true, true, true, false, false, false, true, false
27 };
28
29 internal static ReadOnlySpan<bool> UnreservedTable => new bool[128]
30 {
31 false, false, false, false, false, false, false, false, false, false,
32 false, false, false, false, false, false, false, false, false, false,
33 false, false, false, false, false, false, false, false, false, false,
34 false, false, false, false, false, false, false, false, false, false,
35 false, false, false, false, false, true, true, false, true, true,
36 true, true, true, true, true, true, true, true, false, false,
37 false, false, false, false, false, true, true, true, true, true,
38 true, true, true, true, true, true, true, true, true, true,
39 true, true, true, true, true, true, true, true, true, true,
40 true, false, false, false, false, true, false, true, true, true,
41 true, true, true, true, true, true, true, true, true, true,
42 true, true, true, true, true, true, true, true, true, true,
43 true, true, true, false, false, false, true, false
44 };
45
46 internal unsafe static bool TestForSubPath(char* selfPtr, int selfLength, char* otherPtr, int otherLength, bool ignoreCase)
47 {
48 int i = 0;
49 bool flag = true;
50 for (; i < selfLength && i < otherLength; i++)
51 {
52 char c = selfPtr[i];
53 char c2 = otherPtr[i];
54 switch (c)
55 {
56 case '#':
57 case '?':
58 return true;
59 case '/':
60 if (c2 != '/')
61 {
62 return false;
63 }
64 if (!flag)
65 {
66 return false;
67 }
68 flag = true;
69 continue;
70 default:
71 if (c2 == '?' || c2 == '#')
72 {
73 break;
74 }
75 if (!ignoreCase)
76 {
77 if (c != c2)
78 {
79 flag = false;
80 }
81 }
82 else if (char.ToLowerInvariant(c) != char.ToLowerInvariant(c2))
83 {
84 flag = false;
85 }
86 continue;
87 }
88 break;
89 }
90 for (; i < selfLength; i++)
91 {
92 char c;
93 if ((c = selfPtr[i]) != '?')
94 {
95 switch (c)
96 {
97 case '#':
98 break;
99 case '/':
100 return false;
101 default:
102 continue;
103 }
104 }
105 return true;
106 }
107 return true;
108 }
109
110 internal static string EscapeString(string stringToEscape, bool checkExistingEscaped, ReadOnlySpan<bool> unreserved, char forceEscape1 = '\0', char forceEscape2 = '\0')
111 {
112 if (stringToEscape == null)
113 {
114 throw new ArgumentNullException("stringToEscape");
115 }
116 if (stringToEscape.Length == 0)
117 {
118 return string.Empty;
119 }
120 ReadOnlySpan<bool> readOnlySpan = default(Span<bool>);
121 if ((forceEscape1 | forceEscape2) == 0)
122 {
123 readOnlySpan = unreserved;
124 }
125 else
126 {
127 Span<bool> span = stackalloc bool[128];
128 unreserved.CopyTo(span);
129 span[forceEscape1] = false;
130 span[forceEscape2] = false;
131 readOnlySpan = span;
132 }
133 int i;
134 for (i = 0; i < stringToEscape.Length; i++)
135 {
136 char index;
137 if ((index = stringToEscape[i]) > '\u007f')
138 {
139 break;
140 }
141 if (!readOnlySpan[index])
142 {
143 break;
144 }
145 }
146 if (i == stringToEscape.Length)
147 {
148 return stringToEscape;
149 }
150 Span<char> initialBuffer = stackalloc char[512];
152 vsb.Append(stringToEscape.AsSpan(0, i));
153 EscapeStringToBuilder(stringToEscape.AsSpan(i), ref vsb, readOnlySpan, checkExistingEscaped);
154 return vsb.ToString();
155 }
156
157 internal static void EscapeString(ReadOnlySpan<char> stringToEscape, ref System.Text.ValueStringBuilder dest, bool checkExistingEscaped, char forceEscape1 = '\0', char forceEscape2 = '\0')
158 {
159 ReadOnlySpan<bool> readOnlySpan = default(Span<bool>);
160 if ((forceEscape1 | forceEscape2) == 0)
161 {
162 readOnlySpan = UnreservedReservedTable;
163 }
164 else
165 {
166 Span<bool> span = stackalloc bool[128];
167 UnreservedReservedTable.CopyTo(span);
168 span[forceEscape1] = false;
169 span[forceEscape2] = false;
170 readOnlySpan = span;
171 }
172 int i;
173 for (i = 0; i < stringToEscape.Length; i++)
174 {
175 char index;
176 if ((index = stringToEscape[i]) > '\u007f')
177 {
178 break;
179 }
180 if (!readOnlySpan[index])
181 {
182 break;
183 }
184 }
185 if (i == stringToEscape.Length)
186 {
187 dest.Append(stringToEscape);
188 return;
189 }
190 dest.Append(stringToEscape.Slice(0, i));
191 ReadOnlySpan<bool> noEscape = MemoryMarshal.CreateReadOnlySpan(ref MemoryMarshal.GetReference(readOnlySpan), readOnlySpan.Length);
192 EscapeStringToBuilder(stringToEscape.Slice(i), ref dest, noEscape, checkExistingEscaped);
193 }
194
195 private static void EscapeStringToBuilder(ReadOnlySpan<char> stringToEscape, ref System.Text.ValueStringBuilder vsb, ReadOnlySpan<bool> noEscape, bool checkExistingEscaped)
196 {
197 Span<byte> destination = stackalloc byte[4];
198 SpanRuneEnumerator spanRuneEnumerator = stringToEscape.EnumerateRunes();
199 while (spanRuneEnumerator.MoveNext())
200 {
201 Rune current = spanRuneEnumerator.Current;
202 if (!current.IsAscii)
203 {
204 current.TryEncodeToUtf8(destination, out var bytesWritten);
205 Span<byte> span = destination.Slice(0, bytesWritten);
206 for (int i = 0; i < span.Length; i++)
207 {
208 byte value = span[i];
209 vsb.Append('%');
210 System.HexConverter.ToCharsBuffer(value, vsb.AppendSpan(2));
211 }
212 continue;
213 }
214 byte b = (byte)current.Value;
215 if (noEscape[b])
216 {
217 vsb.Append((char)b);
218 continue;
219 }
220 if (checkExistingEscaped && b == 37)
221 {
222 SpanRuneEnumerator spanRuneEnumerator2 = spanRuneEnumerator;
223 if (spanRuneEnumerator2.MoveNext())
224 {
225 Rune current2 = spanRuneEnumerator2.Current;
226 if (current2.IsAscii && IsHexDigit((char)current2.Value) && spanRuneEnumerator2.MoveNext())
227 {
228 Rune current3 = spanRuneEnumerator2.Current;
229 if (current3.IsAscii && IsHexDigit((char)current3.Value))
230 {
231 vsb.Append('%');
232 vsb.Append((char)current2.Value);
233 vsb.Append((char)current3.Value);
234 spanRuneEnumerator = spanRuneEnumerator2;
235 continue;
236 }
237 }
238 }
239 }
240 vsb.Append('%');
241 System.HexConverter.ToCharsBuffer(b, vsb.AppendSpan(2));
242 }
243 }
244
245 internal unsafe static char[] UnescapeString(string input, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery)
246 {
247 fixed (char* pStr = input)
248 {
249 return UnescapeString(pStr, start, end, dest, ref destPosition, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery);
250 }
251 }
252
253 internal unsafe static char[] UnescapeString(char* pStr, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery)
254 {
256 dest2.Append(dest.AsSpan(0, destPosition));
257 UnescapeString(pStr, start, end, ref dest2, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery);
258 if (dest2.Length > dest.Length)
259 {
260 dest = dest2.AsSpan().ToArray();
261 }
262 else
263 {
264 dest2.AsSpan(destPosition).TryCopyTo(dest.AsSpan(destPosition));
265 }
266 destPosition = dest2.Length;
267 dest2.Dispose();
268 return dest;
269 }
270
271 internal unsafe static void UnescapeString(string input, int start, int end, ref System.Text.ValueStringBuilder dest, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery)
272 {
273 fixed (char* pStr = input)
274 {
275 UnescapeString(pStr, start, end, ref dest, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery);
276 }
277 }
278
279 internal unsafe static void UnescapeString(ReadOnlySpan<char> input, ref System.Text.ValueStringBuilder dest, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery)
280 {
281 fixed (char* pStr = &MemoryMarshal.GetReference(input))
282 {
283 UnescapeString(pStr, 0, input.Length, ref dest, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery);
284 }
285 }
286
287 internal unsafe static void UnescapeString(char* pStr, int start, int end, ref System.Text.ValueStringBuilder dest, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery)
288 {
289 if ((unescapeMode & UnescapeMode.EscapeUnescape) == 0)
290 {
291 dest.Append(pStr + start, end - start);
292 return;
293 }
294 bool flag = false;
295 bool flag2 = Uri.IriParsingStatic(syntax) && (unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.EscapeUnescape;
296 int i = start;
297 while (i < end)
298 {
299 char c = '\0';
300 for (; i < end; i++)
301 {
302 if ((c = pStr[i]) == '%')
303 {
304 if ((unescapeMode & UnescapeMode.Unescape) == 0)
305 {
306 flag = true;
307 break;
308 }
309 if (i + 2 < end)
310 {
311 c = DecodeHexChars(pStr[i + 1], pStr[i + 2]);
312 if (unescapeMode < UnescapeMode.UnescapeAll)
313 {
314 switch (c)
315 {
316 case '\uffff':
317 if ((unescapeMode & UnescapeMode.Escape) == 0)
318 {
319 continue;
320 }
321 flag = true;
322 break;
323 case '%':
324 i += 2;
325 continue;
326 default:
327 if (c == rsvd1 || c == rsvd2 || c == rsvd3)
328 {
329 i += 2;
330 continue;
331 }
332 if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 && IsNotSafeForUnescape(c))
333 {
334 i += 2;
335 continue;
336 }
337 if (flag2 && ((c <= '\u009f' && IsNotSafeForUnescape(c)) || (c > '\u009f' && !IriHelper.CheckIriUnicodeRange(c, isQuery))))
338 {
339 i += 2;
340 continue;
341 }
342 break;
343 }
344 break;
345 }
346 if (c != '\uffff')
347 {
348 break;
349 }
350 if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow)
351 {
353 }
354 }
355 else
356 {
357 if (unescapeMode < UnescapeMode.UnescapeAll)
358 {
359 flag = true;
360 break;
361 }
362 if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow)
363 {
365 }
366 }
367 }
368 else if ((unescapeMode & (UnescapeMode.Unescape | UnescapeMode.UnescapeAll)) != (UnescapeMode.Unescape | UnescapeMode.UnescapeAll) && (unescapeMode & UnescapeMode.Escape) != 0)
369 {
370 if (c == rsvd1 || c == rsvd2 || c == rsvd3)
371 {
372 flag = true;
373 break;
374 }
375 if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 && (c <= '\u001f' || (c >= '\u007f' && c <= '\u009f')))
376 {
377 flag = true;
378 break;
379 }
380 }
381 }
382 while (start < i)
383 {
384 dest.Append(pStr[start++]);
385 }
386 if (i != end)
387 {
388 if (flag)
389 {
390 EscapeAsciiChar((byte)pStr[i], ref dest);
391 flag = false;
392 i++;
393 }
394 else if (c <= '\u007f')
395 {
396 dest.Append(c);
397 i += 3;
398 }
399 else
400 {
401 int num = PercentEncodingHelper.UnescapePercentEncodedUTF8Sequence(pStr + i, end - i, ref dest, isQuery, flag2);
402 i += num;
403 }
404 start = i;
405 }
406 }
407 }
408
409 internal static void EscapeAsciiChar(byte b, ref System.Text.ValueStringBuilder to)
410 {
411 to.Append('%');
412 System.HexConverter.ToCharsBuffer(b, to.AppendSpan(2));
413 }
414
415 internal static char DecodeHexChars(int first, int second)
416 {
417 int num = System.HexConverter.FromChar(first);
418 int num2 = System.HexConverter.FromChar(second);
419 if ((num | num2) == 255)
420 {
421 return '\uffff';
422 }
423 return (char)((num << 4) | num2);
424 }
425
426 internal static bool IsNotSafeForUnescape(char ch)
427 {
428 if (ch <= '\u001f' || (ch >= '\u007f' && ch <= '\u009f'))
429 {
430 return true;
431 }
432 return ";/?:@&=+$,#[]!'()*%\\#".Contains(ch);
433 }
434
435 internal static bool IsGenDelim(char ch)
436 {
437 if (ch != ':' && ch != '/' && ch != '?' && ch != '#' && ch != '[' && ch != ']')
438 {
439 return ch == '@';
440 }
441 return true;
442 }
443
444 internal static bool IsLWS(char ch)
445 {
446 if (ch <= ' ')
447 {
448 if (ch != ' ' && ch != '\n' && ch != '\r')
449 {
450 return ch == '\t';
451 }
452 return true;
453 }
454 return false;
455 }
456
457 internal static bool IsAsciiLetter(char character)
458 {
459 return ((uint)(character - 65) & -33) < 26;
460 }
461
462 internal static bool IsAsciiLetterOrDigit(char character)
463 {
464 if (((uint)(character - 65) & -33) >= 26)
465 {
466 return (uint)(character - 48) < 10u;
467 }
468 return true;
469 }
470
471 internal static bool IsHexDigit(char character)
472 {
473 return System.HexConverter.IsHexChar(character);
474 }
475
476 internal static bool IsBidiControlCharacter(char ch)
477 {
478 if (ch != '\u200e' && ch != '\u200f' && ch != '\u202a' && ch != '\u202b' && ch != '\u202c' && ch != '\u202d')
479 {
480 return ch == '\u202e';
481 }
482 return true;
483 }
484
485 internal unsafe static string StripBidiControlCharacters(ReadOnlySpan<char> strToClean, string backingString = null)
486 {
487 int num = 0;
488 ReadOnlySpan<char> readOnlySpan = strToClean;
489 for (int i = 0; i < readOnlySpan.Length; i++)
490 {
491 char c = readOnlySpan[i];
492 if ((uint)(c - 8206) <= 32u && IsBidiControlCharacter(c))
493 {
494 num++;
495 }
496 }
497 if (num == 0)
498 {
499 return backingString ?? new string(strToClean);
500 }
501 if (num == strToClean.Length)
502 {
503 return string.Empty;
504 }
505 fixed (char* ptr = &MemoryMarshal.GetReference(strToClean))
506 {
507 return string.Create(strToClean.Length - num, ((IntPtr)ptr, strToClean.Length), delegate(Span<char> buffer, (IntPtr StrToClean, int Length) state)
508 {
509 ReadOnlySpan<char> readOnlySpan2 = new ReadOnlySpan<char>((void*)state.StrToClean, state.Length);
510 int num2 = 0;
511 ReadOnlySpan<char> readOnlySpan3 = readOnlySpan2;
512 for (int j = 0; j < readOnlySpan3.Length; j++)
513 {
514 char c2 = readOnlySpan3[j];
515 if ((uint)(c2 - 8206) > 32u || !IsBidiControlCharacter(c2))
516 {
517 buffer[num2++] = c2;
518 }
519 }
520 });
521 }
522 }
523}
static void ToCharsBuffer(byte value, Span< char > buffer, int startingIndex=0, Casing casing=Casing.Upper)
static bool IsHexChar(int c)
static int FromChar(int c)
static bool CheckIriUnicodeRange(char unicode, bool isQuery)
Definition IriHelper.cs:8
static unsafe int UnescapePercentEncodedUTF8Sequence(char *input, int length, ref System.Text.ValueStringBuilder dest, bool isQuery, bool iriParsing)
static string net_uri_BadString
Definition SR.cs:30
Definition SR.cs:7
static Encoding UTF8
Definition Encoding.cs:526
static Encoding GetEncoding(int codepage)
Definition Encoding.cs:593
static unsafe char[] UnescapeString(char *pStr, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery)
Definition UriHelper.cs:253
static bool IsLWS(char ch)
Definition UriHelper.cs:444
static ReadOnlySpan< bool > UnreservedReservedTable
Definition UriHelper.cs:12
static bool IsNotSafeForUnescape(char ch)
Definition UriHelper.cs:426
static ReadOnlySpan< bool > UnreservedTable
Definition UriHelper.cs:29
static unsafe char[] UnescapeString(string input, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery)
Definition UriHelper.cs:245
static readonly Encoding s_noFallbackCharUTF8
Definition UriHelper.cs:8
static void EscapeAsciiChar(byte b, ref System.Text.ValueStringBuilder to)
Definition UriHelper.cs:409
static unsafe void UnescapeString(ReadOnlySpan< char > input, ref System.Text.ValueStringBuilder dest, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery)
Definition UriHelper.cs:279
static unsafe void UnescapeString(char *pStr, int start, int end, ref System.Text.ValueStringBuilder dest, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery)
Definition UriHelper.cs:287
static bool IsAsciiLetterOrDigit(char character)
Definition UriHelper.cs:462
static bool IsGenDelim(char ch)
Definition UriHelper.cs:435
static void EscapeString(ReadOnlySpan< char > stringToEscape, ref System.Text.ValueStringBuilder dest, bool checkExistingEscaped, char forceEscape1='\0', char forceEscape2='\0')
Definition UriHelper.cs:157
static bool IsBidiControlCharacter(char ch)
Definition UriHelper.cs:476
static void EscapeStringToBuilder(ReadOnlySpan< char > stringToEscape, ref System.Text.ValueStringBuilder vsb, ReadOnlySpan< bool > noEscape, bool checkExistingEscaped)
Definition UriHelper.cs:195
static string EscapeString(string stringToEscape, bool checkExistingEscaped, ReadOnlySpan< bool > unreserved, char forceEscape1='\0', char forceEscape2='\0')
Definition UriHelper.cs:110
static unsafe bool TestForSubPath(char *selfPtr, int selfLength, char *otherPtr, int otherLength, bool ignoreCase)
Definition UriHelper.cs:46
static bool IsAsciiLetter(char character)
Definition UriHelper.cs:457
static readonly char[] s_WSchars
Definition UriHelper.cs:10
static bool IsHexDigit(char character)
Definition UriHelper.cs:471
static char DecodeHexChars(int first, int second)
Definition UriHelper.cs:415
static unsafe void UnescapeString(string input, int start, int end, ref System.Text.ValueStringBuilder dest, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery)
Definition UriHelper.cs:271
static unsafe string StripBidiControlCharacters(ReadOnlySpan< char > strToClean, string backingString=null)
Definition UriHelper.cs:485
static bool IriParsingStatic(UriParser syntax)
Definition Uri.cs:601
bool TryCopyTo(Span< T > destination)
void CopyTo(Span< T > destination)
ReadOnlySpan< T > Slice(int start)
Span< T > Slice(int start)
Definition Span.cs:271
int Length
Definition Span.cs:70
bool IsAscii
Definition Rune.cs:47
bool TryEncodeToUtf8(Span< byte > destination, out int bytesWritten)
Definition Rune.cs:580
ReadOnlySpan< char > AsSpan(bool terminate)