Skip to content

Commit b30129c

Browse files
author
egorbot
committed
simpler version
1 parent 93d49b4 commit b30129c

5 files changed

Lines changed: 174 additions & 248 deletions

File tree

src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64DecoderHelper.cs

Lines changed: 89 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,14 @@ internal static unsafe OperationStatus DecodeFrom<TBase64Decoder, T>(TBase64Deco
129129

130130
while (src < srcMax)
131131
{
132-
int result = decoder.DecodeFourElements(src, ref decodingMap);
132+
int result = decoder.DecodeFourElements(new ReadOnlySpan<T>(src, 4), ref decodingMap);
133133

134134
if (result < 0)
135135
{
136136
goto InvalidDataExit;
137137
}
138138

139-
WriteThreeLowOrderBytes(dest, result);
139+
WriteThreeLowOrderBytes(new Span<byte>(dest, 3), result);
140140
src += 4;
141141
dest += 3;
142142
}
@@ -166,7 +166,7 @@ internal static unsafe OperationStatus DecodeFrom<TBase64Decoder, T>(TBase64Deco
166166
// If more than 4 bytes remained it will end up in DestinationTooSmallExit or InvalidDataExit (might succeed after whitespace removed)
167167
long remaining = srcEnd - src;
168168
Debug.Assert(typeof(TBase64Decoder) == typeof(Base64DecoderByte) ? remaining == 4 : remaining < 8);
169-
int i0 = decoder.DecodeRemaining(srcEnd, ref decodingMap, remaining, out uint t2, out uint t3);
169+
int i0 = decoder.DecodeRemaining(new ReadOnlySpan<T>(src, (int)remaining), ref decodingMap, out uint t2, out uint t3);
170170

171171
if (i0 < 0)
172172
{
@@ -194,7 +194,7 @@ internal static unsafe OperationStatus DecodeFrom<TBase64Decoder, T>(TBase64Deco
194194
goto DestinationTooSmallExit;
195195
}
196196

197-
WriteThreeLowOrderBytes(dest, i0);
197+
WriteThreeLowOrderBytes(new Span<byte>(dest, 3), i0);
198198
dest += 3;
199199
src += 4;
200200
}
@@ -331,7 +331,7 @@ static OperationStatus InvalidDataFallback(TBase64Decoder decoder, ReadOnlySpan<
331331
}
332332
}
333333

334-
internal static unsafe OperationStatus DecodeFromUtf8InPlace<TBase64Decoder>(TBase64Decoder decoder, Span<byte> buffer, out int bytesWritten, bool ignoreWhiteSpace)
334+
internal static OperationStatus DecodeFromUtf8InPlace<TBase64Decoder>(TBase64Decoder decoder, Span<byte> buffer, out int bytesWritten, bool ignoreWhiteSpace)
335335
where TBase64Decoder : IBase64Decoder<byte>
336336
{
337337
if (buffer.IsEmpty)
@@ -340,64 +340,63 @@ internal static unsafe OperationStatus DecodeFromUtf8InPlace<TBase64Decoder>(TBa
340340
return OperationStatus.Done;
341341
}
342342

343-
fixed (byte* bufferBytes = &MemoryMarshal.GetReference(buffer))
344-
{
345-
uint bufferLength = (uint)buffer.Length;
346-
uint sourceIndex = 0;
347-
uint destIndex = 0;
343+
uint bufferLength = (uint)buffer.Length;
344+
uint sourceIndex = 0;
345+
uint destIndex = 0;
348346

349-
if (decoder.IsInvalidLength(buffer.Length))
350-
{
351-
goto InvalidExit;
352-
}
347+
if (decoder.IsInvalidLength(buffer.Length))
348+
{
349+
goto InvalidExit;
350+
}
353351

354-
ref sbyte decodingMap = ref MemoryMarshal.GetReference(decoder.DecodingMap);
352+
ref sbyte decodingMap = ref MemoryMarshal.GetReference(decoder.DecodingMap);
355353

356-
if (bufferLength > 4)
354+
if (bufferLength > 4)
355+
{
356+
while (sourceIndex < bufferLength - 4)
357357
{
358-
while (sourceIndex < bufferLength - 4)
358+
int result = decoder.DecodeFourElements(buffer.Slice((int)sourceIndex, 4), ref decodingMap);
359+
if (result < 0)
359360
{
360-
int result = decoder.DecodeFourElements(bufferBytes + sourceIndex, ref decodingMap);
361-
if (result < 0)
362-
{
363-
goto InvalidExit;
364-
}
365-
366-
WriteThreeLowOrderBytes(bufferBytes + destIndex, result);
367-
destIndex += 3;
368-
sourceIndex += 4;
361+
goto InvalidExit;
369362
}
363+
364+
WriteThreeLowOrderBytes(buffer.Slice((int)destIndex, 3), result);
365+
destIndex += 3;
366+
sourceIndex += 4;
370367
}
368+
}
371369

372-
uint t0;
373-
uint t1;
374-
uint t2;
375-
uint t3;
370+
uint t0;
371+
uint t1;
372+
uint t2;
373+
uint t3;
376374

377-
switch (bufferLength - sourceIndex)
378-
{
379-
case 2:
380-
t0 = bufferBytes[bufferLength - 2];
381-
t1 = bufferBytes[bufferLength - 1];
382-
t2 = EncodingPad;
383-
t3 = EncodingPad;
384-
break;
385-
case 3:
386-
t0 = bufferBytes[bufferLength - 3];
387-
t1 = bufferBytes[bufferLength - 2];
388-
t2 = bufferBytes[bufferLength - 1];
389-
t3 = EncodingPad;
390-
break;
391-
case 4:
392-
t0 = bufferBytes[bufferLength - 4];
393-
t1 = bufferBytes[bufferLength - 3];
394-
t2 = bufferBytes[bufferLength - 2];
395-
t3 = bufferBytes[bufferLength - 1];
396-
break;
397-
default:
398-
goto InvalidExit;
399-
}
375+
switch (bufferLength - sourceIndex)
376+
{
377+
case 2:
378+
t0 = buffer[(int)(bufferLength - 2)];
379+
t1 = buffer[(int)(bufferLength - 1)];
380+
t2 = EncodingPad;
381+
t3 = EncodingPad;
382+
break;
383+
case 3:
384+
t0 = buffer[(int)(bufferLength - 3)];
385+
t1 = buffer[(int)(bufferLength - 2)];
386+
t2 = buffer[(int)(bufferLength - 1)];
387+
t3 = EncodingPad;
388+
break;
389+
case 4:
390+
t0 = buffer[(int)(bufferLength - 4)];
391+
t1 = buffer[(int)(bufferLength - 3)];
392+
t2 = buffer[(int)(bufferLength - 2)];
393+
t3 = buffer[(int)(bufferLength - 1)];
394+
break;
395+
default:
396+
goto InvalidExit;
397+
}
400398

399+
{
401400
int i0 = Unsafe.Add(ref decodingMap, (int)t0);
402401
int i1 = Unsafe.Add(ref decodingMap, (int)t1);
403402

@@ -421,7 +420,7 @@ internal static unsafe OperationStatus DecodeFromUtf8InPlace<TBase64Decoder>(TBa
421420
goto InvalidExit;
422421
}
423422

424-
WriteThreeLowOrderBytes(bufferBytes + destIndex, i0);
423+
WriteThreeLowOrderBytes(buffer.Slice((int)destIndex, 3), i0);
425424
destIndex += 3;
426425
}
427426
else if (!decoder.IsValidPadding(t2))
@@ -437,8 +436,8 @@ internal static unsafe OperationStatus DecodeFromUtf8InPlace<TBase64Decoder>(TBa
437436
goto InvalidExit;
438437
}
439438

440-
bufferBytes[destIndex] = (byte)(i0 >> 16);
441-
bufferBytes[destIndex + 1] = (byte)(i0 >> 8);
439+
buffer[(int)destIndex] = (byte)(i0 >> 16);
440+
buffer[(int)(destIndex + 1)] = (byte)(i0 >> 8);
442441
destIndex += 2;
443442
}
444443
else
@@ -448,19 +447,19 @@ internal static unsafe OperationStatus DecodeFromUtf8InPlace<TBase64Decoder>(TBa
448447
goto InvalidExit;
449448
}
450449

451-
bufferBytes[destIndex] = (byte)(i0 >> 16);
450+
buffer[(int)destIndex] = (byte)(i0 >> 16);
452451
destIndex += 1;
453452
}
453+
}
454454

455-
bytesWritten = (int)destIndex;
456-
return OperationStatus.Done;
455+
bytesWritten = (int)destIndex;
456+
return OperationStatus.Done;
457457

458-
InvalidExit:
459-
bytesWritten = (int)destIndex;
460-
return ignoreWhiteSpace ?
461-
DecodeWithWhiteSpaceFromUtf8InPlace<TBase64Decoder>(decoder, buffer, ref bytesWritten, sourceIndex) : // The input may have whitespace, attempt to decode while ignoring whitespace.
462-
OperationStatus.InvalidData;
463-
}
458+
InvalidExit:
459+
bytesWritten = (int)destIndex;
460+
return ignoreWhiteSpace ?
461+
DecodeWithWhiteSpaceFromUtf8InPlace<TBase64Decoder>(decoder, buffer, ref bytesWritten, sourceIndex) : // The input may have whitespace, attempt to decode while ignoring whitespace.
462+
OperationStatus.InvalidData;
464463
}
465464

466465
internal static OperationStatus DecodeWithWhiteSpaceBlockwise<TBase64Decoder>(TBase64Decoder decoder, ReadOnlySpan<byte> source, Span<byte> bytes, ref int bytesConsumed, ref int bytesWritten, bool isFinalBlock = true)
@@ -1300,7 +1299,7 @@ private static unsafe void Vector128Decode<TBase64Decoder, T>(TBase64Decoder dec
13001299
#endif
13011300

13021301
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1303-
private static unsafe void WriteThreeLowOrderBytes(byte* destination, int value)
1302+
private static void WriteThreeLowOrderBytes(Span<byte> destination, int value)
13041303
{
13051304
destination[0] = (byte)(value >> 16);
13061305
destination[1] = (byte)(value >> 8);
@@ -1514,7 +1513,7 @@ public unsafe bool TryLoadArmVector128x4(byte* src, byte* srcStart, int sourceLe
15141513
#endif // NET
15151514

15161515
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1517-
public unsafe int DecodeFourElements(byte* source, ref sbyte decodingMap)
1516+
public int DecodeFourElements(ReadOnlySpan<byte> source, ref sbyte decodingMap)
15181517
{
15191518
// The 'source' span expected to have at least 4 elements, and the 'decodingMap' consists 256 sbytes
15201519
uint t0 = source[0];
@@ -1539,28 +1538,28 @@ public unsafe int DecodeFourElements(byte* source, ref sbyte decodingMap)
15391538
}
15401539

15411540
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1542-
public unsafe int DecodeRemaining(byte* srcEnd, ref sbyte decodingMap, long remaining, out uint t2, out uint t3)
1541+
public int DecodeRemaining(ReadOnlySpan<byte> source, ref sbyte decodingMap, out uint t2, out uint t3)
15431542
{
15441543
uint t0;
15451544
uint t1;
15461545
t2 = EncodingPad;
15471546
t3 = EncodingPad;
1548-
switch (remaining)
1547+
switch (source.Length)
15491548
{
15501549
case 2:
1551-
t0 = srcEnd[-2];
1552-
t1 = srcEnd[-1];
1550+
t0 = source[0];
1551+
t1 = source[1];
15531552
break;
15541553
case 3:
1555-
t0 = srcEnd[-3];
1556-
t1 = srcEnd[-2];
1557-
t2 = srcEnd[-1];
1554+
t0 = source[0];
1555+
t1 = source[1];
1556+
t2 = source[2];
15581557
break;
15591558
case 4:
1560-
t0 = srcEnd[-4];
1561-
t1 = srcEnd[-3];
1562-
t2 = srcEnd[-2];
1563-
t3 = srcEnd[-1];
1559+
t0 = source[0];
1560+
t1 = source[1];
1561+
t2 = source[2];
1562+
t3 = source[3];
15641563
break;
15651564
default:
15661565
return -1;
@@ -1720,7 +1719,7 @@ public unsafe bool TryLoadArmVector128x4(ushort* src, ushort* srcStart, int sour
17201719
#endif // NET
17211720

17221721
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1723-
public unsafe int DecodeFourElements(ushort* source, ref sbyte decodingMap)
1722+
public int DecodeFourElements(ReadOnlySpan<ushort> source, ref sbyte decodingMap)
17241723
{
17251724
// The 'source' span expected to have at least 4 elements, and the 'decodingMap' consists 256 sbytes
17261725
uint t0 = source[0];
@@ -1750,28 +1749,28 @@ public unsafe int DecodeFourElements(ushort* source, ref sbyte decodingMap)
17501749
}
17511750

17521751
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1753-
public unsafe int DecodeRemaining(ushort* srcEnd, ref sbyte decodingMap, long remaining, out uint t2, out uint t3)
1752+
public int DecodeRemaining(ReadOnlySpan<ushort> source, ref sbyte decodingMap, out uint t2, out uint t3)
17541753
{
17551754
uint t0;
17561755
uint t1;
17571756
t2 = EncodingPad;
17581757
t3 = EncodingPad;
1759-
switch (remaining)
1758+
switch (source.Length)
17601759
{
17611760
case 2:
1762-
t0 = srcEnd[-2];
1763-
t1 = srcEnd[-1];
1761+
t0 = source[0];
1762+
t1 = source[1];
17641763
break;
17651764
case 3:
1766-
t0 = srcEnd[-3];
1767-
t1 = srcEnd[-2];
1768-
t2 = srcEnd[-1];
1765+
t0 = source[0];
1766+
t1 = source[1];
1767+
t2 = source[2];
17691768
break;
17701769
case 4:
1771-
t0 = srcEnd[-4];
1772-
t1 = srcEnd[-3];
1773-
t2 = srcEnd[-2];
1774-
t3 = srcEnd[-1];
1770+
t0 = source[0];
1771+
t1 = source[1];
1772+
t2 = source[2];
1773+
t3 = source[3];
17751774
break;
17761775
default:
17771776
return -1;

0 commit comments

Comments
 (0)