More tests.
[mono.git] / mcs / class / System.Data / System.Data.SqlTypes / SqlChars.cs
1 //
2 // System.Data.SqlTypes.SqlChars
3 //
4 // Author:
5 //   Tim Coleman <tim@timcoleman.com>
6 //
7 // Copyright (C) Tim Coleman, 2003
8 //
9
10 //
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 #if NET_2_0
34
35 using System;
36 using System.Globalization;
37 using System.Xml;
38 using System.Text;
39 using System.Xml.Schema;
40 using System.Xml.Serialization;
41 using System.Runtime.Serialization;
42
43 namespace System.Data.SqlTypes
44 {
45         [SerializableAttribute]
46         [XmlSchemaProvider ("GetXsdType")]
47         public sealed class SqlChars : INullable, IXmlSerializable, ISerializable
48         {
49                 #region Fields
50
51                 bool notNull;
52                 char [] buffer;
53                 StorageState storage = StorageState.UnmanagedBuffer;
54
55                 #endregion
56
57                 #region Constructors
58
59                 public SqlChars ()
60                 {
61                         notNull = false;
62                         buffer = null;
63                 }
64
65                 public SqlChars (char[] buffer)
66                 {
67                         if (buffer == null) {
68                                 notNull = false;
69                                 this.buffer = null;
70                         } else {
71                                 notNull = true;
72                                 this.buffer = buffer;
73                                 storage = StorageState.Buffer;
74                         }
75                 }
76
77                 public SqlChars (SqlString value)
78                 {
79                         if (value.IsNull) {
80                                 notNull = false;
81                                 buffer = null;
82                         } else {
83                                 notNull = true;
84                                 buffer = value.Value.ToCharArray ();
85                                 storage = StorageState.Buffer;
86                         }
87                 }
88
89                 #endregion
90
91                 #region Properties
92
93                 public char [] Buffer {
94                         get { return buffer; }
95                 }
96
97                 public bool IsNull {
98                         get { return !notNull; }
99                 }
100
101                 public char this [long offset] {
102                         set {
103                                 if (notNull && offset >= 0 && offset < buffer.Length)
104                                         buffer [offset] = value;
105                         }
106                         get {
107                                 if (buffer == null)
108                                         throw new SqlNullValueException ("Data is Null");
109                                 if (offset < 0 || offset >= buffer.Length)
110                                         throw new ArgumentOutOfRangeException ("Parameter name: offset");
111                                 return buffer [offset];
112                         }
113                 }
114
115                 public long Length {
116                         get {
117                                 if (!notNull || buffer == null)
118                                         throw new SqlNullValueException ("Data is Null");
119                                 if (buffer.Length < 0)
120                                         return -1;
121                                 return buffer.Length;
122                         }
123                 }
124
125                 public long MaxLength {
126                         get {
127                                 if (!notNull || buffer == null || storage == StorageState.Stream)
128                                         return -1;
129                                 return buffer.Length;
130                         }
131                 }
132
133                 public static SqlChars Null {
134                         get {
135                                 return new SqlChars ();
136                         }
137                 }
138
139                 public StorageState Storage {
140                         get {
141                                 if (storage == StorageState.UnmanagedBuffer)
142                                         throw new SqlNullValueException ("Data is Null");
143                                 return storage;
144                         }
145                 }
146
147                 public char [] Value {
148                         get {
149                                 if (buffer == null)
150                                         return buffer;
151                                 return (char []) buffer.Clone ();
152                         }
153                 }
154
155                 #endregion
156
157                 #region Methods
158
159                 public void SetLength (long value)
160                 {
161                         if (buffer == null)
162                                 throw new SqlTypeException ("There is no buffer");
163                         if (value < 0 || value > buffer.Length)
164                                 throw new ArgumentOutOfRangeException ("Specified argument was out of the range of valid values.");
165                         Array.Resize (ref buffer, (int) value);
166                 }
167
168                 public void SetNull ()
169                 {
170                         buffer = null;
171                         notNull = false;
172                 }
173
174                 public static explicit operator SqlString (SqlChars value)
175                 {
176                         if (value.IsNull)
177                                 return SqlString.Null;
178                         else {
179                                 return new SqlString (new String (value.Value));
180                         }
181                 }
182
183                 public static explicit operator SqlChars (SqlString value)
184                 {
185                         if (value.IsNull)
186                                 return Null;
187                         else
188                                 return new SqlChars (value.Value);
189                 }
190
191                 public SqlString ToSqlString ()
192                 {
193                         if (buffer == null) {
194                                 return SqlString.Null;
195                         } else {
196                                 return new SqlString (buffer.ToString ());
197                         }
198                 }
199
200                 public long Read (long offset, char [] buffer, int offsetInBuffer, int count)
201                 {
202                         if (buffer == null)
203                                 throw new ArgumentNullException ("buffer");
204
205                         if (IsNull)
206                                 throw new SqlNullValueException ("There is no buffer. Read or write operation failed");
207                         
208                         if (count > MaxLength || count > buffer.Length || 
209                             count < 0 || ((offsetInBuffer + count) > buffer.Length))
210                                 throw new ArgumentOutOfRangeException ("count");
211                         
212                         if (offset < 0 || offset > MaxLength)
213                                 throw new ArgumentOutOfRangeException ("offset");
214                         
215                         if (offsetInBuffer < 0 || offsetInBuffer > buffer.Length)
216                                 throw new ArgumentOutOfRangeException ("offsetInBuffer");
217                         
218                         /*      LAMESPEC: If count specifies more characters than what is available from 
219                                 offset to the Length of the SqlChars instance, only the available 
220                                 characters are copied 
221                          */
222                         
223                         /* Final count of what will be copied */
224                         long actualCount = count;
225                         if (count + offset > Length)
226                                 actualCount = Length - offset;
227                         
228                         Array.Copy (this.buffer, offset, buffer, offsetInBuffer, actualCount);
229                         
230                         return actualCount;
231                 }
232
233                 public void Write (long offset, char [] buffer, int offsetInBuffer, int count)
234                 {
235                         if (buffer == null)
236                                 throw new ArgumentNullException ("buffer");
237
238                         if (IsNull)
239                                 throw new SqlTypeException ("There is no buffer. Read or write operation failed.");
240                                                         
241                         if (offset < 0) 
242                                 throw new ArgumentOutOfRangeException ("offset");
243                         
244                         if (offsetInBuffer < 0 || offsetInBuffer > buffer.Length 
245                             || offsetInBuffer > Length 
246                             || offsetInBuffer + count > Length
247                             || offsetInBuffer + count > buffer.Length)
248                                 throw new ArgumentOutOfRangeException ("offsetInBuffer");
249                         
250                         if (count < 0 || count > MaxLength)
251                                 throw new ArgumentOutOfRangeException ("count");
252                         
253                         if (offset > MaxLength || offset+count > MaxLength)
254                                 throw new SqlTypeException ("The buffer is insufficient. Read or write operation failed.");
255                         
256                         if (count + offset > Length && 
257                             count + offset <= MaxLength)
258                                 SetLength (count);
259                         
260                         Array.Copy (buffer, offsetInBuffer, this.buffer, offset, count);
261                 }
262
263                 public static XmlQualifiedName GetXsdType (XmlSchemaSet schemaSet)
264                 {
265                         if (schemaSet != null && schemaSet.Count == 0) {
266                                 XmlSchema xs = new XmlSchema ();
267                                 XmlSchemaComplexType ct = new XmlSchemaComplexType ();
268                                 ct.Name = "string";
269                                 xs.Items.Add (ct);
270                                 schemaSet.Add (xs);
271                         }
272                         return new XmlQualifiedName ("string", "http://www.w3.org/2001/XMLSchema");
273                 }
274                 
275                 XmlSchema IXmlSerializable.GetSchema ()
276                 {
277                         return null;
278                 }
279                 
280                 void IXmlSerializable.ReadXml (XmlReader reader)
281                 {
282                         if (reader == null)
283                                 return;
284
285                         switch (reader.ReadState) {
286                         case ReadState.EndOfFile:
287                         case ReadState.Error:
288                         case ReadState.Closed:
289                                 return;
290                         }
291                         // Skip XML declaration and prolog
292                         // or do I need to validate for the <string> tag?
293                         reader.MoveToContent ();
294                         if (reader.EOF)
295                                 return;
296                         
297                         reader.Read ();
298                         if (reader.NodeType == XmlNodeType.EndElement)
299                                 return;
300
301                         if (reader.Value.Length > 0) {
302                                 if (String.Compare ("Null", reader.Value) == 0) {
303                                         // means a null reference/invalid value
304                                         notNull = false;
305                                         return; 
306                                 }
307                                 // FIXME: Validate the value for expected format
308                                 this.buffer = reader.Value.ToCharArray ();
309                                 this.notNull = true;
310                                 this.storage = StorageState.Buffer;
311                         }
312                 }
313                 
314                 void IXmlSerializable.WriteXml (XmlWriter writer) 
315                 {
316                         writer.WriteString (this.buffer.ToString ());
317                 }
318
319                 [MonoTODO]
320                 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
321                 {
322                         throw new NotImplementedException ();
323                 }
324
325                 #endregion
326         }
327 }
328
329 #endif