This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[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.Globalization;
39 using System.Threading;
40
41 namespace System.Data.SqlTypes
42 {
43         /// <summary>
44         /// A variable-length stream of characters 
45         /// to be stored in or retrieved from the database
46         /// </summary>
47         public struct SqlString : INullable, IComparable 
48         {
49
50                 #region Fields
51
52                 string value;
53
54                 private bool notNull;
55
56                 // FIXME: locale id is not working yet
57                 private int lcid;
58                 private SqlCompareOptions compareOptions;
59
60                 public static readonly int BinarySort = 0x8000;
61                 public static readonly int IgnoreCase = 0x1;
62                 public static readonly int IgnoreKanaType = 0x8;
63                 public static readonly int IgnoreNonSpace = 0x2;
64                 public static readonly int IgnoreWidth = 0x10;
65                 public static readonly SqlString Null;
66
67                 internal static readonly NumberFormatInfo MoneyFormat;
68                 internal static NumberFormatInfo DecimalFormat;
69                 #endregion // Fields
70
71                 #region Constructors
72
73                 static SqlString ()
74                 {
75                         MoneyFormat = (NumberFormatInfo) NumberFormatInfo.InvariantInfo.Clone ();
76                         MoneyFormat.NumberDecimalDigits = 4;
77                         MoneyFormat.NumberGroupSeparator = String.Empty;
78
79                         DecimalFormat = (NumberFormatInfo) NumberFormatInfo.InvariantInfo.Clone ();
80                         DecimalFormat.NumberDecimalDigits = 13;
81                         DecimalFormat.NumberGroupSeparator = String.Empty;
82                 }
83
84                 // init with a string data
85                 public SqlString (string data) 
86                 {
87                         this.value = data;
88                         lcid = CultureInfo.CurrentCulture.LCID;
89                         notNull = true;
90                         this.compareOptions = SqlCompareOptions.IgnoreCase |
91                                 SqlCompareOptions.IgnoreKanaType |
92                                 SqlCompareOptions.IgnoreWidth;
93                 }
94
95                 // init with a string data and locale id values.
96                 public SqlString (string data, int lcid) 
97                 {
98                         this.value = data;
99                         this.lcid = lcid;
100                         notNull = true;
101                         this.compareOptions = SqlCompareOptions.IgnoreCase |
102                                 SqlCompareOptions.IgnoreKanaType |
103                                 SqlCompareOptions.IgnoreWidth;
104                 }
105
106                 // init with locale id, compare options, 
107                 // and an array of bytes data
108                 public SqlString (int lcid, SqlCompareOptions compareOptions, byte[] data) 
109                         : this (lcid, compareOptions, data, true) { }
110
111                 // init with string data, locale id, and compare options
112                 public SqlString (string data, int lcid, SqlCompareOptions compareOptions) 
113                 {
114                         this.value = data;
115                         this.lcid = lcid;
116                         this.compareOptions = compareOptions;
117                         notNull = true;
118                 }
119
120                 // init with locale id, compare options, array of bytes data,
121                 // and whether unicode is encoded or not
122                 public SqlString (int lcid, SqlCompareOptions compareOptions, byte[] data, bool fUnicode) 
123                 {
124                         char [] chars;
125
126                         if (fUnicode)
127                                 chars = new char [data.Length/2];
128                         else
129                                 chars = new char [data.Length];
130                         
131                         int j = 0;
132                         for (int i = 0; i < chars.Length; i++) {
133
134                                 if (fUnicode) {
135                                         chars [i] = (char)(data [j] << 16);
136                                         chars [i] += (char)data [j + 1];
137                                         j += 2;
138                                 } else {
139                                         chars [i] = (char)data[i];
140                                 }
141                         }
142                                 
143                         this.value = new String (chars);
144                         this.lcid = lcid;
145                         this.compareOptions = compareOptions;
146                         notNull = true;
147                 }
148
149                 // init with locale id, compare options, array of bytes data,
150                 // starting index in the byte array, 
151                 // and number of bytes to copy
152                 public SqlString (int lcid, SqlCompareOptions compareOptions, byte[] data, 
153                                   int index, int count) 
154                         : this (lcid, compareOptions, data, index, count, true) { }
155
156                 // init with locale id, compare options, array of bytes data,
157                 // starting index in the byte array, number of byte to copy,
158                 // and whether unicode is encoded or not
159                 public SqlString (int lcid, SqlCompareOptions compareOptions, byte[] data, int index, int count, bool fUnicode) 
160                 {                      
161                         char [] chars;
162
163                         if (fUnicode)
164                                 chars = new char [(count - index) / 2];
165                         else
166                                 chars = new char [count - index];
167
168                         if (index >= data.Length)
169                                 throw new ArgumentOutOfRangeException ("index");
170
171                         if ((index + count) > data.Length)
172                                 throw new ArgumentOutOfRangeException ("count");
173
174                         int j = 0;
175                         for (int i = index; i < chars.Length; i++) {
176                                 
177                                 if (fUnicode) {
178                                         chars [i] = (char)(data[j] << 16);
179                                         chars [i] += (char)data[j+1];
180                                         j += 2;
181                                 } else {
182                                         chars [i] = (char)data [j];
183                                         j++;
184                                 }
185                         }
186
187                         this.value = new String (chars);
188                         this.lcid = lcid;
189                         this.compareOptions = compareOptions;
190                         notNull = true;
191                 }
192
193                 #endregion // Constructors
194
195
196                 #region Public Properties
197
198                 public CompareInfo CompareInfo {
199                         get { 
200                                 return new CultureInfo (lcid).CompareInfo;
201                         }
202                 }
203
204                 public CultureInfo CultureInfo {
205                         get { 
206                                 return new CultureInfo (lcid);
207                         }
208                 }
209
210                 public bool IsNull {
211                         get { return !notNull; }
212                 }
213
214                 // geographics location and language (locale id)
215                 public int LCID {
216                         get { 
217                                 return lcid;
218                         }
219                 }
220         
221                 public SqlCompareOptions SqlCompareOptions {
222                         get { 
223                                 return compareOptions;
224                         }
225                 }
226
227                 public string Value {
228                         get {
229                                 if (this.IsNull)
230                                         throw new SqlNullValueException (Locale.GetText ("The property contains Null."));
231                                 else
232                                         return value;
233                         }
234                 }
235
236                 #endregion // Public Properties\r
237 \r
238                 #region Private Properties\r
239 \r
240                 private CompareOptions CompareOptions {\r
241                         get {\r
242                                 return\r
243                                         (this.compareOptions & SqlCompareOptions.BinarySort) != 0 ?\r
244                                         CompareOptions.Ordinal :\r
245                                         // 27 == all SqlCompareOptions - BinarySort \r
246                                         // (1,2,8,24 are common to CompareOptions)\r
247                                         (CompareOptions)((int)this.compareOptions & 27);\r
248                         }\r
249                 }\r
250 \r
251                 #endregion Private Properties
252
253                 #region Public Methods
254
255                 public SqlString Clone() 
256                 {
257                         return new  SqlString (value, lcid, compareOptions);
258                 }
259
260                 public static CompareOptions CompareOptionsFromSqlCompareOptions (SqlCompareOptions compareOptions) 
261                 {
262                         CompareOptions options = CompareOptions.None;
263                         
264                         if ((compareOptions & SqlCompareOptions.IgnoreCase) != 0)
265                                 options |= CompareOptions.IgnoreCase;
266                         if ((compareOptions & SqlCompareOptions.IgnoreKanaType) != 0)
267                                 options |= CompareOptions.IgnoreKanaType;
268                         if ((compareOptions & SqlCompareOptions.IgnoreNonSpace) != 0)
269                                 options |= CompareOptions.IgnoreNonSpace;
270                         if ((compareOptions & SqlCompareOptions.IgnoreWidth) != 0)
271                                 options |= CompareOptions.IgnoreWidth;
272                         if ((compareOptions & SqlCompareOptions.BinarySort) != 0)
273                                 // FIXME: Exception string
274                                 throw new ArgumentOutOfRangeException (); 
275                         
276                         return options;         
277                 }
278
279                 // **********************************
280                 // Comparison Methods
281                 // **********************************
282
283                 public int CompareTo (object value)
284                 {
285                         if (value == null)
286                                 return 1;
287                         else if (!(value is SqlString))
288                                 throw new ArgumentException (Locale.GetText ("Value is not a System.Data.SqlTypes.SqlString"));
289                         else if (((SqlString)value).IsNull)
290                                 return 1;
291 //                      else
292 //                              return String.Compare (this.value, ((SqlString)value).Value, (this.SqlCompareOptions & SqlCompareOptions.IgnoreCase) != 0, this.CultureInfo);
293                         return CultureInfo.CompareInfo.Compare (this.value, ((SqlString)value).Value, this.CompareOptions);
294                 }
295
296                 public static SqlString Concat(SqlString x, SqlString y) 
297                 {
298                         return (x + y);
299                 }
300
301                 public override bool Equals(object value) 
302                 {
303                         if (!(value is SqlString))
304                                 return false;
305                         if (this.IsNull && ((SqlString)value).IsNull)
306                                 return true;
307                         else if (((SqlString)value).IsNull)
308                                 return false;
309                         else
310                                 return (bool) (this == (SqlString)value);
311                 }
312
313                 public static SqlBoolean Equals(SqlString x, SqlString y) 
314                 {
315                         return (x == y);
316                 }
317
318                 public override int GetHashCode() 
319                 {
320                         int result = 10;
321                         for (int i = 0; i < value.Length; i++)
322                                 result = 91 * result + (int)(value [i] ^ (value [i] >> 32));
323                                                 
324                         result = 91 * result + lcid.GetHashCode ();
325                         result = 91 * result + (int)compareOptions;
326
327                         return result;
328                 }
329
330                 public byte[] GetNonUnicodeBytes() 
331                 {
332                         byte [] bytes = new byte [value.Length];
333
334                         for (int i = 0; i < bytes.Length; i++) 
335                                 bytes [i] = (byte)value [i];
336
337                         return bytes;
338                 }
339
340                 public byte[] GetUnicodeBytes() 
341                 {
342                         byte [] bytes = new byte [value.Length * 2];
343                         
344                         int j = 0;
345                         for (int i = 0; i < value.Length; i++) {                                
346                                 bytes [j] = (byte)(value [i] & 0x0000FFFF);
347                                 bytes [j + 1] = (byte)((value [i] & 0xFFFF0000) >> 16);
348                                 j += 2;
349                         }
350                         
351                         return bytes;
352                 }
353
354                 public static SqlBoolean GreaterThan(SqlString x, SqlString y) 
355                 {
356                         return (x > y);
357                 }
358
359                 public static SqlBoolean GreaterThanOrEqual(SqlString x, SqlString y) 
360                 {
361                         return (x >= y);
362                 }
363
364                 public static SqlBoolean LessThan(SqlString x, SqlString y) 
365                 {
366                         return (x < y);
367                 }
368
369                 public static SqlBoolean LessThanOrEqual(SqlString x, SqlString y) 
370                 {
371                         return (x <= y);
372                 }
373
374                 public static SqlBoolean NotEquals(SqlString x, SqlString y) 
375                 {
376                         return (x != y);
377                 }
378
379                 // ****************************************
380                 // Type Conversions From SqlString To ...
381                 // ****************************************
382
383                 public SqlBoolean ToSqlBoolean() 
384                 {
385                         return ((SqlBoolean)this);
386                 }
387
388                 public SqlByte ToSqlByte() 
389                 {
390                         return ((SqlByte)this);
391                 }
392
393                 public SqlDateTime ToSqlDateTime() 
394                 {
395                         return ((SqlDateTime)this);
396                 }
397
398                 public SqlDecimal ToSqlDecimal() 
399                 {
400                         return ((SqlDecimal)this);
401                 }
402
403                 public SqlDouble ToSqlDouble() 
404                 {
405                         return ((SqlDouble)this);
406                 }
407
408                 public SqlGuid ToSqlGuid() 
409                 {
410                         return ((SqlGuid)this);
411                 }
412
413                 public SqlInt16 ToSqlInt16() 
414                 {
415                         return ((SqlInt16)this);
416                 }
417
418                 public SqlInt32 ToSqlInt32() 
419                 {
420                         return ((SqlInt32)this);
421                 }
422
423                 public SqlInt64 ToSqlInt64() 
424                 {
425                         return ((SqlInt64)this);
426                 }
427
428                 public SqlMoney ToSqlMoney() 
429                 {
430                         return ((SqlMoney)this);
431                 }
432
433                 public SqlSingle ToSqlSingle() 
434                 {
435                         return ((SqlSingle)this);
436                 }
437
438                 public override string ToString() 
439                 {
440                         if (!notNull)
441                                 return "Null";
442                         return ((string)this);
443                 }
444
445                 // ***********************************
446                 // Operators
447                 // ***********************************
448
449                 // Concatenates
450                 public static SqlString operator + (SqlString x, SqlString y) 
451                 {
452                         if (x.IsNull || y.IsNull)
453                                 return SqlString.Null;
454
455                         return new SqlString (x.Value + y.Value);
456                 }
457
458                 // Equality
459                 public static SqlBoolean operator == (SqlString x, SqlString y) 
460                 {
461                         if (x.IsNull || y.IsNull)
462                                 return SqlBoolean.Null;
463                         else
464                                 return new SqlBoolean (x.Value == y.Value);
465                 }
466
467                 // Greater Than
468                 public static SqlBoolean operator > (SqlString x, SqlString y) 
469                 {
470                         if (x.IsNull || y.IsNull)
471                                 return SqlBoolean.Null;
472                         else
473                                 return new SqlBoolean (x.CompareTo (y) > 0);
474                 }
475
476                 // Greater Than Or Equal
477                 public static SqlBoolean operator >= (SqlString x, SqlString y) 
478                 {
479                         if (x.IsNull || y.IsNull)
480                                 return SqlBoolean.Null;
481                         else
482                                 return new SqlBoolean (x.CompareTo (y) >= 0);
483                 }
484
485                 public static SqlBoolean operator != (SqlString x, SqlString y) 
486                 { 
487                         if (x.IsNull || y.IsNull)
488                                 return SqlBoolean.Null;
489                         else
490                                 return new SqlBoolean (x.Value != y.Value);
491                 }
492
493                 // Less Than
494                 public static SqlBoolean operator < (SqlString x, SqlString y) 
495                 {
496                         if (x.IsNull || y.IsNull)
497                                 return SqlBoolean.Null;
498                         else
499                                 return new SqlBoolean (x.CompareTo (y) < 0);
500                 }
501
502                 // Less Than Or Equal
503                 public static SqlBoolean operator <= (SqlString x, SqlString y) 
504                 {
505                         if (x.IsNull || y.IsNull)
506                                 return SqlBoolean.Null;
507                         else
508                                 return new SqlBoolean (x.CompareTo (y) <= 0);
509                 }
510
511                 // **************************************
512                 // Type Conversions
513                 // **************************************
514
515                 public static explicit operator SqlString (SqlBoolean x) 
516                 {
517                         if (x.IsNull)
518                                 return Null;
519                         else
520                                 return new SqlString (x.Value.ToString ());
521                 }
522
523                 public static explicit operator SqlString (SqlByte x) 
524                 {
525                         if (x.IsNull)
526                                 return Null;
527                         else
528                                 return new SqlString (x.Value.ToString ());
529                 }
530
531                 public static explicit operator SqlString (SqlDateTime x) 
532                 {
533                         if (x.IsNull)
534                                 return Null;
535                         else
536                                 return new SqlString (x.Value.ToString ());
537                 }
538
539                 public static explicit operator SqlString (SqlDecimal x)
540                 {
541                         if (x.IsNull)
542                                 return Null;
543                         else
544                                 return new SqlString (x.Value.ToString ());
545                                 // return new SqlString (x.Value.ToString ("N", DecimalFormat));
546                 }
547
548                 public static explicit operator SqlString (SqlDouble x) 
549                 {
550                         if (x.IsNull)
551                                 return Null;
552                         else
553                                 return new SqlString (x.Value.ToString ());
554                 }
555
556                 public static explicit operator SqlString (SqlGuid x) 
557                 {
558                         if (x.IsNull)
559                                 return Null;
560                         else
561                                 return new SqlString (x.Value.ToString ());
562                 }
563
564                 public static explicit operator SqlString (SqlInt16 x) 
565                 {
566                         if (x.IsNull)
567                                 return Null;
568                         else
569                                 return new SqlString (x.Value.ToString ());
570                 }
571
572                 public static explicit operator SqlString (SqlInt32 x) 
573                 {
574                         if (x.IsNull)
575                                 return Null;
576                         else
577                                 return new SqlString (x.Value.ToString ());
578                 }
579
580                 public static explicit operator SqlString (SqlInt64 x) 
581                 {
582                         if (x.IsNull)
583                                 return Null;
584                         else
585                                 return new SqlString (x.Value.ToString ());
586                 }
587
588                 public static explicit operator SqlString (SqlMoney x) 
589                 {
590                         if (x.IsNull)
591                                 return Null;
592                         else
593                                 return new SqlString (x.Value.ToString ());
594                                 // return new SqlString (x.Value.ToString ("N", MoneyFormat));
595                 }
596
597                 public static explicit operator SqlString (SqlSingle x) 
598                 {
599                         if (x.IsNull)
600                                 return Null;
601                         else
602                                 return new SqlString (x.Value.ToString ());
603                 }
604
605                 public static explicit operator string (SqlString x) 
606                 {
607                         return x.Value;
608                 }
609
610                 public static implicit operator SqlString (string x) 
611                 {
612                         return new SqlString (x);
613                 }
614
615                 #endregion // Public Methods
616         }
617 }