From 00a33640179c8d3b186a0834ee09836e6b47d7f2 Mon Sep 17 00:00:00 2001 From: Wraith Date: Thu, 27 Aug 2020 18:46:04 +0100 Subject: [PATCH] Small spanifications (#667) --- .../src/Microsoft/Data/SqlClient/TdsParser.cs | 40 ++++++----- .../Data/SqlClient/TdsParserStateObject.cs | 70 ++++++------------- 2 files changed, 42 insertions(+), 68 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs index 230509be7f..b0b25d2e09 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -1619,47 +1619,49 @@ internal byte[] SerializeInt(int v, TdsParserStateObject stateObj) { if (null == stateObj._bIntBytes) { - stateObj._bIntBytes = new byte[4]; + stateObj._bIntBytes = new byte[sizeof(int)]; } else { - Debug.Assert(4 == stateObj._bIntBytes.Length); + Debug.Assert(sizeof(int) == stateObj._bIntBytes.Length); } - int current = 0; - byte[] bytes = stateObj._bIntBytes; - bytes[current++] = (byte)(v & 0xff); - bytes[current++] = (byte)((v >> 8) & 0xff); - bytes[current++] = (byte)((v >> 16) & 0xff); - bytes[current++] = (byte)((v >> 24) & 0xff); - return bytes; + WriteInt(stateObj._bIntBytes.AsSpan(), v); + return stateObj._bIntBytes; } - // - // Takes an int and writes it as an int. - // internal void WriteInt(int v, TdsParserStateObject stateObj) { + Span buffer = stackalloc byte[sizeof(int)]; + WriteInt(buffer, v); if ((stateObj._outBytesUsed + 4) > stateObj._outBuff.Length) { // if all of the int doesn't fit into the buffer - for (int shiftValue = 0; shiftValue < sizeof(int) * 8; shiftValue += 8) + for (int index = 0; index < sizeof(int); index++) { - stateObj.WriteByte((byte)((v >> shiftValue) & 0xff)); + stateObj.WriteByte(buffer[index]); } } else { // all of the int fits into the buffer - // NOTE: We don't use a loop here for performance - stateObj._outBuff[stateObj._outBytesUsed] = (byte)(v & 0xff); - stateObj._outBuff[stateObj._outBytesUsed + 1] = (byte)((v >> 8) & 0xff); - stateObj._outBuff[stateObj._outBytesUsed + 2] = (byte)((v >> 16) & 0xff); - stateObj._outBuff[stateObj._outBytesUsed + 3] = (byte)((v >> 24) & 0xff); + buffer.CopyTo(stateObj._outBuff.AsSpan(stateObj._outBytesUsed, sizeof(int))); stateObj._outBytesUsed += 4; } } + internal static void WriteInt(Span buffer, int value) + { +#if netcoreapp + BitConverter.TryWriteBytes(buffer, value); +#else + buffer[0] = (byte)(value & 0xff); + buffer[1] = (byte)((value >> 8) & 0xff); + buffer[2] = (byte)((value >> 16) & 0xff); + buffer[3] = (byte)((value >> 24) & 0xff); +#endif + } + // // Takes a float and writes it as a 32 bit float. // diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs index a5e84c2a6a..7e9f5a6d67 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs @@ -1403,36 +1403,28 @@ internal bool TryReadChar(out char value) { Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); - byte[] buffer; - int offset; + Span buffer = stackalloc byte[2]; if (((_inBytesUsed + 2) > _inBytesRead) || (_inBytesPacket < 2)) { // If the char isn't fully in the buffer, or if it isn't fully in the packet, // then use ReadByteArray since the logic is there to take care of that. - - if (!TryReadByteArray(_bTmp, 2)) + if (!TryReadByteArray(buffer, 2)) { value = '\0'; return false; } - - buffer = _bTmp; - offset = 0; } else { // The entire char is in the packet and in the buffer, so just return it // and take care of the counters. - - buffer = _inBuff; - offset = _inBytesUsed; - + buffer = _inBuff.AsSpan(_inBytesUsed, 2); _inBytesUsed += 2; _inBytesPacket -= 2; } AssertValidState(); - value = (char)((buffer[offset + 1] << 8) + buffer[offset]); + value = (char)((buffer[1] << 8) + buffer[0]); return true; } @@ -1440,70 +1432,58 @@ internal bool TryReadInt16(out short value) { Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); - byte[] buffer; - int offset; + Span buffer = stackalloc byte[2]; if (((_inBytesUsed + 2) > _inBytesRead) || (_inBytesPacket < 2)) { // If the int16 isn't fully in the buffer, or if it isn't fully in the packet, // then use ReadByteArray since the logic is there to take care of that. - - if (!TryReadByteArray(_bTmp, 2)) + if (!TryReadByteArray(buffer, 2)) { value = default; return false; } - - buffer = _bTmp; - offset = 0; } else { // The entire int16 is in the packet and in the buffer, so just return it // and take care of the counters. - - buffer = _inBuff; - offset = _inBytesUsed; - + buffer = _inBuff.AsSpan(_inBytesUsed,2); _inBytesUsed += 2; _inBytesPacket -= 2; } AssertValidState(); - value = (short)((buffer[offset + 1] << 8) + buffer[offset]); + value = (short)((buffer[1] << 8) + buffer[0]); return true; } internal bool TryReadInt32(out int value) { Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); + Span buffer = stackalloc byte[4]; if (((_inBytesUsed + 4) > _inBytesRead) || (_inBytesPacket < 4)) { // If the int isn't fully in the buffer, or if it isn't fully in the packet, // then use ReadByteArray since the logic is there to take care of that. - - if (!TryReadByteArray(_bTmp, 4)) + if (!TryReadByteArray(buffer, 4)) { value = 0; return false; } - - AssertValidState(); - value = BitConverter.ToInt32(_bTmp, 0); - return true; } else { // The entire int is in the packet and in the buffer, so just return it // and take care of the counters. - - value = BitConverter.ToInt32(_inBuff, _inBytesUsed); - + buffer = _inBuff.AsSpan(_inBytesUsed, 4); _inBytesUsed += 4; _inBytesPacket -= 4; - - AssertValidState(); - return true; } + + AssertValidState(); + value = (buffer[3] << 24) + (buffer[2] <<16) + (buffer[1] << 8) + buffer[0]; + return true; + } // This method is safe to call when doing async without snapshot @@ -1559,36 +1539,28 @@ internal bool TryReadUInt16(out ushort value) { Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); - byte[] buffer; - int offset; + Span buffer = stackalloc byte[2]; if (((_inBytesUsed + 2) > _inBytesRead) || (_inBytesPacket < 2)) { // If the uint16 isn't fully in the buffer, or if it isn't fully in the packet, // then use ReadByteArray since the logic is there to take care of that. - - if (!TryReadByteArray(_bTmp, 2)) + if (!TryReadByteArray(buffer, 2)) { value = default; return false; } - - buffer = _bTmp; - offset = 0; } else { // The entire uint16 is in the packet and in the buffer, so just return it // and take care of the counters. - - buffer = _inBuff; - offset = _inBytesUsed; - + buffer = _inBuff.AsSpan(_inBytesUsed, 2); _inBytesUsed += 2; _inBytesPacket -= 2; } AssertValidState(); - value = (ushort)((buffer[offset + 1] << 8) + buffer[offset]); + value = (ushort)((buffer[1] << 8) + buffer[0]); return true; } @@ -3627,8 +3599,8 @@ private void SniWriteStatisticsAndTracing() statistics.RequestNetworkServerTimer(); } } - [Conditional("DEBUG")] + [Conditional("DEBUG")] private void AssertValidState() { if (_inBytesUsed < 0 || _inBytesRead < 0)