[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / referencesource / System.Data / System / Data / SQLTypes / SQLBinary.cs
blobe9df08a601d4877affb4367df12b0a84e8aa1eca
1 //------------------------------------------------------------------------------
2 // <copyright file="SQLBinary.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">junfang</owner>
6 // <owner current="true" primary="false">Microsoft</owner>
7 // <owner current="true" primary="false">Microsoft</owner>
8 //------------------------------------------------------------------------------
10 //**************************************************************************
11 // @File: SqlBinary.cs
13 // Create by: JunFang
15 // Purpose: Implementation of SqlBinary which is corresponding to
16 // data type "binary/varbinary" in SQL Server
18 // Notes:
19 //
20 // History:
22 // 1/30/2000 JunFang Created and implemented as first drop.
24 // @EndHeader@
25 //**************************************************************************
27 using System;
28 using System.Data.Common;
29 using System.Globalization;
30 using System.Xml;
31 using System.Xml.Schema;
32 using System.Xml.Serialization;
34 namespace System.Data.SqlTypes {
36 [Serializable]
37 [XmlSchemaProvider("GetXsdType")]
38 public struct SqlBinary : INullable, IComparable, IXmlSerializable {
39 private byte[] m_value; // null if m_value is null
41 // constructor
42 // construct a Null
43 private SqlBinary(bool fNull) {
44 m_value = null;
47 /// <devdoc>
48 /// <para>
49 /// Initializes a new instance of the <see cref='System.Data.SqlTypes.SqlBinary'/> class with a binary object to be stored.
50 /// </para>
51 /// </devdoc>
52 public SqlBinary(byte[] value) {
53 // if value is null, this generates a SqlBinary.Null
54 if (value == null)
55 m_value = null;
56 else {
57 m_value = new byte[value.Length];
58 value.CopyTo(m_value, 0);
62 /// <devdoc>
63 /// <para>
64 /// Initializes a new instance of the <see cref='System.Data.SqlTypes.SqlBinary'/> class with a binary object to be stored. This constructor will not copy the value.
65 /// </para>
66 /// </devdoc>
67 internal SqlBinary(byte[] value, bool ignored) {
68 // if value is null, this generates a SqlBinary.Null
69 if (value == null)
70 m_value = null;
71 else {
72 m_value = value;
76 // INullable
77 /// <devdoc>
78 /// <para>
79 /// Gets whether or not <see cref='System.Data.SqlTypes.SqlBinary.Value'/> is null.
80 /// </para>
81 /// </devdoc>
82 public bool IsNull {
83 get { return(m_value == null);}
86 // property: Value
87 /// <devdoc>
88 /// <para>
89 /// Gets
90 /// or sets the
91 /// value of the SQL binary object retrieved.
92 /// </para>
93 /// </devdoc>
94 public byte[] Value {
95 get {
96 if (IsNull)
97 throw new SqlNullValueException();
98 else {
99 byte[] value = new byte[m_value.Length];
100 m_value.CopyTo(value, 0);
101 return value;
106 // class indexer
107 public byte this[int index] {
108 get {
109 if (IsNull)
110 throw new SqlNullValueException();
111 else
112 return m_value[index];
116 // property: Length
117 /// <devdoc>
118 /// <para>
119 /// Gets the length in bytes of <see cref='System.Data.SqlTypes.SqlBinary.Value'/>.
120 /// </para>
121 /// </devdoc>
122 public int Length {
123 get {
124 if (!IsNull)
125 return m_value.Length;
126 else
127 throw new SqlNullValueException();
131 // Implicit conversion from byte[] to SqlBinary
132 // Alternative: constructor SqlBinary(bytep[])
133 /// <devdoc>
134 /// <para>
135 /// Converts a binary object to a <see cref='System.Data.SqlTypes.SqlBinary'/>.
136 /// </para>
137 /// </devdoc>
138 public static implicit operator SqlBinary(byte[] x) {
139 return new SqlBinary(x);
142 // Explicit conversion from SqlBinary to byte[]. Throw exception if x is Null.
143 // Alternative: Value property
144 /// <devdoc>
145 /// <para>
146 /// Converts a <see cref='System.Data.SqlTypes.SqlBinary'/> to a binary object.
147 /// </para>
148 /// </devdoc>
149 public static explicit operator byte[](SqlBinary x) {
150 return x.Value;
153 /// <devdoc>
154 /// <para>
155 /// Returns a string describing a <see cref='System.Data.SqlTypes.SqlBinary'/> object.
156 /// </para>
157 /// </devdoc>
158 public override String ToString() {
159 return IsNull ? SQLResource.NullString : "SqlBinary(" + m_value.Length.ToString(CultureInfo.InvariantCulture) + ")";
163 // Unary operators
165 // Binary operators
167 // Arithmetic operators
168 /// <devdoc>
169 /// <para>
170 /// Adds two instances of <see cref='System.Data.SqlTypes.SqlBinary'/> together.
171 /// </para>
172 /// </devdoc>
173 // Alternative method: SqlBinary.Concat
174 public static SqlBinary operator +(SqlBinary x, SqlBinary y) {
175 if (x.IsNull || y.IsNull)
176 return Null;
178 byte[] rgbResult = new byte[x.Value.Length + y.Value.Length];
179 x.Value.CopyTo(rgbResult, 0);
180 y.Value.CopyTo(rgbResult, x.Value.Length);
182 return new SqlBinary(rgbResult);
186 // Comparisons
188 private static EComparison PerformCompareByte(byte[] x, byte[] y) {
189 // the smaller length of two arrays
190 int len = (x.Length < y.Length) ? x.Length : y.Length;
191 int i;
193 for (i = 0; i < len; ++i) {
194 if (x[i] != y[i]) {
195 if (x[i] < y[i])
196 return EComparison.LT;
197 else
198 return EComparison.GT;
202 if (x.Length == y.Length)
203 return EComparison.EQ;
204 else {
205 // if the remaining bytes are all zeroes, they are still equal.
207 byte bZero = (byte)0;
209 if (x.Length < y.Length) {
210 // array X is shorter
211 for (i = len; i < y.Length; ++i) {
212 if (y[i] != bZero)
213 return EComparison.LT;
216 else {
217 // array Y is shorter
218 for (i = len; i < x.Length; ++i) {
219 if (x[i] != bZero)
220 return EComparison.GT;
224 return EComparison.EQ;
229 // Implicit conversions
231 // Explicit conversions
233 // Explicit conversion from SqlGuid to SqlBinary
234 /// <devdoc>
235 /// <para>
236 /// Converts a <see cref='System.Data.SqlTypes.SqlGuid'/> to a <see cref='System.Data.SqlTypes.SqlBinary'/>
237 /// .
238 /// </para>
239 /// </devdoc>
240 // Alternative method: SqlGuid.ToSqlBinary
241 public static explicit operator SqlBinary(SqlGuid x) {
242 return x.IsNull ? SqlBinary.Null : new SqlBinary(x.ToByteArray());
245 // Builtin functions
247 // Overloading comparison operators
248 /// <devdoc>
249 /// <para>
250 /// Compares two instances of <see cref='System.Data.SqlTypes.SqlBinary'/> for
251 /// equality.
252 /// </para>
253 /// </devdoc>
254 public static SqlBoolean operator==(SqlBinary x, SqlBinary y) {
255 if (x.IsNull || y.IsNull)
256 return SqlBoolean.Null;
258 return new SqlBoolean(PerformCompareByte(x.Value, y.Value) == EComparison.EQ);
261 /// <devdoc>
262 /// <para>
263 /// Compares two instances of <see cref='System.Data.SqlTypes.SqlBinary'/>
264 /// for equality.
265 /// </para>
266 /// </devdoc>
267 public static SqlBoolean operator!=(SqlBinary x, SqlBinary y) {
268 return ! (x == y);
271 /// <devdoc>
272 /// <para>
273 /// Compares the first <see cref='System.Data.SqlTypes.SqlBinary'/> for being less than the
274 /// second <see cref='System.Data.SqlTypes.SqlBinary'/>.
275 /// </para>
276 /// </devdoc>
277 public static SqlBoolean operator<(SqlBinary x, SqlBinary y) {
278 if (x.IsNull || y.IsNull)
279 return SqlBoolean.Null;
281 return new SqlBoolean(PerformCompareByte(x.Value, y.Value) == EComparison.LT);
284 /// <devdoc>
285 /// <para>
286 /// Compares the first <see cref='System.Data.SqlTypes.SqlBinary'/> for being greater than the second <see cref='System.Data.SqlTypes.SqlBinary'/>.
287 /// </para>
288 /// </devdoc>
289 public static SqlBoolean operator>(SqlBinary x, SqlBinary y) {
290 if (x.IsNull || y.IsNull)
291 return SqlBoolean.Null;
293 return new SqlBoolean(PerformCompareByte(x.Value, y.Value) == EComparison.GT);
296 /// <devdoc>
297 /// <para>
298 /// Compares the first <see cref='System.Data.SqlTypes.SqlBinary'/> for being less than or equal to the second <see cref='System.Data.SqlTypes.SqlBinary'/>.
299 /// </para>
300 /// </devdoc>
301 public static SqlBoolean operator<=(SqlBinary x, SqlBinary y) {
302 if (x.IsNull || y.IsNull)
303 return SqlBoolean.Null;
305 EComparison cmpResult = PerformCompareByte(x.Value, y.Value);
306 return new SqlBoolean(cmpResult == EComparison.LT || cmpResult == EComparison.EQ);
309 /// <devdoc>
310 /// <para>
311 /// Compares the first <see cref='System.Data.SqlTypes.SqlBinary'/> for being greater than or equal the second <see cref='System.Data.SqlTypes.SqlBinary'/>.
312 /// </para>
313 /// </devdoc>
314 public static SqlBoolean operator>=(SqlBinary x, SqlBinary y) {
315 if (x.IsNull || y.IsNull)
316 return SqlBoolean.Null;
318 EComparison cmpResult = PerformCompareByte(x.Value, y.Value);
319 return new SqlBoolean(cmpResult == EComparison.GT || cmpResult == EComparison.EQ);
322 //--------------------------------------------------
323 // Alternative methods for overloaded operators
324 //--------------------------------------------------
326 // Alternative method for operator +
327 public static SqlBinary Add(SqlBinary x, SqlBinary y) {
328 return x + y;
331 public static SqlBinary Concat(SqlBinary x, SqlBinary y) {
332 return x + y;
335 // Alternative method for operator ==
336 public static SqlBoolean Equals(SqlBinary x, SqlBinary y) {
337 return (x == y);
340 // Alternative method for operator !=
341 public static SqlBoolean NotEquals(SqlBinary x, SqlBinary y) {
342 return (x != y);
345 // Alternative method for operator <
346 public static SqlBoolean LessThan(SqlBinary x, SqlBinary y) {
347 return (x < y);
350 // Alternative method for operator >
351 public static SqlBoolean GreaterThan(SqlBinary x, SqlBinary y) {
352 return (x > y);
355 // Alternative method for operator <=
356 public static SqlBoolean LessThanOrEqual(SqlBinary x, SqlBinary y) {
357 return (x <= y);
360 // Alternative method for operator >=
361 public static SqlBoolean GreaterThanOrEqual(SqlBinary x, SqlBinary y) {
362 return (x >= y);
365 // Alternative method for conversions.
366 public SqlGuid ToSqlGuid() {
367 return (SqlGuid)this;
370 // IComparable
371 // Compares this object to another object, returning an integer that
372 // indicates the relationship.
373 // Returns a value less than zero if this < object, zero if this = object,
374 // or a value greater than zero if this > object.
375 // null is considered to be less than any instance.
376 // If object is not of same type, this method throws an ArgumentException.
377 /// <devdoc>
378 /// <para>[To be supplied.]</para>
379 /// </devdoc>
380 public int CompareTo(Object value) {
381 if (value is SqlBinary) {
382 SqlBinary i = (SqlBinary)value;
384 return CompareTo(i);
386 throw ADP.WrongType(value.GetType(), typeof(SqlBinary));
389 public int CompareTo(SqlBinary value) {
390 // If both Null, consider them equal.
391 // Otherwise, Null is less than anything.
392 if (IsNull)
393 return value.IsNull ? 0 : -1;
394 else if (value.IsNull)
395 return 1;
397 if (this < value) return -1;
398 if (this > value) return 1;
399 return 0;
402 // Compares this instance with a specified object
403 /// <devdoc>
404 /// <para>[To be supplied.]</para>
405 /// </devdoc>
406 public override bool Equals(Object value) {
407 if (!(value is SqlBinary)) {
408 return false;
411 SqlBinary i = (SqlBinary)value;
413 if (i.IsNull || IsNull)
414 return (i.IsNull && IsNull);
415 else
416 return (this == i).Value;
419 // Hash a byte array.
420 // Trailing zeroes/spaces would affect the hash value, so caller needs to
421 // perform trimming as necessary.
422 internal static int HashByteArray(byte[] rgbValue, int length)
424 SQLDebug.Check(length >= 0);
426 if (length <= 0)
427 return 0;
429 SQLDebug.Check(rgbValue.Length >= length);
431 int ulValue = 0;
432 int ulHi;
434 // Size of CRC window (hashing bytes, ssstr, sswstr, numeric)
435 const int x_cbCrcWindow = 4;
436 // const int iShiftVal = (sizeof ulValue) * (8*sizeof(char)) - x_cbCrcWindow;
437 const int iShiftVal = 4 * 8 - x_cbCrcWindow;
439 for(int i = 0; i < length; i++)
441 ulHi = (ulValue >> iShiftVal) & 0xff;
442 ulValue <<= x_cbCrcWindow;
443 ulValue = ulValue ^ rgbValue[i] ^ ulHi;
446 return ulValue;
448 // For hashing purpose
449 /// <devdoc>
450 /// <para>[To be supplied.]</para>
451 /// </devdoc>
452 public override int GetHashCode()
454 if (IsNull)
455 return 0;
457 //First trim off extra '\0's
458 int cbLen = m_value.Length;
459 while (cbLen > 0 && m_value[cbLen - 1] == 0)
460 --cbLen;
462 return HashByteArray(m_value, cbLen);
465 /// <devdoc>
466 /// <para>[To be supplied.]</para>
467 /// </devdoc>
468 XmlSchema IXmlSerializable.GetSchema() { return null; }
470 /// <devdoc>
471 /// <para>[To be supplied.]</para>
472 /// </devdoc>
473 void IXmlSerializable.ReadXml(XmlReader reader) {
474 string isNull = reader.GetAttribute("nil", XmlSchema.InstanceNamespace);
475 if (isNull != null && XmlConvert.ToBoolean(isNull)) {
476 // VSTFDevDiv# 479603 - SqlTypes read null value infinitely and never read the next value. Fix - Read the next value.
477 reader.ReadElementString();
478 m_value = null;
480 else {
481 string base64 = reader.ReadElementString();
482 if (base64 == null) {
483 m_value = new byte[0];
485 else {
486 base64 = base64.Trim();
488 if (base64.Length == 0) {
489 m_value = new byte[0];
491 else {
492 m_value = Convert.FromBase64String(base64);
498 /// <devdoc>
499 /// <para>[To be supplied.]</para>
500 /// </devdoc>
501 void IXmlSerializable.WriteXml(XmlWriter writer) {
502 if (IsNull) {
503 writer.WriteAttributeString("xsi", "nil", XmlSchema.InstanceNamespace, "true");
505 else {
506 writer.WriteString(Convert.ToBase64String(m_value));
510 /// <devdoc>
511 /// <para>[To be supplied.]</para>
512 /// </devdoc>
513 public static XmlQualifiedName GetXsdType(XmlSchemaSet schemaSet) {
514 return new XmlQualifiedName("base64Binary", XmlSchema.Namespace);
517 /// <devdoc>
518 /// <para>
519 /// Represents a null value that can be assigned to
520 /// the <see cref='System.Data.SqlTypes.SqlBinary.Value'/> property of an
521 /// instance of the <see cref='System.Data.SqlTypes.SqlBinary'/> class.
522 /// </para>
523 /// </devdoc>
524 public static readonly SqlBinary Null = new SqlBinary(true);
526 } // SqlBinary
528 } // namespace System.Data.SqlTypes