From 7bc1a3d77aea11aa2b8a76f0c719c0814f56d8cc Mon Sep 17 00:00:00 2001 From: Alex Peck Date: Fri, 11 Feb 2022 23:35:58 -0800 Subject: [PATCH 1/3] migrate --- Base64/FromBase64Transform.cs | 39 ++++++++++++++++++++++++++++------- Base64/UnsafeConvert.cs | 14 +++++++------ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/Base64/FromBase64Transform.cs b/Base64/FromBase64Transform.cs index b87f376..d7da766 100644 --- a/Base64/FromBase64Transform.cs +++ b/Base64/FromBase64Transform.cs @@ -83,8 +83,9 @@ 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); @@ -92,8 +93,14 @@ public unsafe int TransformBlock(Block block) 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 + Convert.TryFromBase64Chars(tempCharBuffer.AsSpan(), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes); + + 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) @@ -119,8 +126,9 @@ 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); @@ -128,6 +136,13 @@ public unsafe int TransformBlock(Block block) block.outputOffset += outputBytes; totalOutputBytes += outputBytes; } +#endif +#if NET5_0_OR_GREATER + Convert.TryFromBase64Chars(tempCharBuffer.AsSpan(), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes2); + + block.outputOffset += outputBytes2; + totalOutputBytes += outputBytes2; +#endif // advance startPtr past the block just written startPtr = tmpPtr; @@ -223,8 +238,9 @@ 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); @@ -232,6 +248,13 @@ private unsafe int FlushTempBuffer(Block block) block.outputOffset += outputBytes; totalOutputBytes += outputBytes; } +#endif +#if NET5_0_OR_GREATER + Convert.TryFromBase64Chars(tempCharBuffer.AsSpan(), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes2); + + block.outputOffset += outputBytes2; + totalOutputBytes += outputBytes2; +#endif // advance offset int count = (int)(startPtr - (byte*)(inputPtr + block.inputOffset)); diff --git a/Base64/UnsafeConvert.cs b/Base64/UnsafeConvert.cs index d398dd2..50759b8 100644 --- a/Base64/UnsafeConvert.cs +++ b/Base64/UnsafeConvert.cs @@ -6,7 +6,8 @@ using System.Text; namespace Base64 -{ +{ +#if NETFRAMEWORK public static class UnsafeConvert { /// @@ -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, @@ -87,4 +88,5 @@ public static unsafe int FromBase64_DecodeReflect( } } } +#endif } From a8e4cc54f6daab872b849f469f5158725adcafd4 Mon Sep 17 00:00:00 2001 From: Alex Peck Date: Fri, 11 Feb 2022 23:41:47 -0800 Subject: [PATCH 2/3] slice input --- Base64/FromBase64Transform.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Base64/FromBase64Transform.cs b/Base64/FromBase64Transform.cs index d7da766..495cdc8 100644 --- a/Base64/FromBase64Transform.cs +++ b/Base64/FromBase64Transform.cs @@ -95,7 +95,7 @@ public unsafe int TransformBlock(Block block) } #endif #if NET5_0_OR_GREATER - Convert.TryFromBase64Chars(tempCharBuffer.AsSpan(), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes); + Convert.TryFromBase64Chars(tempCharBuffer.AsSpan().Slice(0, nWritten), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes); block.outputOffset += outputBytes; totalOutputBytes += outputBytes; @@ -138,7 +138,7 @@ public unsafe int TransformBlock(Block block) } #endif #if NET5_0_OR_GREATER - Convert.TryFromBase64Chars(tempCharBuffer.AsSpan(), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes2); + Convert.TryFromBase64Chars(tempCharBuffer.AsSpan().Slice(0, nWritten), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes2); block.outputOffset += outputBytes2; totalOutputBytes += outputBytes2; @@ -250,7 +250,7 @@ private unsafe int FlushTempBuffer(Block block) } #endif #if NET5_0_OR_GREATER - Convert.TryFromBase64Chars(tempCharBuffer.AsSpan(), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes2); + Convert.TryFromBase64Chars(tempCharBuffer.AsSpan().Slice(0, nWritten), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes2); block.outputOffset += outputBytes2; totalOutputBytes += outputBytes2; From 73bcc706a7cb9a38cc43221d3d314107d344ed96 Mon Sep 17 00:00:00 2001 From: Alex Peck Date: Fri, 11 Feb 2022 23:44:13 -0800 Subject: [PATCH 3/3] pass --- Base64/FromBase64Transform.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Base64/FromBase64Transform.cs b/Base64/FromBase64Transform.cs index 495cdc8..a2c4813 100644 --- a/Base64/FromBase64Transform.cs +++ b/Base64/FromBase64Transform.cs @@ -95,7 +95,10 @@ public unsafe int TransformBlock(Block block) } #endif #if NET5_0_OR_GREATER - Convert.TryFromBase64Chars(tempCharBuffer.AsSpan().Slice(0, nWritten), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes); + 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; @@ -138,7 +141,10 @@ public unsafe int TransformBlock(Block block) } #endif #if NET5_0_OR_GREATER - Convert.TryFromBase64Chars(tempCharBuffer.AsSpan().Slice(0, nWritten), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes2); + 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; @@ -250,7 +256,10 @@ private unsafe int FlushTempBuffer(Block block) } #endif #if NET5_0_OR_GREATER - Convert.TryFromBase64Chars(tempCharBuffer.AsSpan().Slice(0, nWritten), block.outputBuffer.AsSpan().Slice(block.outputOffset), out int outputBytes2); + 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;