659db8d52fdd1d8df784dde0f072692c47562f66
[mono.git] / mcs / class / referencesource / System.Data / System / Data / Common / DataRecordInternal.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="DataRecordInternal.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 // <owner current="true" primary="false">Microsoft</owner>
7 //------------------------------------------------------------------------------
8
9 namespace System.Data.Common {
10
11     using System;
12     using System.Collections;
13     using System.ComponentModel;
14     using System.Data;
15     using System.Data.ProviderBase;
16     using System.Diagnostics;
17     using System.IO;
18     using System.Threading;
19
20     internal sealed class DataRecordInternal : DbDataRecord, ICustomTypeDescriptor {
21         private SchemaInfo[] _schemaInfo;
22         private object[] _values;
23         private PropertyDescriptorCollection _propertyDescriptors;
24         private FieldNameLookup _fieldNameLookup; // MDAC 69015
25
26         // copy all runtime data information
27         internal DataRecordInternal(SchemaInfo[] schemaInfo, object[] values, PropertyDescriptorCollection descriptors, FieldNameLookup fieldNameLookup) {
28             Debug.Assert(null != schemaInfo, "invalid attempt to instantiate DataRecordInternal with null schema information");
29             Debug.Assert(null != values, "invalid attempt to instantiate DataRecordInternal with null value[]");
30             _schemaInfo = schemaInfo;
31             _values = values;
32             _propertyDescriptors = descriptors;
33             _fieldNameLookup = fieldNameLookup;
34         }
35
36         // copy all runtime data information
37         internal DataRecordInternal(object[] values, PropertyDescriptorCollection descriptors, FieldNameLookup fieldNameLookup) {
38             Debug.Assert(null != values, "invalid attempt to instantiate DataRecordInternal with null value[]");
39             _values = values;
40             _propertyDescriptors = descriptors;
41             _fieldNameLookup = fieldNameLookup;
42         }
43
44         internal void SetSchemaInfo(SchemaInfo[] schemaInfo) {
45             Debug.Assert(null == _schemaInfo, "invalid attempt to override DataRecordInternal schema information");
46             _schemaInfo = schemaInfo;
47         }
48
49         public override int FieldCount {
50             get {
51                 return _schemaInfo.Length;
52             }
53         }
54
55         public override int GetValues(object[] values) {
56             if (null == values) {
57                 throw ADP.ArgumentNull("values");
58             }
59
60             int copyLen = (values.Length < _schemaInfo.Length) ? values.Length : _schemaInfo.Length;
61             for (int i = 0; i < copyLen; i++) {
62                 values[i] = _values[i];
63             }
64             return copyLen;
65         }
66
67         public override string GetName(int i) {
68             return _schemaInfo[i].name;
69         }
70
71
72         public override object GetValue(int i) {
73             return _values[i];
74         }
75
76         public override string GetDataTypeName(int i) {
77             return _schemaInfo[i].typeName;
78         }
79
80         public override Type GetFieldType(int i) {
81             return _schemaInfo[i].type;
82         }
83
84         public override int GetOrdinal(string name) { // MDAC 69015
85             return _fieldNameLookup.GetOrdinal(name); // MDAC 71470
86         }
87
88         public override object this[int i] {
89             get {
90                 return GetValue(i);
91             }
92         }
93
94         public override object this[string name] {
95             get {
96                 return GetValue(GetOrdinal(name));
97             }
98         }
99
100         public override bool GetBoolean(int i) {
101             return((bool) _values[i]);
102         }
103
104         public override byte GetByte(int i) {
105             return((byte) _values[i]);
106         }
107
108         public override long GetBytes(int i, long dataIndex, byte[] buffer, int bufferIndex, int length) {
109             int cbytes = 0;
110             int ndataIndex;
111
112             byte[] data = (byte[])_values[i];
113
114             cbytes = data.Length;
115
116             // since arrays can't handle 64 bit values and this interface doesn't
117             // allow chunked access to data, a dataIndex outside the rang of Int32
118             // is invalid
119             if (dataIndex > Int32.MaxValue) {
120                 throw ADP.InvalidSourceBufferIndex(cbytes, dataIndex, "dataIndex");
121             }
122
123             ndataIndex = (int)dataIndex;
124
125             // if no buffer is passed in, return the number of characters we have
126             if (null == buffer)
127                 return cbytes;
128
129             try {
130                 if (ndataIndex < cbytes) {
131                     // help the user out in the case where there's less data than requested
132                     if ((ndataIndex + length) > cbytes)
133                         cbytes = cbytes - ndataIndex;
134                     else
135                         cbytes = length;
136                 }
137
138                 // until arrays are 64 bit, we have to do these casts
139                 Array.Copy(data, ndataIndex, buffer, bufferIndex, (int)cbytes);
140             }
141             catch (Exception e) {
142                 // 
143                 if (ADP.IsCatchableExceptionType(e)) {
144                     cbytes = data.Length;
145
146                     if (length < 0)
147                         throw ADP.InvalidDataLength(length);
148
149                     // if bad buffer index, throw
150                     if (bufferIndex < 0 || bufferIndex >= buffer.Length)
151                         throw ADP.InvalidDestinationBufferIndex(length, bufferIndex, "bufferIndex");
152
153                     // if bad data index, throw
154                     if (dataIndex < 0 || dataIndex >= cbytes)
155                         throw ADP.InvalidSourceBufferIndex(length, dataIndex, "dataIndex");
156
157                     // if there is not enough room in the buffer for data
158                     if (cbytes + bufferIndex > buffer.Length)
159                         throw ADP.InvalidBufferSizeOrIndex(cbytes, bufferIndex);
160                 }
161
162                 throw;
163             }
164
165             return cbytes;
166         }
167
168         public override char GetChar(int i) {
169             string s;
170
171             s = (string)_values[i];
172             char[] c = s.ToCharArray();
173             return c[0];
174         }
175
176         public override long GetChars(int i, long dataIndex, char[] buffer, int bufferIndex, int length) {
177             int cchars = 0;
178             string s;
179             int ndataIndex;
180
181             // if the object doesn't contain a char[] then the user will get an exception
182             s = (string)_values[i];
183
184             char[] data = s.ToCharArray();
185
186             cchars = data.Length;
187
188             // since arrays can't handle 64 bit values and this interface doesn't
189             // allow chunked access to data, a dataIndex outside the rang of Int32
190             // is invalid
191             if (dataIndex > Int32.MaxValue) {
192                 throw ADP.InvalidSourceBufferIndex(cchars, dataIndex, "dataIndex");
193             }
194
195             ndataIndex = (int)dataIndex;
196
197
198             // if no buffer is passed in, return the number of characters we have
199             if (null == buffer)
200                 return cchars;
201
202             try {
203                 if (ndataIndex < cchars) {
204                     // help the user out in the case where there's less data than requested
205                     if ((ndataIndex + length) > cchars)
206                         cchars = cchars - ndataIndex;
207                     else
208                         cchars = length;
209                 }
210
211                 Array.Copy(data, ndataIndex, buffer, bufferIndex, cchars);
212             }
213             catch (Exception e) {
214                 // 
215                 if (ADP.IsCatchableExceptionType(e)) {
216                     cchars = data.Length;
217
218                     if (length < 0)
219                        throw ADP.InvalidDataLength(length);
220
221                     // if bad buffer index, throw
222                     if (bufferIndex < 0 || bufferIndex >= buffer.Length)
223                         throw ADP.InvalidDestinationBufferIndex(buffer.Length, bufferIndex, "bufferIndex");
224
225                     // if bad data index, throw
226                     if (ndataIndex < 0 || ndataIndex >= cchars)
227                         throw ADP.InvalidSourceBufferIndex(cchars, dataIndex, "dataIndex");
228
229                     // if there is not enough room in the buffer for data
230                     if (cchars + bufferIndex > buffer.Length)
231                         throw ADP.InvalidBufferSizeOrIndex(cchars, bufferIndex);
232                 }
233
234                 throw;
235             }
236
237             return cchars;
238         }
239
240         public override Guid GetGuid(int i) {
241             return ((Guid)_values[i]);
242         }
243
244
245         public override Int16 GetInt16(int i) {
246             return((Int16) _values[i]);
247         }
248
249         public override Int32 GetInt32(int i) {
250             return((Int32) _values[i]);
251         }
252
253         public override Int64 GetInt64(int i) {
254             return((Int64) _values[i]);
255         }
256
257         public override float GetFloat(int i) {
258             return((float) _values[i]);
259         }
260
261         public override double GetDouble(int i) {
262             return((double) _values[i]);
263         }
264
265         public override string GetString(int i) {
266             return((string) _values[i]);
267         }
268
269         public override Decimal GetDecimal(int i) {
270             return((Decimal) _values[i]);
271         }
272
273         public override DateTime GetDateTime(int i) {
274             return((DateTime) _values[i]);
275         }
276
277         public override bool IsDBNull(int i) {
278             object o = _values[i];
279             return (null == o || Convert.IsDBNull(o));
280         }
281
282         //
283         // ICustomTypeDescriptor
284         //
285
286         AttributeCollection ICustomTypeDescriptor.GetAttributes() {
287             return new AttributeCollection((Attribute[])null);
288
289         }
290
291         string ICustomTypeDescriptor.GetClassName() {
292             return null;
293         }
294
295         string ICustomTypeDescriptor.GetComponentName() {
296             return null;
297         }
298
299         TypeConverter ICustomTypeDescriptor.GetConverter() {
300             return null;
301         }
302
303         EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() {
304             return null;
305         }
306
307
308         PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() {
309             return null;
310         }
311
312         object ICustomTypeDescriptor.GetEditor(Type editorBaseType) {
313             return null;
314         }
315
316         EventDescriptorCollection ICustomTypeDescriptor.GetEvents() {
317             return new EventDescriptorCollection(null);
318         }
319
320         EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) {
321             return new EventDescriptorCollection(null);
322         }
323
324         PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() {
325             return((ICustomTypeDescriptor)this).GetProperties(null);
326         }
327
328         PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) {
329             if(_propertyDescriptors == null) {
330                 _propertyDescriptors = new PropertyDescriptorCollection(null);
331             }
332             return _propertyDescriptors;
333         }
334
335         object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) {
336             return this;
337         }
338     }
339
340     // this doesn't change per record, only alloc once
341     internal struct SchemaInfo {
342         public string name;
343         public string typeName;
344         public Type type;
345     }
346 }