1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Xml;
6 using System.Collections;
7 
8 namespace System.Data.Common
9 {
10     internal sealed class DateTimeOffsetStorage : DataStorage
11     {
12         private static readonly DateTimeOffset s_defaultValue = DateTimeOffset.MinValue;
13 
14         private DateTimeOffset[] _values;
15 
DateTimeOffsetStorage(DataColumn column)16         internal DateTimeOffsetStorage(DataColumn column)
17         : base(column, typeof(DateTimeOffset), s_defaultValue, StorageType.DateTimeOffset)
18         {
19         }
20 
Aggregate(int[] records, AggregateType kind)21         public override object Aggregate(int[] records, AggregateType kind)
22         {
23             bool hasData = false;
24             try
25             {
26                 switch (kind)
27                 {
28                     case AggregateType.Min:
29                         DateTimeOffset min = DateTimeOffset.MaxValue;
30                         for (int i = 0; i < records.Length; i++)
31                         {
32                             int record = records[i];
33                             if (HasValue(record))
34                             {
35                                 min = (DateTimeOffset.Compare(_values[record], min) < 0) ? _values[record] : min;
36                                 hasData = true;
37                             }
38                         }
39                         if (hasData)
40                         {
41                             return min;
42                         }
43                         return _nullValue;
44 
45                     case AggregateType.Max:
46                         DateTimeOffset max = DateTimeOffset.MinValue;
47                         for (int i = 0; i < records.Length; i++)
48                         {
49                             int record = records[i];
50                             if (HasValue(record))
51                             {
52                                 max = (DateTimeOffset.Compare(_values[record], max) >= 0) ? _values[record] : max;
53                                 hasData = true;
54                             }
55                         }
56                         if (hasData)
57                         {
58                             return max;
59                         }
60                         return _nullValue;
61 
62                     case AggregateType.First:
63                         if (records.Length > 0)
64                         {
65                             return _values[records[0]];
66                         }
67                         return null;
68 
69                     case AggregateType.Count:
70                         int count = 0;
71                         for (int i = 0; i < records.Length; i++)
72                         {
73                             if (HasValue(records[i]))
74                             {
75                                 count++;
76                             }
77                         }
78                         return count;
79                 }
80             }
81             catch (OverflowException)
82             {
83                 throw ExprException.Overflow(typeof(DateTimeOffset));
84             }
85             throw ExceptionBuilder.AggregateException(kind, _dataType);
86         }
87 
Compare(int recordNo1, int recordNo2)88         public override int Compare(int recordNo1, int recordNo2)
89         {
90             DateTimeOffset valueNo1 = _values[recordNo1];
91             DateTimeOffset valueNo2 = _values[recordNo2];
92 
93             if (valueNo1 == s_defaultValue || valueNo2 == s_defaultValue)
94             {
95                 int bitCheck = CompareBits(recordNo1, recordNo2);
96                 if (0 != bitCheck)
97                 {
98                     return bitCheck;
99                 }
100             }
101             return DateTimeOffset.Compare(valueNo1, valueNo2);
102         }
103 
CompareValueTo(int recordNo, object value)104         public override int CompareValueTo(int recordNo, object value)
105         {
106             System.Diagnostics.Debug.Assert(0 <= recordNo, "Invalid record");
107             System.Diagnostics.Debug.Assert(null != value, "null value");
108 
109             if (_nullValue == value)
110             {
111                 return (HasValue(recordNo) ? 1 : 0);
112             }
113 
114             DateTimeOffset valueNo1 = _values[recordNo];
115             if ((s_defaultValue == valueNo1) && !HasValue(recordNo))
116             {
117                 return -1;
118             }
119             return DateTimeOffset.Compare(valueNo1, (DateTimeOffset)value);
120         }
121 
ConvertValue(object value)122         public override object ConvertValue(object value)
123         {
124             if (_nullValue != value)
125             {
126                 if (null != value)
127                 {
128                     value = ((DateTimeOffset)value);
129                 }
130                 else
131                 {
132                     value = _nullValue;
133                 }
134             }
135             return value;
136         }
137 
Copy(int recordNo1, int recordNo2)138         public override void Copy(int recordNo1, int recordNo2)
139         {
140             CopyBits(recordNo1, recordNo2);
141             _values[recordNo2] = _values[recordNo1];
142         }
143 
Get(int record)144         public override object Get(int record)
145         {
146             DateTimeOffset value = _values[record];
147             if ((value != s_defaultValue) || HasValue(record))
148             {
149                 return value;
150             }
151             return _nullValue;
152         }
153 
Set(int record, object value)154         public override void Set(int record, object value)
155         {
156             System.Diagnostics.Debug.Assert(null != value, "null value");
157             if (_nullValue == value)
158             {
159                 _values[record] = s_defaultValue;
160                 SetNullBit(record, true);
161             }
162             else
163             {
164                 _values[record] = (DateTimeOffset)value;
165                 SetNullBit(record, false);
166             }
167         }
168 
SetCapacity(int capacity)169         public override void SetCapacity(int capacity)
170         {
171             DateTimeOffset[] newValues = new DateTimeOffset[capacity];
172             if (null != _values)
173             {
174                 Array.Copy(_values, 0, newValues, 0, Math.Min(capacity, _values.Length));
175             }
176             _values = newValues;
177             base.SetCapacity(capacity);
178         }
179 
ConvertXmlToObject(string s)180         public override object ConvertXmlToObject(string s)
181         {
182             return XmlConvert.ToDateTimeOffset(s);
183         }
184 
ConvertObjectToXml(object value)185         public override string ConvertObjectToXml(object value)
186         {
187             return XmlConvert.ToString((DateTimeOffset)value);
188         }
189 
GetEmptyStorage(int recordCount)190         protected override object GetEmptyStorage(int recordCount)
191         {
192             return new DateTimeOffset[recordCount];
193         }
194 
CopyValue(int record, object store, BitArray nullbits, int storeIndex)195         protected override void CopyValue(int record, object store, BitArray nullbits, int storeIndex)
196         {
197             DateTimeOffset[] typedStore = (DateTimeOffset[])store;
198             typedStore[storeIndex] = _values[record];
199             nullbits.Set(storeIndex, !HasValue(record));
200         }
201 
SetStorage(object store, BitArray nullbits)202         protected override void SetStorage(object store, BitArray nullbits)
203         {
204             _values = (DateTimeOffset[])store;
205             SetNullStorage(nullbits);
206         }
207     }
208 }
209