From ca24841d2e00c51a0a52df522139fcb096e0995f Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 27 Feb 2023 20:00:46 +0700 Subject: Use string.Create when available --- crypto/src/asn1/Asn1InputStream.cs | 128 +++++++++++++++++++---------- crypto/src/asn1/DerBMPString.cs | 23 ++++++ crypto/src/math/ec/abc/SimpleBigDecimal.cs | 9 +- crypto/src/openpgp/SXprUtilities.cs | 10 +++ crypto/src/util/Strings.cs | 10 +++ 5 files changed, 131 insertions(+), 49 deletions(-) diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs index 0e772010f..b09322234 100644 --- a/crypto/src/asn1/Asn1InputStream.cs +++ b/crypto/src/asn1/Asn1InputStream.cs @@ -359,56 +359,13 @@ namespace Org.BouncyCastle.Asn1 return buf; } - private static char[] GetBmpCharBuffer(DefiniteLengthInputStream defIn) - { - int remainingBytes = defIn.Remaining; - if (0 != (remainingBytes & 1)) - throw new IOException("malformed BMPString encoding encountered"); - - char[] str = new char[remainingBytes / 2]; - int stringPos = 0; - - byte[] buf = new byte[8]; - while (remainingBytes >= 8) - { - if (Streams.ReadFully(defIn, buf, 0, 8) != 8) - throw new EndOfStreamException("EOF encountered in middle of BMPString"); - - str[stringPos ] = (char)((buf[0] << 8) | (buf[1] & 0xFF)); - str[stringPos + 1] = (char)((buf[2] << 8) | (buf[3] & 0xFF)); - str[stringPos + 2] = (char)((buf[4] << 8) | (buf[5] & 0xFF)); - str[stringPos + 3] = (char)((buf[6] << 8) | (buf[7] & 0xFF)); - stringPos += 4; - remainingBytes -= 8; - } - if (remainingBytes > 0) - { - if (Streams.ReadFully(defIn, buf, 0, remainingBytes) != remainingBytes) - throw new EndOfStreamException("EOF encountered in middle of BMPString"); - - int bufPos = 0; - do - { - int b1 = buf[bufPos++] << 8; - int b2 = buf[bufPos++] & 0xFF; - str[stringPos++] = (char)(b1 | b2); - } - while (bufPos < remainingBytes); - } - - if (0 != defIn.Remaining || str.Length != stringPos) - throw new InvalidOperationException(); - - return str; - } - internal static Asn1Object CreatePrimitiveDerObject(int tagNo, DefiniteLengthInputStream defIn, byte[][] tmpBuffers) { switch (tagNo) { case Asn1Tags.BmpString: - return DerBmpString.CreatePrimitive(GetBmpCharBuffer(defIn)); + return CreateDerBmpString(defIn); case Asn1Tags.Boolean: return DerBoolean.CreatePrimitive(GetBuffer(defIn, tmpBuffers)); case Asn1Tags.Enumerated: @@ -463,5 +420,88 @@ namespace Org.BouncyCastle.Asn1 throw new IOException("unknown tag " + tagNo + " encountered"); } } + + private static DerBmpString CreateDerBmpString(DefiniteLengthInputStream defIn) + { + int remainingBytes = defIn.Remaining; + if (0 != (remainingBytes & 1)) + throw new IOException("malformed BMPString encoding encountered"); + + int length = remainingBytes / 2; + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return DerBmpString.CreatePrimitive(length, defIn, (str, defIn) => + { + int stringPos = 0; + + Span buf = stackalloc byte[8]; + while (remainingBytes >= 8) + { + if (Streams.ReadFully(defIn, buf) != 8) + throw new EndOfStreamException("EOF encountered in middle of BMPString"); + + str[stringPos ] = (char)((buf[0] << 8) | (buf[1] & 0xFF)); + str[stringPos + 1] = (char)((buf[2] << 8) | (buf[3] & 0xFF)); + str[stringPos + 2] = (char)((buf[4] << 8) | (buf[5] & 0xFF)); + str[stringPos + 3] = (char)((buf[6] << 8) | (buf[7] & 0xFF)); + stringPos += 4; + remainingBytes -= 8; + } + if (remainingBytes > 0) + { + if (Streams.ReadFully(defIn, buf) != remainingBytes) + throw new EndOfStreamException("EOF encountered in middle of BMPString"); + + int bufPos = 0; + do + { + int b1 = buf[bufPos++] << 8; + int b2 = buf[bufPos++] & 0xFF; + str[stringPos++] = (char)(b1 | b2); + } + while (bufPos < remainingBytes); + } + + if (0 != defIn.Remaining || str.Length != stringPos) + throw new InvalidOperationException(); + }); +#else + char[] str = new char[length]; + int stringPos = 0; + + byte[] buf = new byte[8]; + while (remainingBytes >= 8) + { + if (Streams.ReadFully(defIn, buf, 0, 8) != 8) + throw new EndOfStreamException("EOF encountered in middle of BMPString"); + + str[stringPos ] = (char)((buf[0] << 8) | (buf[1] & 0xFF)); + str[stringPos + 1] = (char)((buf[2] << 8) | (buf[3] & 0xFF)); + str[stringPos + 2] = (char)((buf[4] << 8) | (buf[5] & 0xFF)); + str[stringPos + 3] = (char)((buf[6] << 8) | (buf[7] & 0xFF)); + stringPos += 4; + remainingBytes -= 8; + } + if (remainingBytes > 0) + { + if (Streams.ReadFully(defIn, buf, 0, remainingBytes) != remainingBytes) + throw new EndOfStreamException("EOF encountered in middle of BMPString"); + + int bufPos = 0; + do + { + int b1 = buf[bufPos++] << 8; + int b2 = buf[bufPos++] & 0xFF; + str[stringPos++] = (char)(b1 | b2); + } + while (bufPos < remainingBytes); + } + + if (0 != defIn.Remaining || str.Length != stringPos) + throw new InvalidOperationException(); + + return DerBmpString.CreatePrimitive(str); +#endif + } } } diff --git a/crypto/src/asn1/DerBMPString.cs b/crypto/src/asn1/DerBMPString.cs index 284a4b830..bf21fa424 100644 --- a/crypto/src/asn1/DerBMPString.cs +++ b/crypto/src/asn1/DerBMPString.cs @@ -1,4 +1,7 @@ using System; +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER +using System.Buffers; +#endif using System.IO; using Org.BouncyCastle.Utilities; @@ -82,6 +85,16 @@ namespace Org.BouncyCastle.Asn1 throw new ArgumentException("malformed BMPString encoding encountered", "contents"); int charLen = byteLen / 2; + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + m_str = string.Create(charLen, contents, (chars, bytes) => + { + for (int i = 0; i < chars.Length; ++i) + { + chars[i] = (char)((bytes[2 * i] << 8) | (bytes[2 * i + 1] & 0xff)); + } + }); +#else char[] cs = new char[charLen]; for (int i = 0; i != charLen; i++) @@ -90,8 +103,10 @@ namespace Org.BouncyCastle.Asn1 } m_str = new string(cs); +#endif } +#if !(NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER) internal DerBmpString(char[] str) { if (str == null) @@ -99,6 +114,7 @@ namespace Org.BouncyCastle.Asn1 m_str = new string(str); } +#endif /** * basic constructor @@ -157,10 +173,17 @@ namespace Org.BouncyCastle.Asn1 return new DerBmpString(contents); } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + internal static DerBmpString CreatePrimitive(int length, TState state, SpanAction action) + { + return new DerBmpString(string.Create(length, state, action)); + } +#else internal static DerBmpString CreatePrimitive(char[] str) { // TODO[asn1] Asn1InputStream has a validator/converter that should be unified in this class somehow return new DerBmpString(str); } +#endif } } diff --git a/crypto/src/math/ec/abc/SimpleBigDecimal.cs b/crypto/src/math/ec/abc/SimpleBigDecimal.cs index d5664dbfd..c69d02f0c 100644 --- a/crypto/src/math/ec/abc/SimpleBigDecimal.cs +++ b/crypto/src/math/ec/abc/SimpleBigDecimal.cs @@ -196,19 +196,18 @@ namespace Org.BouncyCastle.Math.EC.Abc } string leftOfPoint = floorBigInt.ToString(); - char[] fractCharArr = new char[scale]; - string fractStr = fract.ToString(2); + char[] rightOfPoint = new char[scale]; + string fractStr = fract.ToString(2); int fractLen = fractStr.Length; int zeroes = scale - fractLen; for (int i = 0; i < zeroes; i++) { - fractCharArr[i] = '0'; + rightOfPoint[i] = '0'; } for (int j = 0; j < fractLen; j++) { - fractCharArr[zeroes + j] = fractStr[j]; + rightOfPoint[zeroes + j] = fractStr[j]; } - string rightOfPoint = new string(fractCharArr); StringBuilder sb = new StringBuilder(leftOfPoint); sb.Append("."); diff --git a/crypto/src/openpgp/SXprUtilities.cs b/crypto/src/openpgp/SXprUtilities.cs index d7969813f..835d3c347 100644 --- a/crypto/src/openpgp/SXprUtilities.cs +++ b/crypto/src/openpgp/SXprUtilities.cs @@ -34,6 +34,15 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp { int len = ReadLength(input, ch); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return string.Create(len, input, (chars, input) => + { + for (int i = 0; i < chars.Length; ++i) + { + chars[i] = Convert.ToChar(input.ReadByte()); + } + }); +#else char[] chars = new char[len]; for (int i = 0; i != chars.Length; i++) @@ -42,6 +51,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp } return new string(chars); +#endif } internal static byte[] ReadBytes(Stream input, int ch) diff --git a/crypto/src/util/Strings.cs b/crypto/src/util/Strings.cs index b1a63a3a1..147b6d349 100644 --- a/crypto/src/util/Strings.cs +++ b/crypto/src/util/Strings.cs @@ -18,12 +18,22 @@ namespace Org.BouncyCastle.Utilities public static string FromByteArray(byte[] bs) { +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return string.Create(bs.Length, bs, (chars, bytes) => + { + for (int i = 0; i < chars.Length; ++i) + { + chars[i] = Convert.ToChar(bytes[i]); + } + }); +#else char[] cs = new char[bs.Length]; for (int i = 0; i < cs.Length; ++i) { cs[i] = Convert.ToChar(bs[i]); } return new string(cs); +#endif } public static byte[] ToByteArray(char[] cs) -- cgit 1.4.1