@@ -6780,7 +6780,7 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt
67806780
67816781 // Now read the 4 next integers which contain the actual value.
67826782 length = checked((int)length - 1);
6783- int[] bits = new int[4];
6783+ Span< int> bits = stackalloc int[4];
67846784 int decLength = length >> 2;
67856785 ReadOnlySpan<byte> span = unencryptedBytes.AsSpan();
67866786 for (int i = 0; i < decLength; i++)
@@ -7700,8 +7700,15 @@ internal Task WriteSqlVariantValue(object value, int length, int offset, TdsPars
77007700
77017701 case TdsEnums.SQLNUMERICN:
77027702 {
7703+ #if NET
7704+ Span<int> decimalBits = stackalloc int[4];
7705+ decimal.GetBits((decimal)value, decimalBits);
7706+ #else
7707+ int[] decimalBits = decimal.GetBits((decimal)value);
7708+ #endif
7709+
77037710 stateObj.WriteByte(mt.Precision); //propbytes: precision
7704- stateObj.WriteByte((byte)((decimal.GetBits((decimal)value) [3] & 0x00ff0000) >> 0x10)); // propbytes: scale
7711+ stateObj.WriteByte((byte)((decimalBits [3] & 0x00ff0000) >> 0x10)); // propbytes: scale
77057712 WriteDecimal((decimal)value, stateObj);
77067713 break;
77077714 }
@@ -7862,9 +7869,15 @@ internal Task WriteSqlVariantDataRowValue(object value, TdsParserStateObject sta
78627869
78637870 case TdsEnums.SQLNUMERICN:
78647871 {
7872+ #if NET
7873+ Span<int> decimalBits = stackalloc int[4];
7874+ decimal.GetBits((decimal)value, decimalBits);
7875+ #else
7876+ int[] decimalBits = decimal.GetBits((decimal)value);
7877+ #endif
78657878 WriteSqlVariantHeader(21, metatype.TDSType, metatype.PropBytes, stateObj);
78667879 stateObj.WriteByte(metatype.Precision); //propbytes: precision
7867- stateObj.WriteByte((byte)((decimal.GetBits((decimal)value) [3] & 0x00ff0000) >> 0x10)); // propbytes: scale
7880+ stateObj.WriteByte((byte)((decimalBits [3] & 0x00ff0000) >> 0x10)); // propbytes: scale
78687881 WriteDecimal((decimal)value, stateObj);
78697882 break;
78707883 }
@@ -7921,7 +7934,12 @@ private byte[] SerializeSqlMoney(SqlMoney value, int length, TdsParserStateObjec
79217934 private void WriteSqlMoney(SqlMoney value, int length, TdsParserStateObject stateObj)
79227935 {
79237936 // UNDONE: can I use SqlMoney.ToInt64()?
7937+ #if NET
7938+ Span<int> bits = stackalloc int[4];
7939+ decimal.GetBits(value.Value, bits);
7940+ #else
79247941 int[] bits = decimal.GetBits(value.Value);
7942+ #endif
79257943
79267944 // this decimal should be scaled by 10000 (regardless of what the incoming decimal was scaled by)
79277945 bool isNeg = (0 != (bits[3] & unchecked((int)0x80000000)));
@@ -7954,7 +7972,12 @@ private void WriteSqlMoney(SqlMoney value, int length, TdsParserStateObject stat
79547972 private byte[] SerializeCurrency(Decimal value, int length, TdsParserStateObject stateObj)
79557973 {
79567974 SqlMoney m = new SqlMoney(value);
7957- int[] bits = Decimal.GetBits(m.Value);
7975+ #if NET
7976+ Span<int> bits = stackalloc int[4];
7977+ decimal.GetBits(m.Value, bits);
7978+ #else
7979+ int[] bits = decimal.GetBits(m.Value);
7980+ #endif
79587981
79597982 // this decimal should be scaled by 10000 (regardless of what the incoming decimal was scaled by)
79607983 bool isNeg = (0 != (bits[3] & unchecked((int)0x80000000)));
@@ -7999,7 +8022,12 @@ private byte[] SerializeCurrency(Decimal value, int length, TdsParserStateObject
79998022 private void WriteCurrency(decimal value, int length, TdsParserStateObject stateObj)
80008023 {
80018024 SqlMoney m = new SqlMoney(value);
8025+ #if NET
8026+ Span<int> bits = stackalloc int[4];
8027+ decimal.GetBits(m.Value, bits);
8028+ #else
80028029 int[] bits = decimal.GetBits(m.Value);
8030+ #endif
80038031
80048032 // this decimal should be scaled by 10000 (regardless of what the incoming decimal was scaled by)
80058033 bool isNeg = (0 != (bits[3] & unchecked((int)0x80000000)));
@@ -8136,8 +8164,8 @@ private TdsOperationStatus TryReadSqlDecimal(SqlBuffer value, int length, byte p
81368164
81378165 length = checked((int)length - 1);
81388166
8139- int[] bits;
8140- result = TryReadDecimalBits(length, stateObj, out bits);
8167+ Span< int> bits = stackalloc int[4] ;
8168+ result = TryReadDecimalBits(length, stateObj, bits);
81418169 if (result != TdsOperationStatus.Done)
81428170 {
81438171 return result;
@@ -8149,31 +8177,16 @@ private TdsOperationStatus TryReadSqlDecimal(SqlBuffer value, int length, byte p
81498177
81508178 // @devnote: length should be size of decimal without the sign
81518179 // @devnote: sign should have already been read off the wire
8152- private TdsOperationStatus TryReadDecimalBits(int length, TdsParserStateObject stateObj, out int[] bits)
8180+ private TdsOperationStatus TryReadDecimalBits(int length, TdsParserStateObject stateObj, Span< int> bits)
81538181 {
8154- bits = stateObj._decimalBits; // used alloc'd array if we have one already
8155- int i;
8156-
8157- if (bits == null)
8158- {
8159- bits = new int[4];
8160- stateObj._decimalBits = bits;
8161- }
8162- else
8163- {
8164- for (i = 0; i < bits.Length; i++)
8165- {
8166- bits[i] = 0;
8167- }
8168- }
8169-
8182+ Debug.Assert(bits.Length == 4);
81708183 Debug.Assert((length > 0) &&
81718184 (length <= TdsEnums.MAX_NUMERIC_LEN - 1) &&
81728185 (length % 4 == 0), "decimal should have 4, 8, 12, or 16 bytes of data");
81738186
81748187 int decLength = length >> 2;
81758188
8176- for (i = 0; i < decLength; i++)
8189+ for (int i = 0; i < decLength; i++)
81778190 {
81788191 // up to 16 bytes of data following the sign byte
81798192 TdsOperationStatus result = stateObj.TryReadInt32(out bits[i]);
@@ -8199,7 +8212,13 @@ internal static SqlDecimal AdjustSqlDecimalScale(SqlDecimal d, int newScale)
81998212
82008213 internal static decimal AdjustDecimalScale(decimal value, int newScale)
82018214 {
8202- int oldScale = (decimal.GetBits(value)[3] & 0x00ff0000) >> 0x10;
8215+ #if NET
8216+ Span<int> decimalBits = stackalloc int[4];
8217+ decimal.GetBits(value, decimalBits);
8218+ #else
8219+ int[] decimalBits = decimal.GetBits(value);
8220+ #endif
8221+ int oldScale = (decimalBits[3] & 0x00ff0000) >> 0x10;
82038222
82048223 if (newScale != oldScale)
82058224 {
@@ -8281,7 +8300,12 @@ internal void WriteSqlDecimal(SqlDecimal d, TdsParserStateObject stateObj)
82818300
82828301 private byte[] SerializeDecimal(decimal value, TdsParserStateObject stateObj)
82838302 {
8284- int[] decimalBits = Decimal.GetBits(value);
8303+ #if NET
8304+ Span<int> decimalBits = stackalloc int[4];
8305+ decimal.GetBits(value, decimalBits);
8306+ #else
8307+ int[] decimalBits = decimal.GetBits(value);
8308+ #endif
82858309 if (stateObj._bDecimalBytes == null)
82868310 {
82878311 stateObj._bDecimalBytes = new byte[17];
@@ -8336,8 +8360,12 @@ struct {
83368360
83378361 private void WriteDecimal(decimal value, TdsParserStateObject stateObj)
83388362 {
8339- stateObj._decimalBits = decimal.GetBits(value);
8340- Debug.Assert(stateObj._decimalBits != null, "decimalBits should be filled in at TdsExecuteRPC time");
8363+ #if NET
8364+ Span<int> decimalBits = stackalloc int[4];
8365+ decimal.GetBits(value, decimalBits);
8366+ #else
8367+ int[] decimalBits = decimal.GetBits(value);
8368+ #endif
83418369
83428370 /*
83438371 Returns a binary representation of a Decimal. The return value is an integer
@@ -8359,7 +8387,7 @@ struct {
83598387 */
83608388
83618389 // write the sign (note that COM and SQL are opposite)
8362- if (0x80000000 == (stateObj._decimalBits [3] & 0x80000000))
8390+ if ((decimalBits [3] & 0x80000000) == 0x80000000 )
83638391 {
83648392 stateObj.WriteByte(0);
83658393 }
@@ -8368,9 +8396,9 @@ struct {
83688396 stateObj.WriteByte(1);
83698397 }
83708398
8371- WriteInt(stateObj._decimalBits [0], stateObj);
8372- WriteInt(stateObj._decimalBits [1], stateObj);
8373- WriteInt(stateObj._decimalBits [2], stateObj);
8399+ WriteInt(decimalBits [0], stateObj);
8400+ WriteInt(decimalBits [1], stateObj);
8401+ WriteInt(decimalBits [2], stateObj);
83748402 WriteInt(0, stateObj);
83758403 }
83768404
0 commit comments