2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / Mono.Data.SybaseClient / Mono.Data.SybaseTypes / SybaseBinary.cs
1 //
2 // Mono.Data.SybaseTypes.SybaseBinary
3 //
4 // Author:
5 //   Tim Coleman (tim@timcoleman.com)
6 //
7 // Based on System.Data.SqlTypes.SqlBinary
8 //
9 // (C) Ximian, Inc. 2002-2003
10 // (C) Copyright Tim Coleman, 2002-2003
11 //
12
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using Mono.Data.SybaseClient;
35 using System;
36 using System.Data.SqlTypes;
37 using System.Globalization;
38
39 namespace Mono.Data.SybaseTypes {
40         public struct SybaseBinary : INullable, IComparable
41         {
42                 #region Fields
43
44                 byte[] value;
45                 private bool notNull;
46
47                 public static readonly SybaseBinary Null;
48
49                 #endregion
50
51                 #region Constructors
52                 
53                 public SybaseBinary (byte[] value) 
54                 {
55                         this.value = value;
56                         notNull = true;
57                 }
58
59                 #endregion
60
61                 #region Properties
62
63                 public bool IsNull {
64                         get { return !notNull; }
65                 }
66
67                 public byte this[int index] {
68                         get { 
69                                 if (this.IsNull)
70                                         throw new SybaseNullValueException ("The property contains Null.");
71                                 else if (index >= this.Length)
72                                         throw new SybaseNullValueException ("The index parameter indicates a position beyond the length of the byte array.");
73                                 else
74                                         return value [index]; 
75                         }
76                 }
77
78                 public int Length {
79                         get { 
80                                 if (this.IsNull)
81                                         throw new SybaseNullValueException ("The property contains Null.");
82                                 else
83                                         return value.Length;
84                         }
85                 }
86
87                 public byte[] Value 
88                 {
89                         get { 
90                                 if (this.IsNull) 
91                                         throw new SybaseNullValueException ("The property contains Null.");
92                                 else 
93                                         return value; 
94                         }
95                 }
96
97                 #endregion
98
99                 #region Methods
100
101                 public int CompareTo (object value) 
102                 {
103                         if (value == null)
104                                 return 1;
105                         else if (!(value is SybaseBinary))
106                                 throw new ArgumentException ("Value is not a Mono.Data.SybaseTypes.SybaseBinary.");
107                         else if (((SybaseBinary) value).IsNull)
108                                 return 1;
109                         else
110                                 return Compare (this, (SybaseBinary) value);
111                 }
112
113                 public static SybaseBinary Concat (SybaseBinary x, SybaseBinary y) 
114                 {
115                         return (x + y);
116                 }
117
118                 public override bool Equals (object value) 
119                 {
120                         if (!(value is SybaseBinary))
121                                 return false;
122                         else
123                                 return (bool) (this == (SybaseBinary)value);
124                 }
125
126                 public static SybaseBoolean Equals (SybaseBinary x, SybaseBinary y) 
127                 {
128                         return (x == y);
129                 }
130
131                 public override int GetHashCode () 
132                 {
133                         int result = 10;
134                         for (int i = 0; i < value.Length; i += 1) 
135                                 result = 91 * result + ((int) value [i]);
136                         return result;
137                 }
138
139                 #endregion
140
141                 #region Operators
142
143                 public static SybaseBoolean GreaterThan (SybaseBinary x, SybaseBinary y) 
144                 {
145                         return (x > y);
146                 }
147
148                 public static SybaseBoolean GreaterThanOrEqual (SybaseBinary x, SybaseBinary y) 
149                 {
150                         return (x >= y);
151                 }
152
153                 public static SybaseBoolean LessThan (SybaseBinary x, SybaseBinary y) 
154                 {
155                         return (x < y);
156                 }
157
158                 public static SybaseBoolean LessThanOrEqual (SybaseBinary x, SybaseBinary y) 
159                 {
160                         return (x <= y);
161                 }
162
163                 public static SybaseBoolean NotEquals (SybaseBinary x, SybaseBinary y) 
164                 {
165                         return (x != y);
166                 }
167
168                 public SybaseGuid ToSybaseGuid () 
169                 {
170                         return new SybaseGuid (value);
171                 }
172
173                 public override string ToString () 
174                 {
175                         if (IsNull)
176                                 return "null";
177                         return String.Format ("SybaseBinary ({0})", Length);
178                 }
179
180                 #endregion
181
182                 #region Operators
183
184                 public static SybaseBinary operator + (SybaseBinary x, SybaseBinary y) 
185                 {
186                         byte[] b = new byte [x.Length + y.Length];
187                         int j = 0;
188                         int i;
189
190                         for (i = 0; i < x.Length; i += 1)
191                                 b [i] = x [i];
192
193                         for (; i < x.Length + y.Length; i += 1) {
194                                 b [i] = y [j];
195                                 j += 1;
196                         }
197
198                         return new SybaseBinary (b);
199                 }
200
201                 public static SybaseBoolean operator == (SybaseBinary x, SybaseBinary y) 
202                 {
203                         if (x.IsNull || y.IsNull) 
204                                 return SybaseBoolean.Null;
205                         else
206                                 return new SybaseBoolean (Compare (x, y) == 0);
207                 }
208
209                 public static SybaseBoolean operator > (SybaseBinary x, SybaseBinary y) 
210                 {
211                         if (x.IsNull || y.IsNull) 
212                                 return SybaseBoolean.Null;
213                         else
214                                 return new SybaseBoolean (Compare (x, y) > 0);
215                 }
216
217                 public static SybaseBoolean operator >= (SybaseBinary x, SybaseBinary y) 
218                 {
219                         if (x.IsNull || y.IsNull) 
220                                 return SybaseBoolean.Null;
221                         else
222                                 return new SybaseBoolean (Compare (x, y) >= 0);
223                 }
224
225                 public static SybaseBoolean operator != (SybaseBinary x, SybaseBinary y) 
226                 {
227                         if (x.IsNull || y.IsNull) 
228                                 return SybaseBoolean.Null;
229                         else
230                                 return new SybaseBoolean (Compare (x, y) != 0);
231                 }
232
233                 public static SybaseBoolean operator < (SybaseBinary x, SybaseBinary y) 
234                 {
235                         if (x.IsNull || y.IsNull) 
236                                 return SybaseBoolean.Null;
237                         else
238                                 return new SybaseBoolean (Compare (x, y) < 0);
239                 }
240
241                 public static SybaseBoolean operator <= (SybaseBinary x, SybaseBinary y) 
242                 {
243                         if (x.IsNull || y.IsNull) 
244                                 return SybaseBoolean.Null;
245                         else
246                                 return new SybaseBoolean (Compare (x, y) <= 0);
247                 }
248
249                 public static explicit operator byte[] (SybaseBinary x) 
250                 {
251                         return x.Value;
252                 }
253
254                 public static explicit operator SybaseBinary (SybaseGuid x) 
255                 {
256                         return new SybaseBinary (x.ToByteArray ());
257                 }
258
259                 public static implicit operator SybaseBinary (byte[] x) 
260                 {
261                         return new SybaseBinary (x);
262                 }
263
264                 private static int Compare (SybaseBinary x, SybaseBinary y)
265                 {
266                         int lengthDiff = 0;
267                         
268                         if (x.Length != y.Length) {
269                                 lengthDiff = x.Length - y.Length;
270                                 
271                                 // if diff more than 0, x is longer
272                                 if (lengthDiff > 0) {
273                                         for (int i = x.Length - 1; i > x.Length - lengthDiff; i -= 1) 
274                                                 if (x [i] != (byte) 0)
275                                                         return 1;
276                                 } else {
277                                         for (int i = y.Length - 1; i > y.Length - lengthDiff; i -= 1) 
278                                                 if (y [i] != (byte) 0)
279                                                         return -1;
280                                 }
281                         }
282
283                         // choose shorter
284                         int len = (lengthDiff > 0) ? y.Length : x.Length;
285
286                         for (int i = len - 1; i > 0; i -= 1) {
287                                 byte bx = x [i];
288                                 byte by = y [i];
289
290                                 if (bx > by)
291                                         return 1;
292                                 else if (bx < by)
293                                         return -1;
294                         }
295
296                         return 0;
297                 }
298
299                 #endregion
300         }
301 }