Fix #328490
[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 x)
175                 {
176                         if (x.IsNull)
177                                 return SqlString.Null;
178                         else {
179                                 return new SqlString (new String (x.Value));
180                         }
181                 }
182
183                 public static explicit operator SqlChars (SqlString x)
184                 {
185                         if (x.IsNull)
186                                 return Null;
187                         else
188                                 return new SqlChars (x.Value);
189                 }
190
191                 public SqlString ToSqlString ()
192                 {
193                         if (buffer == null) {
194                                 return SqlString.Null;
195                         }
196                         else {
197                                 return new SqlString (buffer.ToString ());
198                         }
199                 }
200                                                               
201                 public long Read (long offset, char [] buffer, int offsetInBuffer, int count)
202                 {
203                         if (buffer == null)
204                                 throw new ArgumentNullException ("buffer");
205
206                         if (IsNull)
207                                 throw new SqlNullValueException ("There is no buffer. Read or write operation failed");
208                         
209                         if (count > MaxLength || count > buffer.Length || 
210                             count < 0 || ((offsetInBuffer + count) > buffer.Length))
211                                 throw new ArgumentOutOfRangeException ("count");
212                         
213                         if (offset < 0 || offset > MaxLength)
214                                 throw new ArgumentOutOfRangeException ("offset");
215                         
216                         if (offsetInBuffer < 0 || offsetInBuffer > buffer.Length)
217                                 throw new ArgumentOutOfRangeException ("offsetInBuffer");
218                         
219                         /*      LAMESPEC: If count specifies more characters than what is available from 
220                                 offset to the Length of the SqlChars instance, only the available 
221                                 characters are copied 
222                          */
223                         
224                         /* Final count of what will be copied */
225                         long actualCount = count;
226                         if (count + offset > Length)
227                                 actualCount = Length - offset;
228                         
229                         Array.Copy (this.buffer, offset, buffer, offsetInBuffer, actualCount);
230                         
231                         return actualCount;
232                 }
233
234                 public void Write (long offset, char [] buffer, int offsetInBuffer, int count)
235                 {
236                         if (buffer == null)
237                                 throw new ArgumentNullException ("buffer");
238
239                         if (IsNull)
240                                 throw new SqlTypeException ("There is no buffer. Read or write operation failed.");
241                                                         
242                         if (offset < 0) 
243                                 throw new ArgumentOutOfRangeException ("offset");
244                         
245                         if (offsetInBuffer < 0 || offsetInBuffer > buffer.Length 
246                             || offsetInBuffer > Length 
247                             || offsetInBuffer + count > Length
248                             || offsetInBuffer + count > buffer.Length)
249                                 throw new ArgumentOutOfRangeException ("offsetInBuffer");
250                         
251                         if (count < 0 || count > MaxLength)
252                                 throw new ArgumentOutOfRangeException ("count");
253                         
254                         if (offset > MaxLength || offset+count > MaxLength)
255                                 throw new SqlTypeException ("The buffer is insufficient. Read or write operation failed.");
256                         
257                         if (count + offset > Length && 
258                             count + offset <= MaxLength)
259                                 SetLength (count);
260                         
261                         Array.Copy (buffer, offsetInBuffer, this.buffer, offset, count);
262                 }
263
264                 public static XmlQualifiedName GetXsdType (XmlSchemaSet schemaSet)
265                 {
266                         if (schemaSet != null && schemaSet.Count == 0) {
267                                 XmlSchema xs = new XmlSchema ();
268                                 XmlSchemaComplexType ct = new XmlSchemaComplexType ();
269                                 ct.Name = "string";
270                                 xs.Items.Add (ct);
271                                 schemaSet.Add (xs);
272                         }
273                         return new XmlQualifiedName ("string", "http://www.w3.org/2001/XMLSchema");
274                 }
275                 
276                 XmlSchema IXmlSerializable.GetSchema ()
277                 {
278                         return null;
279                 }
280                 
281                 void IXmlSerializable.ReadXml (XmlReader reader)
282                 {
283                         if (reader == null)
284                                 return;
285
286                         switch (reader.ReadState) {
287                         case ReadState.EndOfFile:
288                         case ReadState.Error:
289                         case ReadState.Closed:
290                                 return;
291                         }
292                         // Skip XML declaration and prolog
293                         // or do I need to validate for the <string> tag?
294                         reader.MoveToContent ();
295                         if (reader.EOF)
296                                 return;
297                         
298                         reader.Read ();
299                         if (reader.NodeType == XmlNodeType.EndElement)
300                                 return;
301
302                         if (reader.Value.Length > 0) {
303                                 if (String.Compare ("Null", reader.Value) == 0) {
304                                         // means a null reference/invalid value
305                                         notNull = false;
306                                         return; 
307                                 }
308                                 // FIXME: Validate the value for expected format
309                                 this.buffer = reader.Value.ToCharArray ();
310                                 this.notNull = true;
311                                 this.storage = StorageState.Buffer;
312                         }
313                 }
314                 
315                 void IXmlSerializable.WriteXml (XmlWriter writer) 
316                 {
317                         writer.WriteString (this.buffer.ToString ());
318                 }
319
320                 [MonoTODO]
321                 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
322                 {
323                         throw new NotImplementedException ();
324                 }
325                                                                                 
326                 #endregion
327         }
328 }
329
330 #endif