In corlib/System.Runtime.InteropServices:
[mono.git] / mcs / class / System.Data / System.Data.SqlTypes / SqlString.cs
1 //
2 // System.Data.SqlTypes.SqlString
3 //
4 // Author:
5 //   Rodrigo Moya (rodrigo@ximian.com)
6 //   Daniel Morgan (danmorg@sc.rr.com)
7 //   Tim Coleman (tim@timcoleman.com)
8 //   Ville Palo (vi64pa@koti.soon.fi)
9 //
10 // (C) Ximian, Inc. 2002
11 // (C) Copyright 2002 Tim Coleman
12 //
13
14 //
15 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
16 //
17 // Permission is hereby granted, free of charge, to any person obtaining
18 // a copy of this software and associated documentation files (the
19 // "Software"), to deal in the Software without restriction, including
20 // without limitation the rights to use, copy, modify, merge, publish,
21 // distribute, sublicense, and/or sell copies of the Software, and to
22 // permit persons to whom the Software is furnished to do so, subject to
23 // the following conditions:
24 // 
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
27 // 
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 //
36
37 using System;
38 using System.Xml;
39 using System.Text;
40 using System.Threading;
41 using System.Xml.Schema;
42 using System.Globalization;
43 using System.Xml.Serialization;
44
45 namespace System.Data.SqlTypes
46 {
47         /// <summary>
48         /// A variable-length stream of characters 
49         /// to be stored in or retrieved from the database
50         /// </summary>
51 #if NET_2_0
52         [SerializableAttribute]
53         [XmlSchemaProvider ("GetXsdType")]
54 #endif
55         public struct SqlString : INullable, IComparable 
56 #if NET_2_0
57                                 , IXmlSerializable
58 #endif
59         {
60
61                 #region Fields
62
63                 string value;
64
65                 private bool notNull;
66
67                 // FIXME: locale id is not working yet
68                 private int lcid;
69                 private SqlCompareOptions compareOptions;
70
71                 public static readonly int BinarySort = 0x8000;
72                 public static readonly int IgnoreCase = 0x1;
73                 public static readonly int IgnoreKanaType = 0x8;
74                 public static readonly int IgnoreNonSpace = 0x2;
75                 public static readonly int IgnoreWidth = 0x10;
76                 public static readonly SqlString Null;
77
78                 internal static NumberFormatInfo DecimalFormat;
79                 #endregion // Fields
80
81                 #region Constructors
82
83                 static SqlString ()
84                 {
85                         DecimalFormat = (NumberFormatInfo) NumberFormatInfo.InvariantInfo.Clone ();
86                         DecimalFormat.NumberDecimalDigits = 13;
87                         DecimalFormat.NumberGroupSeparator = String.Empty;
88                 }
89
90                 // init with a string data
91                 public SqlString (string data) 
92                 {
93                         this.value = data;
94                         lcid = CultureInfo.CurrentCulture.LCID;
95                         notNull = true;
96                         this.compareOptions = SqlCompareOptions.IgnoreCase |
97                                 SqlCompareOptions.IgnoreKanaType |
98                                 SqlCompareOptions.IgnoreWidth;
99                 }
100
101                 // init with a string data and locale id values.
102                 public SqlString (string data, int lcid) 
103                 {
104                         this.value = data;
105                         this.lcid = lcid;
106                         notNull = true;
107                         this.compareOptions = SqlCompareOptions.IgnoreCase |
108                                 SqlCompareOptions.IgnoreKanaType |
109                                 SqlCompareOptions.IgnoreWidth;
110                 }
111
112                 // init with locale id, compare options, 
113                 // and an array of bytes data
114                 public SqlString (int lcid, SqlCompareOptions compareOptions, byte[] data) 
115                         : this (lcid, compareOptions, data, true) { }
116
117                 // init with string data, locale id, and compare options
118                 public SqlString (string data, int lcid, SqlCompareOptions compareOptions) 
119                 {
120                         this.value = data;
121                         this.lcid = lcid;
122                         this.compareOptions = compareOptions;
123                         notNull = true;
124                 }
125
126                 // init with locale id, compare options, array of bytes data,
127                 // and whether unicode is encoded or not
128                 public SqlString (int lcid, SqlCompareOptions compareOptions, byte[] data, bool fUnicode) 
129                 {
130                         Encoding encoding = (fUnicode ? Encoding.Unicode : Encoding.ASCII);
131                         this.value = encoding.GetString (data);
132                         this.lcid = lcid;
133                         this.compareOptions = compareOptions;
134                         notNull = true;
135                 }
136
137                 // init with locale id, compare options, array of bytes data,
138                 // starting index in the byte array, 
139                 // and number of bytes to copy
140                 public SqlString (int lcid, SqlCompareOptions compareOptions, byte[] data, 
141                                   int index, int count) 
142                         : this (lcid, compareOptions, data, index, count, true) { }
143
144                 // init with locale id, compare options, array of bytes data,
145                 // starting index in the byte array, number of byte to copy,
146                 // and whether unicode is encoded or not
147                 public SqlString (int lcid, SqlCompareOptions compareOptions, byte[] data, int index, int count, bool fUnicode) 
148                 {                      
149                         Encoding encoding = (fUnicode ? Encoding.Unicode : Encoding.ASCII);
150                         this.value = encoding.GetString (data, index, count);
151                         this.lcid = lcid;
152                         this.compareOptions = compareOptions;
153                         notNull = true;
154                 }
155
156                 #endregion // Constructors
157
158
159                 #region Public Properties
160
161                 public CompareInfo CompareInfo {
162                         get { 
163                                 return new CultureInfo (lcid).CompareInfo;
164                         }
165                 }
166
167                 public CultureInfo CultureInfo {
168                         get { 
169                                 return new CultureInfo (lcid);
170                         }
171                 }
172
173                 public bool IsNull {
174                         get { return !notNull; }
175                 }
176
177                 // geographics location and language (locale id)
178                 public int LCID {
179                         get { 
180                                 return lcid;
181                         }
182                 }
183         
184                 public SqlCompareOptions SqlCompareOptions {
185                         get { 
186                                 return compareOptions;
187                         }
188                 }
189
190                 public string Value {
191                         get {
192                                 if (this.IsNull)
193                                         throw new SqlNullValueException (Locale.GetText ("The property contains Null."));
194                                 else
195                                         return value;
196                         }
197                 }
198
199                 #endregion // Public Properties
200
201                 #region Private Properties
202
203                 private CompareOptions CompareOptions {
204                         get {
205                                 return
206                                         (this.compareOptions & SqlCompareOptions.BinarySort) != 0 ?
207                                         CompareOptions.Ordinal :
208                                         // 27 == all SqlCompareOptions - BinarySort 
209                                         // (1,2,8,24 are common to CompareOptions)
210                                         (CompareOptions)((int)this.compareOptions & 27);
211                         }
212                 }
213
214                 #endregion Private Properties
215
216                 #region Public Methods
217
218                 public SqlString Clone() 
219                 {
220                         return new  SqlString (value, lcid, compareOptions);
221                 }
222
223                 public static CompareOptions CompareOptionsFromSqlCompareOptions (SqlCompareOptions compareOptions) 
224                 {
225                         CompareOptions options = CompareOptions.None;
226                         
227                         if ((compareOptions & SqlCompareOptions.IgnoreCase) != 0)
228                                 options |= CompareOptions.IgnoreCase;
229                         if ((compareOptions & SqlCompareOptions.IgnoreKanaType) != 0)
230                                 options |= CompareOptions.IgnoreKanaType;
231                         if ((compareOptions & SqlCompareOptions.IgnoreNonSpace) != 0)
232                                 options |= CompareOptions.IgnoreNonSpace;
233                         if ((compareOptions & SqlCompareOptions.IgnoreWidth) != 0)
234                                 options |= CompareOptions.IgnoreWidth;
235                         if ((compareOptions & SqlCompareOptions.BinarySort) != 0)
236                                 // FIXME: Exception string
237                                 throw new ArgumentOutOfRangeException (); 
238                         
239                         return options;         
240                 }
241
242                 // **********************************
243                 // Comparison Methods
244                 // **********************************
245
246                 public int CompareTo (object value)
247                 {
248                         if (value == null)
249                                 return 1;
250                         else if (!(value is SqlString))
251                                 throw new ArgumentException (Locale.GetText ("Value is not a System.Data.SqlTypes.SqlString"));
252                         
253                         return CompareSqlString ((SqlString)value);
254                 }
255
256                 
257                 private int CompareSqlString (SqlString value)
258                 {
259                         if (value.IsNull)
260                                 return 1;
261                         else if (value.CompareOptions != this.CompareOptions)
262                                 throw new SqlTypeException (Locale.GetText ("Two strings to be compared have different collation"));
263 //                      else
264 //                              return String.Compare (this.value, ((SqlString)value).Value, (this.SqlCompareOptions & SqlCompareOptions.IgnoreCase) != 0, this.CultureInfo);
265                         return CultureInfo.CompareInfo.Compare (this.value, value.Value, this.CompareOptions);
266                 }
267
268                 public static SqlString Concat(SqlString x, SqlString y) 
269                 {
270                         return (x + y);
271                 }
272
273                 public override bool Equals(object value) 
274                 {
275                         if (!(value is SqlString))
276                                 return false;
277                         if (this.IsNull && ((SqlString)value).IsNull)
278                                 return true;
279                         else if (((SqlString)value).IsNull)
280                                 return false;
281                         else
282                                 return (bool) (this == (SqlString)value);
283                 }
284
285                 public static SqlBoolean Equals(SqlString x, SqlString y) 
286                 {
287                         return (x == y);
288                 }
289
290                 public override int GetHashCode() 
291                 {
292                         int result = 10;
293                         for (int i = 0; i < value.Length; i++)
294                                 result = 91 * result + (int)(value [i] ^ (value [i] >> 32));
295                                                 
296                         result = 91 * result + lcid.GetHashCode ();
297                         result = 91 * result + (int)compareOptions;
298
299                         return result;
300                 }
301
302                 public byte[] GetNonUnicodeBytes() 
303                 {
304                         return Encoding.ASCII.GetBytes (value);
305                 }
306
307                 public byte[] GetUnicodeBytes() 
308                 {
309                         return Encoding.Unicode.GetBytes (value);
310                 }
311
312                 public static SqlBoolean GreaterThan(SqlString x, SqlString y) 
313                 {
314                         return (x > y);
315                 }
316
317                 public static SqlBoolean GreaterThanOrEqual(SqlString x, SqlString y) 
318                 {
319                         return (x >= y);
320                 }
321
322                 public static SqlBoolean LessThan(SqlString x, SqlString y) 
323                 {
324                         return (x < y);
325                 }
326
327                 public static SqlBoolean LessThanOrEqual(SqlString x, SqlString y) 
328                 {
329                         return (x <= y);
330                 }
331
332                 public static SqlBoolean NotEquals(SqlString x, SqlString y) 
333                 {
334                         return (x != y);
335                 }
336
337                 // ****************************************
338                 // Type Conversions From SqlString To ...
339                 // ****************************************
340
341                 public SqlBoolean ToSqlBoolean() 
342                 {
343                         return ((SqlBoolean)this);
344                 }
345
346                 public SqlByte ToSqlByte() 
347                 {
348                         return ((SqlByte)this);
349                 }
350
351                 public SqlDateTime ToSqlDateTime() 
352                 {
353                         return ((SqlDateTime)this);
354                 }
355
356                 public SqlDecimal ToSqlDecimal() 
357                 {
358                         return ((SqlDecimal)this);
359                 }
360
361                 public SqlDouble ToSqlDouble() 
362                 {
363                         return ((SqlDouble)this);
364                 }
365
366                 public SqlGuid ToSqlGuid() 
367                 {
368                         return ((SqlGuid)this);
369                 }
370
371                 public SqlInt16 ToSqlInt16() 
372                 {
373                         return ((SqlInt16)this);
374                 }
375
376                 public SqlInt32 ToSqlInt32() 
377                 {
378                         return ((SqlInt32)this);
379                 }
380
381                 public SqlInt64 ToSqlInt64() 
382                 {
383                         return ((SqlInt64)this);
384                 }
385
386                 public SqlMoney ToSqlMoney() 
387                 {
388                         return ((SqlMoney)this);
389                 }
390
391                 public SqlSingle ToSqlSingle() 
392                 {
393                         return ((SqlSingle)this);
394                 }
395
396                 public override string ToString() 
397                 {
398                         if (!notNull)
399                                 return "Null";
400                         return ((string)this);
401                 }
402
403                 // ***********************************
404                 // Operators
405                 // ***********************************
406
407                 // Concatenates
408                 public static SqlString operator + (SqlString x, SqlString y) 
409                 {
410                          if (x.IsNull || y.IsNull)
411                                 return SqlString.Null;
412
413                         if (( x == null) || (y == null))
414                                 return SqlString.Null;
415                         
416                         return new SqlString (x.Value + y.Value);
417                 }
418
419                 // Equality
420                 public static SqlBoolean operator == (SqlString x, SqlString y) 
421                 {
422                         if (x.IsNull || y.IsNull)
423                                 return SqlBoolean.Null;
424                         else
425                                 return new SqlBoolean (x.Value == y.Value);
426                 }
427
428                 // Greater Than
429                 public static SqlBoolean operator > (SqlString x, SqlString y) 
430                 {
431                         if (x.IsNull || y.IsNull)
432                                 return SqlBoolean.Null;
433                         else
434                                 return new SqlBoolean (x.CompareTo (y) > 0);
435                 }
436
437                 // Greater Than Or Equal
438                 public static SqlBoolean operator >= (SqlString x, SqlString y) 
439                 {
440                         if (x.IsNull || y.IsNull)
441                                 return SqlBoolean.Null;
442                         else
443                                 return new SqlBoolean (x.CompareTo (y) >= 0);
444                 }
445
446                 public static SqlBoolean operator != (SqlString x, SqlString y) 
447                 { 
448                         if (x.IsNull || y.IsNull)
449                                 return SqlBoolean.Null;
450                         else
451                                 return new SqlBoolean (x.Value != y.Value);
452                 }
453
454                 // Less Than
455                 public static SqlBoolean operator < (SqlString x, SqlString y) 
456                 {
457                         if (x.IsNull || y.IsNull)
458                                 return SqlBoolean.Null;
459                         else
460                                 return new SqlBoolean (x.CompareTo (y) < 0);
461                 }
462
463                 // Less Than Or Equal
464                 public static SqlBoolean operator <= (SqlString x, SqlString y) 
465                 {
466                         if (x.IsNull || y.IsNull)
467                                 return SqlBoolean.Null;
468                         else
469                                 return new SqlBoolean (x.CompareTo (y) <= 0);
470                 }
471
472                 // **************************************
473                 // Type Conversions
474                 // **************************************
475
476                 public static explicit operator SqlString (SqlBoolean x) 
477                 {
478                         if (x.IsNull)
479                                 return Null;
480                         else
481                                 return new SqlString (x.Value.ToString ());
482                 }
483
484                 public static explicit operator SqlString (SqlByte x) 
485                 {
486                         if (x.IsNull)
487                                 return Null;
488                         else
489                                 return new SqlString (x.Value.ToString ());
490                 }
491
492                 public static explicit operator SqlString (SqlDateTime x) 
493                 {
494                         if (x.IsNull)
495                                 return Null;
496                         else
497                                 return new SqlString (x.Value.ToString ());
498                 }
499
500                 public static explicit operator SqlString (SqlDecimal x)
501                 {
502                         if (x.IsNull)
503                                 return Null;
504                         else
505                                 return new SqlString (x.Value.ToString ());
506                                 // return new SqlString (x.Value.ToString ("N", DecimalFormat));
507                 }
508
509                 public static explicit operator SqlString (SqlDouble x) 
510                 {
511                         if (x.IsNull)
512                                 return Null;
513                         else
514                                 return new SqlString (x.Value.ToString ());
515                 }
516
517                 public static explicit operator SqlString (SqlGuid x) 
518                 {
519                         if (x.IsNull)
520                                 return Null;
521                         else
522                                 return new SqlString (x.Value.ToString ());
523                 }
524
525                 public static explicit operator SqlString (SqlInt16 x) 
526                 {
527                         if (x.IsNull)
528                                 return Null;
529                         else
530                                 return new SqlString (x.Value.ToString ());
531                 }
532
533                 public static explicit operator SqlString (SqlInt32 x) 
534                 {
535                         if (x.IsNull)
536                                 return Null;
537                         else
538                                 return new SqlString (x.Value.ToString ());
539                 }
540
541                 public static explicit operator SqlString (SqlInt64 x) 
542                 {
543                         if (x.IsNull)
544                                 return Null;
545                         else
546                                 return new SqlString (x.Value.ToString ());
547                 }
548
549                 public static explicit operator SqlString (SqlMoney x) 
550                 {
551                         if (x.IsNull)
552                                 return Null;
553                         else
554                                 return new SqlString (x.ToString ());
555                 }
556
557                 public static explicit operator SqlString (SqlSingle x) 
558                 {
559                         if (x.IsNull)
560                                 return Null;
561                         else
562                                 return new SqlString (x.Value.ToString ());
563                 }
564
565                 public static explicit operator string (SqlString x) 
566                 {
567                         return x.Value;
568                 }
569
570                 public static implicit operator SqlString (string x) 
571                 {
572                         return new SqlString (x);
573                 }
574
575                 #if NET_2_0
576                 public static SqlString Add (SqlString x, SqlString y)
577                 {
578                         return ( x + y);
579                                                                                                     
580                 }
581
582                 public int CompareTo (SqlString value)
583                 {
584                         return CompareSqlString (value);
585                 }
586                 #endif
587
588
589
590                 #endregion // Public Methods
591 #if NET_2_0
592                 public static XmlQualifiedName GetXsdType (XmlSchemaSet schemaSet)
593                 {
594                         XmlQualifiedName qualifiedName = new XmlQualifiedName ("string", "http://www.w3.org/2001/XMLSchema");
595                         return qualifiedName;
596                 }
597
598                 [MonoTODO]
599                 XmlSchema IXmlSerializable.GetSchema ()
600                 {
601                         throw new NotImplementedException ();
602                 }
603                 
604                 [MonoTODO]
605                 void IXmlSerializable.ReadXml (XmlReader reader)
606                 {
607                         throw new NotImplementedException ();
608                 }
609                 
610                 [MonoTODO]
611                 void IXmlSerializable.WriteXml (XmlWriter writer) 
612                 {
613                         throw new NotImplementedException ();
614                 }
615 #endif
616         }
617 }