Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
IPv6AddressHelper.cs
Go to the documentation of this file.
1namespace System;
2
3internal static class IPv6AddressHelper
4{
5 internal static string ParseCanonicalName(string str, int start, ref bool isLoopback, ref string scopeId)
6 {
7 Span<ushort> span = stackalloc ushort[8];
8 span.Clear();
9 Parse(str, span, start, ref scopeId);
10 isLoopback = IsLoopback(span);
11 (int longestSequenceStart, int longestSequenceLength) tuple = FindCompressionRange(span);
12 int item = tuple.longestSequenceStart;
13 int item2 = tuple.longestSequenceLength;
14 bool flag = ShouldHaveIpv4Embedded(span);
15 Span<char> span2 = stackalloc char[48];
16 span2[0] = '[';
17 int num = 1;
18 for (int i = 0; i < 8; i++)
19 {
20 int charsWritten;
21 if (flag && i == 6)
22 {
23 span2[num++] = ':';
24 bool flag2 = (span[i] >> 8).TryFormat(span2.Slice(num), out charsWritten);
25 num += charsWritten;
26 span2[num++] = '.';
27 flag2 = (span[i] & 0xFF).TryFormat(span2.Slice(num), out charsWritten);
28 num += charsWritten;
29 span2[num++] = '.';
30 flag2 = (span[i + 1] >> 8).TryFormat(span2.Slice(num), out charsWritten);
31 num += charsWritten;
32 span2[num++] = '.';
33 flag2 = (span[i + 1] & 0xFF).TryFormat(span2.Slice(num), out charsWritten);
34 num += charsWritten;
35 break;
36 }
37 if (item == i)
38 {
39 span2[num++] = ':';
40 }
41 if (item <= i && item2 == 8)
42 {
43 span2[num++] = ':';
44 break;
45 }
46 if (item > i || i >= item2)
47 {
48 if (i != 0)
49 {
50 span2[num++] = ':';
51 }
52 bool flag2 = span[i].TryFormat(span2.Slice(num), out charsWritten, "x");
53 num += charsWritten;
54 }
55 }
56 span2[num++] = ']';
57 return new string(span2.Slice(0, num));
58 }
59
60 private static bool IsLoopback(ReadOnlySpan<ushort> numbers)
61 {
62 if (numbers[0] == 0 && numbers[1] == 0 && numbers[2] == 0 && numbers[3] == 0 && numbers[4] == 0)
63 {
64 if (numbers[5] != 0 || numbers[6] != 0 || numbers[7] != 1)
65 {
66 if (numbers[6] == 32512 && numbers[7] == 1)
67 {
68 if (numbers[5] != 0)
69 {
70 return numbers[5] == ushort.MaxValue;
71 }
72 return true;
73 }
74 return false;
75 }
76 return true;
77 }
78 return false;
79 }
80
81 private unsafe static bool InternalIsValid(char* name, int start, ref int end, bool validateStrictAddress)
82 {
83 int num = 0;
84 int num2 = 0;
85 bool flag = false;
86 bool flag2 = false;
87 bool flag3 = false;
88 bool flag4 = true;
89 int start2 = 1;
90 if (name[start] == ':' && (start + 1 >= end || name[start + 1] != ':'))
91 {
92 return false;
93 }
94 int i;
95 for (i = start; i < end; i++)
96 {
97 bool num3;
98 if (!flag3)
99 {
100 num3 = Uri.IsHexDigit(name[i]);
101 }
102 else
103 {
104 if (name[i] < '0')
105 {
106 goto IL_0079;
107 }
108 num3 = name[i] <= '9';
109 }
110 if (num3)
111 {
112 num2++;
113 flag4 = false;
114 continue;
115 }
116 goto IL_0079;
117 IL_0079:
118 if (num2 > 4)
119 {
120 return false;
121 }
122 if (num2 != 0)
123 {
124 num++;
125 start2 = i - num2;
126 }
127 char c = name[i];
128 if ((uint)c <= 46u)
129 {
130 if (c == '%')
131 {
132 while (true)
133 {
134 if (++i == end)
135 {
136 return false;
137 }
138 if (name[i] == ']')
139 {
140 break;
141 }
142 if (name[i] != '/')
143 {
144 continue;
145 }
146 goto IL_011c;
147 }
148 goto IL_00ee;
149 }
150 if (c != '.')
151 {
152 goto IL_015c;
153 }
154 if (flag2)
155 {
156 return false;
157 }
158 i = end;
159 if (!IPv4AddressHelper.IsValid(name, start2, ref i, allowIPv6: true, notImplicitFile: false, unknownScheme: false))
160 {
161 return false;
162 }
163 num++;
164 flag2 = true;
165 i--;
166 }
167 else
168 {
169 if (c == '/')
170 {
171 goto IL_011c;
172 }
173 if (c != ':')
174 {
175 if (c == ']')
176 {
177 goto IL_00ee;
178 }
179 goto IL_015c;
180 }
181 if (i > 0 && name[i - 1] == ':')
182 {
183 if (flag)
184 {
185 return false;
186 }
187 flag = true;
188 flag4 = false;
189 }
190 else
191 {
192 flag4 = true;
193 }
194 }
195 goto IL_015e;
196 IL_015c:
197 return false;
198 IL_011c:
199 if (validateStrictAddress)
200 {
201 return false;
202 }
203 if (num == 0 || flag3)
204 {
205 return false;
206 }
207 flag3 = true;
208 flag4 = true;
209 goto IL_015e;
210 IL_015e:
211 num2 = 0;
212 continue;
213 IL_00ee:
214 start = i;
215 i = end;
216 }
217 if (flag3 && (num2 < 1 || num2 > 2))
218 {
219 return false;
220 }
221 int num4 = 8 + (flag3 ? 1 : 0);
222 if (!flag4 && num2 <= 4 && (flag ? (num < num4) : (num == num4)))
223 {
224 if (i == end + 1)
225 {
226 end = start + 1;
227 return true;
228 }
229 return false;
230 }
231 return false;
232 }
233
234 internal unsafe static bool IsValid(char* name, int start, ref int end)
235 {
236 return InternalIsValid(name, start, ref end, validateStrictAddress: false);
237 }
238
239 internal static (int longestSequenceStart, int longestSequenceLength) FindCompressionRange(ReadOnlySpan<ushort> numbers)
240 {
241 int num = 0;
242 int num2 = -1;
243 int num3 = 0;
244 for (int i = 0; i < numbers.Length; i++)
245 {
246 if (numbers[i] == 0)
247 {
248 num3++;
249 if (num3 > num)
250 {
251 num = num3;
252 num2 = i - num3 + 1;
253 }
254 }
255 else
256 {
257 num3 = 0;
258 }
259 }
260 if (num <= 1)
261 {
262 return (longestSequenceStart: -1, longestSequenceLength: -1);
263 }
264 return (longestSequenceStart: num2, longestSequenceLength: num2 + num);
265 }
266
267 internal static bool ShouldHaveIpv4Embedded(ReadOnlySpan<ushort> numbers)
268 {
269 if (numbers[0] == 0 && numbers[1] == 0 && numbers[2] == 0 && numbers[3] == 0 && numbers[6] != 0)
270 {
271 if (numbers[4] == 0 && (numbers[5] == 0 || numbers[5] == ushort.MaxValue))
272 {
273 return true;
274 }
275 if (numbers[4] == ushort.MaxValue && numbers[5] == 0)
276 {
277 return true;
278 }
279 }
280 if (numbers[4] == 0)
281 {
282 return numbers[5] == 24318;
283 }
284 return false;
285 }
286
287 internal static void Parse(ReadOnlySpan<char> address, Span<ushort> numbers, int start, ref string scopeId)
288 {
289 int num = 0;
290 int num2 = 0;
291 int num3 = -1;
292 bool flag = true;
293 int num4 = 0;
294 if (address[start] == '[')
295 {
296 start++;
297 }
298 int i = start;
299 while (i < address.Length && address[i] != ']')
300 {
301 switch (address[i])
302 {
303 case '%':
304 if (flag)
305 {
306 numbers[num2++] = (ushort)num;
307 flag = false;
308 }
309 start = i;
310 for (i++; i < address.Length && address[i] != ']' && address[i] != '/'; i++)
311 {
312 }
313 scopeId = new string(address.Slice(start, i - start));
314 for (; i < address.Length && address[i] != ']'; i++)
315 {
316 }
317 break;
318 case ':':
319 {
320 numbers[num2++] = (ushort)num;
321 num = 0;
322 i++;
323 if (address[i] == ':')
324 {
325 num3 = num2;
326 i++;
327 }
328 else if (num3 < 0 && num2 < 6)
329 {
330 break;
331 }
332 for (int j = i; j < address.Length && address[j] != ']' && address[j] != ':' && address[j] != '%' && address[j] != '/' && j < i + 4; j++)
333 {
334 if (address[j] == '.')
335 {
336 for (; j < address.Length && address[j] != ']' && address[j] != '/' && address[j] != '%'; j++)
337 {
338 }
339 num = IPv4AddressHelper.ParseHostNumber(address, i, j);
340 numbers[num2++] = (ushort)(num >> 16);
341 numbers[num2++] = (ushort)num;
342 i = j;
343 num = 0;
344 flag = false;
345 break;
346 }
347 }
348 break;
349 }
350 case '/':
351 if (flag)
352 {
353 numbers[num2++] = (ushort)num;
354 flag = false;
355 }
356 for (i++; address[i] != ']'; i++)
357 {
358 num4 = num4 * 10 + (address[i] - 48);
359 }
360 break;
361 default:
362 num = num * 16 + Uri.FromHex(address[i++]);
363 break;
364 }
365 }
366 if (flag)
367 {
368 numbers[num2++] = (ushort)num;
369 }
370 if (num3 <= 0)
371 {
372 return;
373 }
374 int num5 = 7;
375 int num6 = num2 - 1;
376 if (num6 != num5)
377 {
378 for (int num7 = num2 - num3; num7 > 0; num7--)
379 {
380 numbers[num5--] = numbers[num6];
381 numbers[num6--] = 0;
382 }
383 }
384 }
385}
static unsafe bool IsValid(char *name, int start, ref int end, bool allowIPv6, bool notImplicitFile, bool unknownScheme)
static int ParseHostNumber(ReadOnlySpan< char > str, int start, int end)
static string ParseCanonicalName(string str, int start, ref bool isLoopback, ref string scopeId)
static unsafe bool InternalIsValid(char *name, int start, ref int end, bool validateStrictAddress)
static void Parse(ReadOnlySpan< char > address, Span< ushort > numbers, int start, ref string scopeId)
static bool IsLoopback(ReadOnlySpan< ushort > numbers)
static unsafe bool IsValid(char *name, int start, ref int end)
static bool ShouldHaveIpv4Embedded(ReadOnlySpan< ushort > numbers)
static int int longestSequenceLength FindCompressionRange(ReadOnlySpan< ushort > numbers)
static int FromHex(char digit)
Definition Uri.cs:1093
static bool IsHexDigit(char character)
Definition Uri.cs:1088
ReadOnlySpan< T > Slice(int start)
Span< T > Slice(int start)
Definition Span.cs:271
unsafe void Clear()
Definition Span.cs:198