Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
ASCIIUtility.cs
Go to the documentation of this file.
7
8namespace System.Text;
9
10internal static class ASCIIUtility
11{
12 [MethodImpl(MethodImplOptions.AggressiveInlining)]
13 private static bool AllBytesInUInt64AreAscii(ulong value)
14 {
15 return (value & 0x8080808080808080uL) == 0;
16 }
17
18 [MethodImpl(MethodImplOptions.AggressiveInlining)]
19 private static bool AllCharsInUInt32AreAscii(uint value)
20 {
21 return (value & 0xFF80FF80u) == 0;
22 }
23
24 [MethodImpl(MethodImplOptions.AggressiveInlining)]
25 private static bool AllCharsInUInt64AreAscii(ulong value)
26 {
27 return (value & 0xFF80FF80FF80FF80uL) == 0;
28 }
29
30 private static bool FirstCharInUInt32IsAscii(uint value)
31 {
33 if ((value & 0xFF80u) != 0)
34 {
36 {
37 }
38 return false;
39 }
40 return true;
41 }
42
43 [MethodImpl(MethodImplOptions.AggressiveInlining)]
44 public unsafe static nuint GetIndexOfFirstNonAsciiByte(byte* pBuffer, nuint bufferLength)
45 {
46 if (!Sse2.IsSupported)
47 {
49 {
50 }
51 return GetIndexOfFirstNonAsciiByte_Default(pBuffer, bufferLength);
52 }
53 return GetIndexOfFirstNonAsciiByte_Intrinsified(pBuffer, bufferLength);
54 }
55
56 private unsafe static nuint GetIndexOfFirstNonAsciiByte_Default(byte* pBuffer, nuint bufferLength)
57 {
58 byte* ptr = pBuffer;
59 if (Vector.IsHardwareAccelerated && bufferLength >= (uint)(2 * Vector<sbyte>.Count))
60 {
61 uint count = (uint)Vector<sbyte>.Count;
62 if (Vector.GreaterThanOrEqualAll(Unsafe.ReadUnaligned<Vector<sbyte>>(pBuffer), Vector<sbyte>.Zero))
63 {
64 byte* ptr2 = pBuffer + bufferLength - count;
65 pBuffer = (byte*)((nuint)(pBuffer + count) & ~(nuint)(count - 1));
66 while (!Vector.LessThanAny(Unsafe.Read<Vector<sbyte>>(pBuffer), Vector<sbyte>.Zero))
67 {
68 pBuffer += count;
69 if (pBuffer > ptr2)
70 {
71 break;
72 }
73 }
74 bufferLength -= (nuint)pBuffer;
75 bufferLength = (nuint)(bufferLength + ptr);
76 }
77 }
78 while (true)
79 {
80 uint num;
81 if (bufferLength >= 8)
82 {
83 num = Unsafe.ReadUnaligned<uint>(pBuffer);
84 uint num2 = Unsafe.ReadUnaligned<uint>(pBuffer + 4);
85 if (!AllBytesInUInt32AreAscii(num | num2))
86 {
88 {
89 num = num2;
90 pBuffer += 4;
91 }
92 goto IL_0100;
93 }
94 pBuffer += 8;
95 bufferLength -= 8;
96 continue;
97 }
98 if ((bufferLength & 4) != 0)
99 {
100 num = Unsafe.ReadUnaligned<uint>(pBuffer);
101 if (!AllBytesInUInt32AreAscii(num))
102 {
103 goto IL_0100;
104 }
105 pBuffer += 4;
106 }
107 if ((bufferLength & 2) != 0)
108 {
109 num = Unsafe.ReadUnaligned<ushort>(pBuffer);
111 {
112 goto IL_0100;
113 }
114 pBuffer += 2;
115 }
116 if ((bufferLength & 1) != 0 && *pBuffer >= 0)
117 {
118 pBuffer++;
119 }
120 break;
121 IL_0100:
123 break;
124 }
125 return (nuint)(pBuffer - (nuint)ptr);
126 }
127
128 [MethodImpl(MethodImplOptions.AggressiveInlining)]
129 private static bool ContainsNonAsciiByte_Sse2(uint sseMask)
130 {
131 return sseMask != 0;
132 }
133
134 private unsafe static nuint GetIndexOfFirstNonAsciiByte_Intrinsified(byte* pBuffer, nuint bufferLength)
135 {
136 uint num = (uint)Unsafe.SizeOf<Vector128<byte>>();
137 nuint num2 = num - 1;
139 {
140 }
141 Vector128<byte> vector = Vector128.Create((ushort)4097).AsByte();
142 uint num3 = uint.MaxValue;
143 uint num4 = uint.MaxValue;
144 uint num5 = uint.MaxValue;
145 uint num6 = uint.MaxValue;
146 byte* ptr = pBuffer;
147 if (bufferLength >= num)
148 {
149 if (Sse2.IsSupported)
150 {
151 num3 = (uint)Sse2.MoveMask(Sse2.LoadVector128(pBuffer));
152 if (!ContainsNonAsciiByte_Sse2(num3))
153 {
154 if (bufferLength < 2 * num)
155 {
156 goto IL_0122;
157 }
158 pBuffer = (byte*)((nuint)(pBuffer + num) & ~num2);
159 bufferLength = (nuint)(bufferLength + ptr);
160 bufferLength -= (nuint)pBuffer;
161 if (bufferLength < 2 * num)
162 {
163 goto IL_00ef;
164 }
165 byte* ptr2 = pBuffer + bufferLength - 2 * num;
166 while (true)
167 {
168 if (Sse2.IsSupported)
169 {
171 Vector128<byte> value2 = Sse2.LoadAlignedVector128(pBuffer + num);
172 num3 = (uint)Sse2.MoveMask(value);
173 num4 = (uint)Sse2.MoveMask(value2);
174 if (ContainsNonAsciiByte_Sse2(num3 | num4))
175 {
176 break;
177 }
178 pBuffer += 2 * num;
179 if (pBuffer <= ptr2)
180 {
181 continue;
182 }
183 goto IL_00ef;
184 }
186 {
187 }
189 }
190 if (!Sse2.IsSupported)
191 {
193 {
194 }
196 }
197 if (!ContainsNonAsciiByte_Sse2(num3))
198 {
199 pBuffer += num;
200 num3 = num4;
201 }
202 }
203 goto IL_0197;
204 }
206 {
207 }
209 }
210 if ((bufferLength & 8) != 0)
211 {
212 _ = UIntPtr.Size;
213 ulong num7 = Unsafe.ReadUnaligned<ulong>(pBuffer);
214 if (!AllBytesInUInt64AreAscii(num7))
215 {
216 num7 &= 0x8080808080808080uL;
217 pBuffer += (nuint)(BitOperations.TrailingZeroCount(num7) >> 3);
218 goto IL_016b;
219 }
220 pBuffer += 8;
221 }
222 if ((bufferLength & 4) != 0)
223 {
224 uint value3 = Unsafe.ReadUnaligned<uint>(pBuffer);
225 if (!AllBytesInUInt32AreAscii(value3))
226 {
228 goto IL_016b;
229 }
230 pBuffer += 4;
231 }
232 if ((bufferLength & 2) != 0)
233 {
234 uint value3 = Unsafe.ReadUnaligned<ushort>(pBuffer);
235 if (!AllBytesInUInt32AreAscii(value3))
236 {
237 pBuffer += (nuint)(((nint)(sbyte)value3 >> 7) + 1);
238 goto IL_016b;
239 }
240 pBuffer += 2;
241 }
242 if ((bufferLength & 1) != 0 && *pBuffer >= 0)
243 {
244 pBuffer++;
245 }
246 goto IL_016b;
247 IL_00ef:
248 if ((bufferLength & num) == 0)
249 {
250 goto IL_0128;
251 }
252 if (Sse2.IsSupported)
253 {
254 num3 = (uint)Sse2.MoveMask(Sse2.LoadAlignedVector128(pBuffer));
255 if (!ContainsNonAsciiByte_Sse2(num3))
256 {
257 goto IL_0122;
258 }
259 goto IL_0197;
260 }
262 {
263 }
265 IL_016b:
266 return (nuint)(pBuffer - (nuint)ptr);
267 IL_0122:
268 pBuffer += num;
269 goto IL_0128;
270 IL_0197:
271 if (Sse2.IsSupported)
272 {
273 pBuffer += (uint)BitOperations.TrailingZeroCount(num3);
274 goto IL_016b;
275 }
277 {
278 }
280 IL_0128:
281 if (((byte)bufferLength & num2) != 0)
282 {
283 pBuffer += (bufferLength & num2) - num;
284 if (!Sse2.IsSupported)
285 {
287 {
288 }
290 }
291 num3 = (uint)Sse2.MoveMask(Sse2.LoadVector128(pBuffer));
293 {
294 goto IL_0197;
295 }
296 pBuffer += num;
297 }
298 goto IL_016b;
299 }
300
301 [MethodImpl(MethodImplOptions.AggressiveInlining)]
302 public unsafe static nuint GetIndexOfFirstNonAsciiChar(char* pBuffer, nuint bufferLength)
303 {
304 if (!Sse2.IsSupported)
305 {
306 return GetIndexOfFirstNonAsciiChar_Default(pBuffer, bufferLength);
307 }
308 return GetIndexOfFirstNonAsciiChar_Sse2(pBuffer, bufferLength);
309 }
310
311 private unsafe static nuint GetIndexOfFirstNonAsciiChar_Default(char* pBuffer, nuint bufferLength)
312 {
313 char* ptr = pBuffer;
314 if (Vector.IsHardwareAccelerated && bufferLength >= (uint)(2 * Vector<ushort>.Count))
315 {
316 uint count = (uint)Vector<ushort>.Count;
317 uint count2 = (uint)Vector<byte>.Count;
318 Vector<ushort> right = new Vector<ushort>(127);
319 if (Vector.LessThanOrEqualAll(Unsafe.ReadUnaligned<Vector<ushort>>(pBuffer), right))
320 {
321 char* ptr2 = pBuffer + bufferLength - count;
322 pBuffer = (char*)((nuint)((byte*)pBuffer + count2) & ~(nuint)(count2 - 1));
323 while (!Vector.GreaterThanAny(Unsafe.Read<Vector<ushort>>(pBuffer), right))
324 {
325 pBuffer += count;
326 if (pBuffer > ptr2)
327 {
328 break;
329 }
330 }
331 bufferLength -= (nuint)(nint)(pBuffer - ptr);
332 }
333 }
334 while (true)
335 {
336 uint num;
337 if (bufferLength >= 4)
338 {
339 num = Unsafe.ReadUnaligned<uint>(pBuffer);
340 uint num2 = Unsafe.ReadUnaligned<uint>(pBuffer + 2);
341 if (!AllCharsInUInt32AreAscii(num | num2))
342 {
344 {
345 num = num2;
346 pBuffer += 2;
347 }
348 goto IL_0109;
349 }
350 pBuffer += 4;
351 bufferLength -= 4;
352 continue;
353 }
354 if ((bufferLength & 2) != 0)
355 {
356 num = Unsafe.ReadUnaligned<uint>(pBuffer);
357 if (!AllCharsInUInt32AreAscii(num))
358 {
359 goto IL_0109;
360 }
361 pBuffer += 2;
362 }
363 if ((bufferLength & 1) != 0 && *pBuffer <= '\u007f')
364 {
365 pBuffer++;
366 }
367 break;
368 IL_0109:
370 {
371 pBuffer++;
372 }
373 break;
374 }
375 nuint num3 = (nuint)((byte*)pBuffer - (nuint)ptr);
376 return num3 / 2;
377 }
378
379 private unsafe static nuint GetIndexOfFirstNonAsciiChar_Sse2(char* pBuffer, nuint bufferLength)
380 {
381 if (bufferLength == 0)
382 {
383 return 0u;
384 }
385 uint num = (uint)Unsafe.SizeOf<Vector128<byte>>();
386 uint num2 = num / 2;
387 char* ptr = pBuffer;
388 Vector128<ushort> right;
389 Vector128<ushort> right2;
391 uint num3;
392 if (bufferLength >= num2)
393 {
394 right = Vector128.Create((ushort)65408);
395 right2 = Vector128.Create((ushort)32640);
396 left = Sse2.LoadVector128((ushort*)pBuffer);
397 num3 = (uint)Sse2.MoveMask(Sse2.AddSaturate(left, right2).AsByte());
398 if ((num3 & 0xAAAA) == 0)
399 {
400 bufferLength <<= 1;
401 if (bufferLength < 2 * num)
402 {
403 goto IL_013e;
404 }
405 pBuffer = (char*)((nuint)((byte*)pBuffer + num) & ~(nuint)(num - 1));
406 bufferLength = (nuint)(bufferLength + (byte*)ptr);
407 bufferLength -= (nuint)pBuffer;
408 if (bufferLength < 2 * num)
409 {
410 goto IL_00fa;
411 }
412 char* ptr2 = (char*)((byte*)pBuffer + bufferLength - 2 * num);
413 Vector128<ushort> vector;
414 while (true)
415 {
416 left = Sse2.LoadAlignedVector128((ushort*)pBuffer);
417 vector = Sse2.LoadAlignedVector128((ushort*)(pBuffer + num2));
418 Vector128<ushort> left2 = Sse2.Or(left, vector);
419 if (Sse41.IsSupported)
420 {
421 if (!Sse41.TestZ(left2, right))
422 {
423 break;
424 }
425 }
426 else
427 {
428 num3 = (uint)Sse2.MoveMask(Sse2.AddSaturate(left2, right2).AsByte());
429 if ((num3 & 0xAAAAu) != 0)
430 {
431 break;
432 }
433 }
434 pBuffer += 2 * num2;
435 if (pBuffer <= ptr2)
436 {
437 continue;
438 }
439 goto IL_00fa;
440 }
441 if (Sse41.IsSupported)
442 {
443 if (!Sse41.TestZ(left, right))
444 {
445 goto IL_01e6;
446 }
447 }
448 else
449 {
450 num3 = (uint)Sse2.MoveMask(Sse2.AddSaturate(left, right2).AsByte());
451 if ((num3 & 0xAAAAu) != 0)
452 {
453 goto IL_01fa;
454 }
455 }
456 pBuffer += num2;
457 left = vector;
458 goto IL_01e6;
459 }
460 goto IL_01fa;
461 }
462 if ((bufferLength & 4) != 0)
463 {
464 _ = UIntPtr.Size;
465 ulong num4 = Unsafe.ReadUnaligned<ulong>(pBuffer);
466 if (!AllCharsInUInt64AreAscii(num4))
467 {
468 num4 &= 0xFF80FF80FF80FF80uL;
469 pBuffer = (char*)((byte*)pBuffer + (nuint)((BitOperations.TrailingZeroCount(num4) >> 3) & ~(nint)1));
470 goto IL_01a1;
471 }
472 pBuffer += 4;
473 }
474 if ((bufferLength & 2) != 0)
475 {
476 uint value = Unsafe.ReadUnaligned<uint>(pBuffer);
478 {
480 {
481 pBuffer++;
482 }
483 goto IL_01a1;
484 }
485 pBuffer += 2;
486 }
487 if ((bufferLength & 1) != 0 && *pBuffer <= '\u007f')
488 {
489 pBuffer++;
490 }
491 goto IL_01a1;
492 IL_00fa:
493 if ((bufferLength & num) != 0)
494 {
495 left = Sse2.LoadAlignedVector128((ushort*)pBuffer);
496 if (Sse41.IsSupported)
497 {
498 if (!Sse41.TestZ(left, right))
499 {
500 goto IL_01e6;
501 }
502 }
503 else
504 {
505 num3 = (uint)Sse2.MoveMask(Sse2.AddSaturate(left, right2).AsByte());
506 if ((num3 & 0xAAAAu) != 0)
507 {
508 goto IL_01fa;
509 }
510 }
511 goto IL_013e;
512 }
513 goto IL_0148;
514 IL_01fa:
515 num3 &= 0xAAAAu;
516 pBuffer = (char*)((byte*)pBuffer + (uint)BitOperations.TrailingZeroCount(num3) - 1);
517 goto IL_01a1;
518 IL_0148:
519 if (((byte)bufferLength & (num - 1)) != 0)
520 {
521 pBuffer = (char*)((byte*)pBuffer + (bufferLength & (num - 1)) - num);
522 left = Sse2.LoadVector128((ushort*)pBuffer);
523 if (Sse41.IsSupported)
524 {
525 if (!Sse41.TestZ(left, right))
526 {
527 goto IL_01e6;
528 }
529 }
530 else
531 {
532 num3 = (uint)Sse2.MoveMask(Sse2.AddSaturate(left, right2).AsByte());
533 if ((num3 & 0xAAAAu) != 0)
534 {
535 goto IL_01fa;
536 }
537 }
538 pBuffer += num2;
539 }
540 goto IL_01a1;
541 IL_01e6:
542 num3 = (uint)Sse2.MoveMask(Sse2.AddSaturate(left, right2).AsByte());
543 goto IL_01fa;
544 IL_013e:
545 pBuffer += num2;
546 goto IL_0148;
547 IL_01a1:
548 return (nuint)(pBuffer - ptr);
549 }
550
551 [MethodImpl(MethodImplOptions.AggressiveInlining)]
552 private static void NarrowFourUtf16CharsToAsciiAndWriteToBuffer(ref byte outputBuffer, ulong value)
553 {
554 if (Sse2.X64.IsSupported)
555 {
557 Vector128<uint> value2 = Sse2.PackUnsignedSaturate(vector, vector).AsUInt32();
558 Unsafe.WriteUnaligned(ref outputBuffer, Sse2.ConvertToUInt32(value2));
559 return;
560 }
562 {
563 }
565 outputBuffer = (byte)value;
566 value >>= 16;
567 Unsafe.Add(ref outputBuffer, 1) = (byte)value;
568 value >>= 16;
569 Unsafe.Add(ref outputBuffer, 2) = (byte)value;
570 value >>= 16;
571 Unsafe.Add(ref outputBuffer, 3) = (byte)value;
572 }
573
574 [MethodImpl(MethodImplOptions.AggressiveInlining)]
575 private static void NarrowTwoUtf16CharsToAsciiAndWriteToBuffer(ref byte outputBuffer, uint value)
576 {
578 outputBuffer = (byte)value;
579 Unsafe.Add(ref outputBuffer, 1) = (byte)(value >> 16);
580 }
581
582 public unsafe static nuint NarrowUtf16ToAscii(char* pUtf16Buffer, byte* pAsciiBuffer, nuint elementCount)
583 {
584 nuint num = 0u;
585 uint num2 = 0u;
586 uint num3 = 0u;
587 ulong num4 = 0uL;
588 if (Sse2.IsSupported)
589 {
590 if (elementCount >= (uint)(2 * Unsafe.SizeOf<Vector128<byte>>()))
591 {
592 _ = IntPtr.Size;
593 num4 = Unsafe.ReadUnaligned<ulong>(pUtf16Buffer);
594 if (!AllCharsInUInt64AreAscii(num4))
595 {
596 goto IL_018b;
597 }
598 num = NarrowUtf16ToAscii_Sse2(pUtf16Buffer, pAsciiBuffer, elementCount);
599 }
600 }
602 {
603 uint num5 = (uint)Unsafe.SizeOf<Vector<byte>>();
604 if (elementCount >= 2 * num5)
605 {
606 _ = IntPtr.Size;
607 num4 = Unsafe.ReadUnaligned<ulong>(pUtf16Buffer);
608 if (!AllCharsInUInt64AreAscii(num4))
609 {
610 goto IL_018b;
611 }
612 Vector<ushort> right = new Vector<ushort>(127);
613 nuint num6 = elementCount - 2 * num5;
614 do
615 {
616 Vector<ushort> vector = Unsafe.ReadUnaligned<Vector<ushort>>(pUtf16Buffer + num);
617 Vector<ushort> vector2 = Unsafe.ReadUnaligned<Vector<ushort>>(pUtf16Buffer + num + Vector<ushort>.Count);
618 if (Vector.GreaterThanAny(Vector.BitwiseOr(vector, vector2), right))
619 {
620 break;
621 }
622 Vector<byte> value = Vector.Narrow(vector, vector2);
623 Unsafe.WriteUnaligned(pAsciiBuffer + num, value);
624 num += num5;
625 }
626 while (num <= num6);
627 }
628 }
629 nuint num7 = elementCount - num;
630 if (num7 < 4)
631 {
632 goto IL_0137;
633 }
634 nuint num8 = num + num7 - 4;
635 while (true)
636 {
637 _ = IntPtr.Size;
638 num4 = Unsafe.ReadUnaligned<ulong>(pUtf16Buffer + num);
639 if (!AllCharsInUInt64AreAscii(num4))
640 {
641 break;
642 }
643 NarrowFourUtf16CharsToAsciiAndWriteToBuffer(ref pAsciiBuffer[num], num4);
644 num += 4;
645 if (num <= num8)
646 {
647 continue;
648 }
649 goto IL_0137;
650 }
651 goto IL_018b;
652 IL_01c4:
653 if (FirstCharInUInt32IsAscii(num2))
654 {
656 {
657 }
658 pAsciiBuffer[num] = (byte)num2;
659 num++;
660 }
661 goto IL_0189;
662 IL_0189:
663 return num;
664 IL_0137:
665 if (((uint)(int)num7 & 2u) != 0)
666 {
667 num2 = Unsafe.ReadUnaligned<uint>(pUtf16Buffer + num);
668 if (!AllCharsInUInt32AreAscii(num2))
669 {
670 goto IL_01c4;
671 }
672 NarrowTwoUtf16CharsToAsciiAndWriteToBuffer(ref pAsciiBuffer[num], num2);
673 num += 2;
674 }
675 if (((uint)(int)num7 & (true ? 1u : 0u)) != 0)
676 {
677 num2 = pUtf16Buffer[num];
678 if (num2 <= 127)
679 {
680 pAsciiBuffer[num] = (byte)num2;
681 num++;
682 }
683 }
684 goto IL_0189;
685 IL_018b:
686 _ = IntPtr.Size;
688 num2 = (uint)num4;
689 if (AllCharsInUInt32AreAscii(num2))
690 {
691 NarrowTwoUtf16CharsToAsciiAndWriteToBuffer(ref pAsciiBuffer[num], num2);
693 num2 = (uint)(num4 >> 32);
694 num += 2;
695 }
696 goto IL_01c4;
697 }
698
699 private unsafe static nuint NarrowUtf16ToAscii_Sse2(char* pUtf16Buffer, byte* pAsciiBuffer, nuint elementCount)
700 {
701 uint num = (uint)Unsafe.SizeOf<Vector128<byte>>();
702 nuint num2 = num - 1;
703 Vector128<short> right = Vector128.Create((short)(-128));
704 Vector128<ushort> right2 = Vector128.Create((ushort)32640);
705 Vector128<short> vector = Sse2.LoadVector128((short*)pUtf16Buffer);
706 if (Sse41.IsSupported)
707 {
708 if (!Sse41.TestZ(vector, right))
709 {
710 return 0u;
711 }
712 }
713 else if (((uint)Sse2.MoveMask(Sse2.AddSaturate(vector.AsUInt16(), right2).AsByte()) & 0xAAAAu) != 0)
714 {
715 return 0u;
716 }
717 Vector128<byte> vector2 = Sse2.PackUnsignedSaturate(vector, vector);
718 Sse2.StoreScalar((ulong*)pAsciiBuffer, vector2.AsUInt64());
719 nuint num3 = num / 2;
720 if (((uint)(int)pAsciiBuffer & (num / 2)) != 0)
721 {
722 goto IL_00e7;
723 }
724 vector = Sse2.LoadVector128((short*)(pUtf16Buffer + num3));
725 if (Sse41.IsSupported)
726 {
727 if (Sse41.TestZ(vector, right))
728 {
729 goto IL_00ca;
730 }
731 }
732 else if ((Sse2.MoveMask(Sse2.AddSaturate(vector.AsUInt16(), right2).AsByte()) & 0xAAAA) == 0)
733 {
734 goto IL_00ca;
735 }
736 goto IL_0183;
737 IL_0183:
738 return num3;
739 IL_00ca:
740 vector2 = Sse2.PackUnsignedSaturate(vector, vector);
741 Sse2.StoreScalar((ulong*)(pAsciiBuffer + num3), vector2.AsUInt64());
742 goto IL_00e7;
743 IL_00e7:
744 num3 = num - ((nuint)pAsciiBuffer & num2);
745 nuint num4 = elementCount - num;
746 do
747 {
748 vector = Sse2.LoadVector128((short*)(pUtf16Buffer + num3));
749 Vector128<short> right3 = Sse2.LoadVector128((short*)(pUtf16Buffer + num3 + num / 2));
750 Vector128<short> vector3 = Sse2.Or(vector, right3);
751 if (Sse41.IsSupported)
752 {
753 if (Sse41.TestZ(vector3, right))
754 {
755 goto IL_015b;
756 }
757 }
758 else if ((Sse2.MoveMask(Sse2.AddSaturate(vector3.AsUInt16(), right2).AsByte()) & 0xAAAA) == 0)
759 {
760 goto IL_015b;
761 }
762 if (Sse41.IsSupported)
763 {
764 if (!Sse41.TestZ(vector, right))
765 {
766 break;
767 }
768 }
769 else if (((uint)Sse2.MoveMask(Sse2.AddSaturate(vector.AsUInt16(), right2).AsByte()) & 0xAAAAu) != 0)
770 {
771 break;
772 }
773 vector2 = Sse2.PackUnsignedSaturate(vector, vector);
774 Sse2.StoreScalar((ulong*)(pAsciiBuffer + num3), vector2.AsUInt64());
775 num3 += num / 2;
776 break;
777 IL_015b:
778 vector2 = Sse2.PackUnsignedSaturate(vector, right3);
779 Sse2.StoreAligned(pAsciiBuffer + num3, vector2);
780 num3 += num;
781 }
782 while (num3 <= num4);
783 goto IL_0183;
784 }
785
786 public unsafe static nuint WidenAsciiToUtf16(byte* pAsciiBuffer, char* pUtf16Buffer, nuint elementCount)
787 {
788 nuint num = 0u;
791 {
792 if (elementCount >= (uint)(2 * Unsafe.SizeOf<Vector128<byte>>()))
793 {
794 num = WidenAsciiToUtf16_Intrinsified(pAsciiBuffer, pUtf16Buffer, elementCount);
795 }
796 }
798 {
799 uint num2 = (uint)Unsafe.SizeOf<Vector<byte>>();
800 if (elementCount >= num2)
801 {
802 nuint num3 = elementCount - num2;
803 do
804 {
805 Vector<sbyte> vector = Unsafe.ReadUnaligned<Vector<sbyte>>(pAsciiBuffer + num);
806 if (Vector.LessThanAny(vector, Vector<sbyte>.Zero))
807 {
808 break;
809 }
810 Vector.Widen(Vector.AsVectorByte(vector), out var low, out var high);
811 Unsafe.WriteUnaligned(pUtf16Buffer + num, low);
812 Unsafe.WriteUnaligned(pUtf16Buffer + num + Vector<ushort>.Count, high);
813 num += num2;
814 }
815 while (num <= num3);
816 }
817 }
818 nuint num4 = elementCount - num;
819 if (num4 < 4)
820 {
821 goto IL_00df;
822 }
823 nuint num5 = num + num4 - 4;
824 uint num6;
825 while (true)
826 {
827 num6 = Unsafe.ReadUnaligned<uint>(pAsciiBuffer + num);
828 if (!AllBytesInUInt32AreAscii(num6))
829 {
830 break;
831 }
832 WidenFourAsciiBytesToUtf16AndWriteToBuffer(ref pUtf16Buffer[num], num6);
833 num += 4;
834 if (num <= num5)
835 {
836 continue;
837 }
838 goto IL_00df;
839 }
840 goto IL_014f;
841 IL_014d:
842 return num;
843 IL_014f:
845 while (((byte)num6 & 0x80) == 0)
846 {
847 pUtf16Buffer[num] = (char)(byte)num6;
848 num++;
849 num6 >>= 8;
850 }
851 goto IL_014d;
852 IL_00df:
853 if (((uint)(int)num4 & 2u) != 0)
854 {
855 num6 = Unsafe.ReadUnaligned<ushort>(pAsciiBuffer + num);
857 {
858 goto IL_014f;
859 }
861 pUtf16Buffer[num] = (char)(byte)num6;
862 pUtf16Buffer[num + 1] = (char)(num6 >> 8);
863 num += 2;
864 }
865 if (((uint)(int)num4 & (true ? 1u : 0u)) != 0)
866 {
867 num6 = pAsciiBuffer[num];
868 if (((byte)num6 & 0x80) == 0)
869 {
870 pUtf16Buffer[num] = (char)num6;
871 num++;
872 }
873 }
874 goto IL_014d;
875 }
876
877 private unsafe static nuint WidenAsciiToUtf16_Intrinsified(byte* pAsciiBuffer, char* pUtf16Buffer, nuint elementCount)
878 {
879 uint num = (uint)Unsafe.SizeOf<Vector128<byte>>();
880 nuint num2 = num - 1;
881 if (Sse2.IsSupported)
882 {
883 Vector128<byte> vector = Sse2.LoadVector128(pAsciiBuffer);
884 if (Sse2.MoveMask(vector) != 0)
885 {
886 return 0u;
887 }
889 if (Sse2.IsSupported)
890 {
891 Vector128<byte> source = Sse2.UnpackLow(vector, zero);
892 Sse2.Store((byte*)pUtf16Buffer, source);
893 nuint num3 = (num >> 1) - (((nuint)pUtf16Buffer >> 1) & (num2 >> 1));
894 nuint num4 = elementCount - num;
895 char* ptr = pUtf16Buffer + num3;
896 while (true)
897 {
898 if (Sse2.IsSupported)
899 {
900 vector = Sse2.LoadVector128(pAsciiBuffer + num3);
901 bool flag = Sse2.MoveMask(vector) != 0;
902 if (!flag)
903 {
904 if (!Sse2.IsSupported)
905 {
907 {
908 }
910 }
911 Vector128<byte> source2 = Sse2.UnpackLow(vector, zero);
912 Sse2.StoreAligned((byte*)ptr, source2);
913 Vector128<byte> source3 = Sse2.UnpackHigh(vector, zero);
914 Sse2.StoreAligned((byte*)ptr + num, source3);
915 num3 += num;
916 ptr += num;
917 if (num3 <= num4)
918 {
919 continue;
920 }
921 }
922 else if (!flag)
923 {
924 if (!Sse2.IsSupported)
925 {
926 break;
927 }
928 source = Sse2.UnpackLow(vector, zero);
929 Sse2.StoreAligned((byte*)(pUtf16Buffer + num3), source);
930 num3 += num / 2;
931 }
932 return num3;
933 }
935 {
936 }
938 }
940 {
941 }
943 }
945 {
946 }
948 }
950 {
951 }
953 }
954
955 [MethodImpl(MethodImplOptions.AggressiveInlining)]
956 internal static void WidenFourAsciiBytesToUtf16AndWriteToBuffer(ref char outputBuffer, uint value)
957 {
958 if (Sse2.X64.IsSupported)
959 {
961 Vector128<ulong> value2 = Sse2.UnpackLow(left, Vector128<byte>.Zero).AsUInt64();
962 Unsafe.WriteUnaligned(ref Unsafe.As<char, byte>(ref outputBuffer), Sse2.X64.ConvertToUInt64(value2));
963 return;
964 }
966 {
967 }
969 outputBuffer = (char)(byte)value;
970 value >>= 8;
971 Unsafe.Add(ref outputBuffer, 1) = (char)(byte)value;
972 value >>= 8;
973 Unsafe.Add(ref outputBuffer, 2) = (char)(byte)value;
974 value >>= 8;
975 Unsafe.Add(ref outputBuffer, 3) = (char)value;
976 }
977
978 [MethodImpl(MethodImplOptions.AggressiveInlining)]
979 internal static bool AllBytesInUInt32AreAscii(uint value)
980 {
981 return (value & 0x80808080u) == 0;
982 }
983
984 [MethodImpl(MethodImplOptions.AggressiveInlining)]
986 {
988 return (uint)BitOperations.TrailingZeroCount(value & 0x80808080u) >> 3;
989 }
990}
static readonly bool IsLittleEndian
static int TrailingZeroCount(int value)
static Vector< T > Zero
Definition Vector.cs:874
static bool IsHardwareAccelerated
Definition Vector.cs:14
static unsafe void Widen(Vector< byte > source, out Vector< ushort > low, out Vector< ushort > high)
Definition Vector.cs:493
static unsafe Vector< byte > Narrow(Vector< ushort > low, Vector< ushort > high)
Definition Vector.cs:623
static Vector128< byte > Create(byte value)
Definition Vector128.cs:138
static Vector128< ulong > ConvertScalarToVector128UInt64(ulong value)
Definition Sse2.cs:39
static ulong ConvertToUInt64(Vector128< ulong > value)
Definition Sse2.cs:24
static unsafe Vector128< sbyte > LoadVector128(sbyte *address)
Definition Sse2.cs:582
static int MoveMask(Vector128< sbyte > value)
Definition Sse2.cs:772
static unsafe Vector128< sbyte > LoadAlignedVector128(sbyte *address)
Definition Sse2.cs:632
static uint ConvertToUInt32(Vector128< uint > value)
Definition Sse2.cs:512
static unsafe void StoreScalar(double *address, Vector128< double > source)
Definition Sse2.cs:1172
static unsafe void Store(sbyte *address, Vector128< sbyte > source)
Definition Sse2.cs:1287
static Vector128< byte > PackUnsignedSaturate(Vector128< short > left, Vector128< short > right)
Definition Sse2.cs:892
static Vector128< byte > Or(Vector128< byte > left, Vector128< byte > right)
Definition Sse2.cs:837
static Vector128< sbyte > AddSaturate(Vector128< sbyte > left, Vector128< sbyte > right)
Definition Sse2.cs:112
static unsafe void StoreAligned(sbyte *address, Vector128< sbyte > source)
Definition Sse2.cs:1197
static Vector128< byte > UnpackLow(Vector128< byte > left, Vector128< byte > right)
Definition Sse2.cs:1467
static new bool IsSupported
Definition Sse2.cs:60
static Vector128< uint > ConvertScalarToVector128UInt32(uint value)
Definition Sse2.cs:537
static Vector128< byte > UnpackHigh(Vector128< byte > left, Vector128< byte > right)
Definition Sse2.cs:1422
static bool TestZ(Vector128< sbyte > left, Vector128< sbyte > right)
Definition Sse41.cs:692
static bool AllCharsInUInt32AreAscii(uint value)
static unsafe nuint GetIndexOfFirstNonAsciiByte_Default(byte *pBuffer, nuint bufferLength)
static unsafe nuint GetIndexOfFirstNonAsciiByte(byte *pBuffer, nuint bufferLength)
static bool AllCharsInUInt64AreAscii(ulong value)
static uint CountNumberOfLeadingAsciiBytesFromUInt32WithSomeNonAsciiData(uint value)
static bool FirstCharInUInt32IsAscii(uint value)
static void WidenFourAsciiBytesToUtf16AndWriteToBuffer(ref char outputBuffer, uint value)
static void NarrowFourUtf16CharsToAsciiAndWriteToBuffer(ref byte outputBuffer, ulong value)
static unsafe nuint GetIndexOfFirstNonAsciiChar_Sse2(char *pBuffer, nuint bufferLength)
static bool ContainsNonAsciiByte_Sse2(uint sseMask)
static unsafe nuint WidenAsciiToUtf16(byte *pAsciiBuffer, char *pUtf16Buffer, nuint elementCount)
static void NarrowTwoUtf16CharsToAsciiAndWriteToBuffer(ref byte outputBuffer, uint value)
static bool AllBytesInUInt32AreAscii(uint value)
static unsafe nuint NarrowUtf16ToAscii(char *pUtf16Buffer, byte *pAsciiBuffer, nuint elementCount)
static unsafe nuint GetIndexOfFirstNonAsciiChar(char *pBuffer, nuint bufferLength)
static unsafe nuint GetIndexOfFirstNonAsciiByte_Intrinsified(byte *pBuffer, nuint bufferLength)
static bool AllBytesInUInt64AreAscii(ulong value)
static unsafe nuint NarrowUtf16ToAscii_Sse2(char *pUtf16Buffer, byte *pAsciiBuffer, nuint elementCount)
static unsafe nuint WidenAsciiToUtf16_Intrinsified(byte *pAsciiBuffer, char *pUtf16Buffer, nuint elementCount)
static unsafe nuint GetIndexOfFirstNonAsciiChar_Default(char *pBuffer, nuint bufferLength)
static int Size
Definition IntPtr.cs:21
static int Size
Definition UIntPtr.cs:22