Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 40 additions & 8 deletions Base64/FromBase64Transform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,27 @@ public unsafe int TransformBlock(Block block)
fixed (char* cp = tempCharBuffer)
{
nWritten = ASCII.GetChars(startPtr, 4 * numBlocks, cp, bufferSize);
}

}

#if NETFRAMEWORK
fixed (byte* op = block.outputBuffer)
{
int outputBytes = UnsafeConvert.FromBase64CharArray(tempCharBuffer, 0, nWritten, op + block.outputOffset);

block.outputOffset += outputBytes;
totalOutputBytes += outputBytes;
}

// If we couldn't write a complete block, try to find 4 bytes starting from the last space.
#endif
#if NET5_0_OR_GREATER
if (!Convert.TryFromBase64Chars(tempCharBuffer.AsSpan().Slice(0, nWritten), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes))
{
throw new FormatException();
}

block.outputOffset += outputBytes;
totalOutputBytes += outputBytes;
#endif
// If we couldn't write a complete block, try to find 4 bytes starting from the last space.
int remainder = effectiveCount % 4;

if (remainder != 0)
Expand All @@ -119,15 +129,26 @@ public unsafe int TransformBlock(Block block)
fixed (byte* tp = this.tempByteBuffer)
{
nWritten = ASCII.GetChars(tp, 4, cp, bufferSize);
}

}

#if NETFRAMEWORK
fixed (byte* op = block.outputBuffer)
{
int outputBytes = UnsafeConvert.FromBase64CharArray(tempCharBuffer, 0, nWritten, op + block.outputOffset);

block.outputOffset += outputBytes;
totalOutputBytes += outputBytes;
}
#endif
#if NET5_0_OR_GREATER
if (!Convert.TryFromBase64Chars(tempCharBuffer.AsSpan().Slice(0, nWritten), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes2))
{
throw new FormatException();
}

block.outputOffset += outputBytes2;
totalOutputBytes += outputBytes2;
#endif

// advance startPtr past the block just written
startPtr = tmpPtr;
Expand Down Expand Up @@ -223,15 +244,26 @@ private unsafe int FlushTempBuffer(Block block)
fixed (byte* tp = this.tempByteBuffer)
{
nWritten = ASCII.GetChars(tp, 4, cp, bufferSize);
}

}

#if NETFRAMEWORK
fixed (byte* op = block.outputBuffer)
{
int outputBytes = UnsafeConvert.FromBase64CharArray(tempCharBuffer, 0, nWritten, op + block.outputOffset);

block.outputOffset += outputBytes;
totalOutputBytes += outputBytes;
}
#endif
#if NET5_0_OR_GREATER
if (!Convert.TryFromBase64Chars(tempCharBuffer.AsSpan().Slice(0, nWritten), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes2))
{
throw new FormatException();
}

block.outputOffset += outputBytes2;
totalOutputBytes += outputBytes2;
#endif

// advance offset
int count = (int)(startPtr - (byte*)(inputPtr + block.inputOffset));
Expand Down
14 changes: 8 additions & 6 deletions Base64/UnsafeConvert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
using System.Text;

namespace Base64
{
{
#if NETFRAMEWORK
public static class UnsafeConvert
{
/// <summary>
Expand Down Expand Up @@ -59,12 +60,12 @@ private static unsafe int FromBase64CharPtr(char* inputPtr, int inputLength, byt
// Note that actualResultLength can differ from resultLength if the caller is modifying the array
// as it is being converted. Silently ignore the failure.
// Consider throwing exception in an non in-place release.
}

private static readonly MethodInfo FromBase64_DecodeMethodInfo = typeof(Convert).GetMethod("FromBase64_Decode", BindingFlags.Static | BindingFlags.NonPublic);
}

// no measurable overhead from reflection here - it's not in a tight loop.
// Can we turn this into a func to avoid allocating the args array? Pointers still need to be boxed.
private static readonly MethodInfo FromBase64_DecodeMethodInfo = typeof(Convert).GetMethod("FromBase64_Decode", BindingFlags.Static | BindingFlags.NonPublic);

// no measurable overhead from reflection here - it's not in a tight loop.
// Can we turn this into a func to avoid allocating the args array? Pointers still need to be boxed.
public static unsafe int FromBase64_DecodeReflect(
char* startInputPtr,
int inputLength,
Expand All @@ -87,4 +88,5 @@ public static unsafe int FromBase64_DecodeReflect(
}
}
}
#endif
}