Skip to content

Commit 6db45d4

Browse files
authored
Add and use TryReadChars method (#1544)
1 parent 5ff68eb commit 6db45d4

File tree

4 files changed

+62
-20
lines changed

4 files changed

+62
-20
lines changed

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12501,18 +12501,18 @@ private bool TryReadPlpUnicodeCharsChunk(char[] buff, int offst, int len, TdsPar
1250112501
return true;
1250212502
}
1250312503

12504-
charsRead = len;
12504+
int charsToRead = len;
1250512505

1250612506
// stateObj._longlenleft is in bytes
12507-
if ((stateObj._longlenleft >> 1) < (ulong)len)
12508-
charsRead = (int)(stateObj._longlenleft >> 1);
12507+
if ((stateObj._longlenleft / 2) < (ulong)len)
12508+
{
12509+
charsToRead = (int)(stateObj._longlenleft >> 1);
12510+
}
1250912511

12510-
for (int ii = 0; ii < charsRead; ii++)
12512+
if (!stateObj.TryReadChars(buff, offst, charsToRead, out charsRead))
1251112513
{
12512-
if (!stateObj.TryReadChar(out buff[offst + ii]))
12513-
{
12514-
return false;
12515-
}
12514+
charsRead = 0;
12515+
return false;
1251612516
}
1251712517

1251812518
stateObj._longlenleft -= ((ulong)charsRead << 1);

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6-
using System.Collections.Generic;
76
using System.Diagnostics;
8-
using System.Linq;
97
using System.Runtime.InteropServices;
108
using System.Security;
11-
using System.Text;
129
using System.Threading;
1310
using System.Threading.Tasks;
1411
using Microsoft.Data.Common;
@@ -487,6 +484,7 @@ internal bool TryReadChar(out char value)
487484

488485
AssertValidState();
489486
value = (char)((buffer[1] << 8) + buffer[0]);
487+
490488
return true;
491489
}
492490

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13528,7 +13528,6 @@ internal void WriteParameterVarLen(MetaType type, int size, bool isNull, TdsPars
1352813528
// Returns the actual chars read
1352913529
private bool TryReadPlpUnicodeCharsChunk(char[] buff, int offst, int len, TdsParserStateObject stateObj, out int charsRead)
1353013530
{
13531-
1353213531
Debug.Assert((buff == null && len == 0) || (buff.Length >= offst + len), "Invalid length sent to ReadPlpUnicodeChars()!");
1353313532
Debug.Assert((stateObj._longlen != 0) && (stateObj._longlen != TdsEnums.SQL_PLP_NULL),
1353413533
"Out of sync plp read request");
@@ -13539,18 +13538,18 @@ private bool TryReadPlpUnicodeCharsChunk(char[] buff, int offst, int len, TdsPar
1353913538
return true;
1354013539
}
1354113540

13542-
charsRead = len;
13541+
int charsToRead = len;
1354313542

1354413543
// stateObj._longlenleft is in bytes
13545-
if ((stateObj._longlenleft >> 1) < (ulong)len)
13546-
charsRead = (int)(stateObj._longlenleft >> 1);
13544+
if ((stateObj._longlenleft / 2) < (ulong)len)
13545+
{
13546+
charsToRead = (int)(stateObj._longlenleft >> 1);
13547+
}
1354713548

13548-
for (int ii = 0; ii < charsRead; ii++)
13549+
if (!stateObj.TryReadChars(buff, offst, charsToRead, out charsRead))
1354913550
{
13550-
if (!stateObj.TryReadChar(out buff[offst + ii]))
13551-
{
13552-
return false;
13553-
}
13551+
charsRead = 0;
13552+
return false;
1355413553
}
1355513554

1355613555
stateObj._longlenleft -= ((ulong)charsRead << 1);

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,51 @@ internal bool TryStartNewRow(bool isNullCompressed, int nullBitmapColumnsCount =
436436
return true;
437437
}
438438

439+
internal bool TryReadChars(char[] chars, int charsOffset, int charsCount, out int charsCopied)
440+
{
441+
charsCopied = 0;
442+
while (charsCopied < charsCount)
443+
{
444+
// check if the current buffer contains some bytes we need to copy and copy them
445+
// in a block
446+
int bytesToRead = Math.Min(
447+
(charsCount - charsCopied) * 2,
448+
unchecked((_inBytesRead - _inBytesUsed) & (int)0xFFFFFFFE) // it the result is odd take off the 0 to make it even
449+
);
450+
if (bytesToRead > 0)
451+
{
452+
Buffer.BlockCopy(
453+
_inBuff,
454+
_inBytesUsed,
455+
chars,
456+
(charsOffset + charsCopied) * 2, // offset in bytes,
457+
bytesToRead
458+
);
459+
charsCopied += (bytesToRead / 2);
460+
_inBytesUsed += bytesToRead;
461+
_inBytesPacket -= bytesToRead;
462+
}
463+
464+
// if the number of chars requested is lower than the number copied then we need
465+
// to request a new packet, use TryReadChar() to do this then loop back to see
466+
// if we can copy another bulk of chars from the new buffer
467+
468+
if (charsCopied < charsCount)
469+
{
470+
bool result = TryReadChar(out chars[charsOffset + charsCopied]);
471+
if (result)
472+
{
473+
charsCopied += 1;
474+
}
475+
else
476+
{
477+
return false;
478+
}
479+
}
480+
}
481+
return true;
482+
}
483+
439484
internal bool IsRowTokenReady()
440485
{
441486
// Removing one byte since TryReadByteArray\TryReadByte will aggressively read the next packet if there is no data left - so we need to ensure there is a spare byte

0 commit comments

Comments
 (0)