2 // XQueryArithmeticOperator.cs
\r
5 // Atsushi Enomoto <atsushi@ximian.com>
\r
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
\r
10 // Permission is hereby granted, free of charge, to any person obtaining
\r
11 // a copy of this software and associated documentation files (the
\r
12 // "Software"), to deal in the Software without restriction, including
\r
13 // without limitation the rights to use, copy, modify, merge, publish,
\r
14 // distribute, sublicense, and/or sell copies of the Software, and to
\r
15 // permit persons to whom the Software is furnished to do so, subject to
\r
16 // the following conditions:
\r
18 // The above copyright notice and this permission notice shall be
\r
19 // included in all copies or substantial portions of the Software.
\r
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
32 using System.Collections;
\r
33 using System.Reflection;
\r
35 using System.Xml.Schema;
\r
36 using System.Xml.Query;
\r
37 using System.Xml.XPath;
\r
38 using System.Xml.Xsl;
\r
40 namespace Mono.Xml.XPath2
\r
42 // FIXME: Handle complete type promotion and subtype substitution.
\r
43 // See XQuery 1.0 Appendix B.*.
\r
44 public class XQueryArithmeticOperator
\r
49 public static XPathAtomicValue Add (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
51 // numeric, date, time, dateTime, yearMonthDuration, dayTimeDuration
\r
52 switch (lvalue.XmlType.TypeCode) {
\r
55 case XmlTypeCode.Integer:
\r
56 switch (rvalue.XmlType.TypeCode) {
\r
57 case XmlTypeCode.Integer:
\r
58 return new XPathAtomicValue (lvalue.ValueAsInt64 + rvalue.ValueAsInt64, rvalue.XmlType);
\r
59 case XmlTypeCode.Decimal:
\r
60 return new XPathAtomicValue (lvalue.ValueAsDecimal + rvalue.ValueAsDecimal, rvalue.XmlType);
\r
61 case XmlTypeCode.Float:
\r
62 case XmlTypeCode.Double:
\r
63 return new XPathAtomicValue (lvalue.ValueAsDouble + rvalue.ValueAsDouble, rvalue.XmlType);
\r
67 case XmlTypeCode.Decimal:
\r
68 switch (rvalue.XmlType.TypeCode) {
\r
69 case XmlTypeCode.Integer:
\r
70 case XmlTypeCode.Decimal:
\r
71 return new XPathAtomicValue (lvalue.ValueAsDecimal + rvalue.ValueAsDecimal, rvalue.XmlType);
\r
72 case XmlTypeCode.Float:
\r
73 case XmlTypeCode.Double:
\r
74 return new XPathAtomicValue (lvalue.ValueAsDouble + rvalue.ValueAsDouble, rvalue.XmlType);
\r
78 case XmlTypeCode.Float:
\r
79 case XmlTypeCode.Double:
\r
80 switch (rvalue.XmlType.TypeCode) {
\r
81 case XmlTypeCode.Integer:
\r
82 case XmlTypeCode.Decimal:
\r
83 case XmlTypeCode.Float:
\r
84 case XmlTypeCode.Double:
\r
85 return new XPathAtomicValue (lvalue.ValueAsDouble + rvalue.ValueAsDouble, rvalue.XmlType);
\r
90 case XmlTypeCode.Time:
\r
91 if (rvalue.XmlType.TypeCode == XmlTypeCode.DayTimeDuration)
\r
92 goto case XmlTypeCode.DateTime;
\r
94 case XmlTypeCode.DateTime:
\r
95 case XmlTypeCode.Date:
\r
96 switch (rvalue.XmlType.TypeCode) {
\r
97 case XmlTypeCode.YearMonthDuration:
\r
98 case XmlTypeCode.DayTimeDuration:
\r
99 return new XPathAtomicValue (lvalue.ValueAsDateTime + new TimeSpan (rvalue.ValueAsDateTime.Ticks), lvalue.XmlType);
\r
103 case XmlTypeCode.YearMonthDuration:
\r
104 switch (rvalue.XmlType.TypeCode) {
\r
105 case XmlTypeCode.Date:
\r
106 case XmlTypeCode.DateTime:
\r
107 return new XPathAtomicValue (lvalue.ValueAsDateTime + new TimeSpan (rvalue.ValueAsDateTime.Ticks), rvalue.XmlType);
\r
108 case XmlTypeCode.YearMonthDuration:
\r
109 return new XPathAtomicValue (new DateTime (lvalue.ValueAsDateTime.Ticks + rvalue.ValueAsDateTime.Ticks), XmlSchemaSimpleType.XdtYearMonthDuration);
\r
112 case XmlTypeCode.DayTimeDuration:
\r
113 switch (rvalue.XmlType.TypeCode) {
\r
114 case XmlTypeCode.Date:
\r
115 case XmlTypeCode.Time:
\r
116 case XmlTypeCode.DateTime:
\r
117 return new XPathAtomicValue (lvalue.ValueAsDateTime + new TimeSpan (rvalue.ValueAsDateTime.Ticks), rvalue.XmlType);
\r
118 case XmlTypeCode.DayTimeDuration:
\r
119 return new XPathAtomicValue (new DateTime (lvalue.ValueAsDateTime.Ticks + rvalue.ValueAsDateTime.Ticks), XmlSchemaSimpleType.XdtDayTimeDuration);
\r
124 throw new XmlQueryException (String.Format ("Not allowed arithmetic operation: {0} + {1}", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r
130 public static XPathAtomicValue Subtract (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
132 // numeric, date, time, dateTime, yearMonthDuration, dayTimeDuration
\r
133 switch (lvalue.XmlType.TypeCode) {
\r
136 case XmlTypeCode.Integer:
\r
137 switch (rvalue.XmlType.TypeCode) {
\r
138 case XmlTypeCode.Integer:
\r
139 return new XPathAtomicValue (lvalue.ValueAsInt64 - rvalue.ValueAsInt64, rvalue.XmlType);
\r
140 case XmlTypeCode.Decimal:
\r
141 return new XPathAtomicValue (lvalue.ValueAsDecimal - rvalue.ValueAsDecimal, rvalue.XmlType);
\r
142 case XmlTypeCode.Float:
\r
143 case XmlTypeCode.Double:
\r
144 return new XPathAtomicValue (lvalue.ValueAsDouble - rvalue.ValueAsDouble, rvalue.XmlType);
\r
148 case XmlTypeCode.Decimal:
\r
149 switch (rvalue.XmlType.TypeCode) {
\r
150 case XmlTypeCode.Integer:
\r
151 case XmlTypeCode.Decimal:
\r
152 return new XPathAtomicValue (lvalue.ValueAsDecimal - rvalue.ValueAsDecimal, rvalue.XmlType);
\r
153 case XmlTypeCode.Float:
\r
154 case XmlTypeCode.Double:
\r
155 return new XPathAtomicValue (lvalue.ValueAsDouble - rvalue.ValueAsDouble, rvalue.XmlType);
\r
159 case XmlTypeCode.Float:
\r
160 case XmlTypeCode.Double:
\r
161 switch (rvalue.XmlType.TypeCode) {
\r
162 case XmlTypeCode.Integer:
\r
163 case XmlTypeCode.Decimal:
\r
164 case XmlTypeCode.Float:
\r
165 case XmlTypeCode.Double:
\r
166 return new XPathAtomicValue (lvalue.ValueAsDouble - rvalue.ValueAsDouble, rvalue.XmlType);
\r
171 case XmlTypeCode.Time:
\r
172 switch (rvalue.XmlType.TypeCode) {
\r
173 case XmlTypeCode.Time:
\r
174 return new XPathAtomicValue (lvalue.ValueAsDateTime - rvalue.ValueAsDateTime, XmlSchemaSimpleType.XdtDayTimeDuration);
\r
175 case XmlTypeCode.DayTimeDuration:
\r
176 return new XPathAtomicValue (lvalue.ValueAsDateTime - new TimeSpan (rvalue.ValueAsDateTime.Ticks), lvalue.XmlType);
\r
180 case XmlTypeCode.DateTime:
\r
181 switch (rvalue.XmlType.TypeCode) {
\r
182 case XmlTypeCode.DateTime:
\r
183 // FIXME: check fn:subtract-daytimes-yielding-dayTimeDuration()
\r
184 return new XPathAtomicValue (lvalue.ValueAsDateTime - rvalue.ValueAsDateTime, XmlSchemaSimpleType.XdtDayTimeDuration);
\r
185 case XmlTypeCode.YearMonthDuration:
\r
186 case XmlTypeCode.DayTimeDuration:
\r
187 return new XPathAtomicValue (lvalue.ValueAsDateTime - new TimeSpan (rvalue.ValueAsDateTime.Ticks), lvalue.XmlType);
\r
191 case XmlTypeCode.Date:
\r
192 switch (rvalue.XmlType.TypeCode) {
\r
193 case XmlTypeCode.Date:
\r
194 // FIXME: check fn:subtract-daytimes-yielding-dayTimeDuration()
\r
195 return new XPathAtomicValue (lvalue.ValueAsDateTime - rvalue.ValueAsDateTime, XmlSchemaSimpleType.XdtDayTimeDuration);
\r
196 case XmlTypeCode.YearMonthDuration:
\r
197 case XmlTypeCode.DayTimeDuration:
\r
198 return new XPathAtomicValue (lvalue.ValueAsDateTime - new TimeSpan (rvalue.ValueAsDateTime.Ticks), lvalue.XmlType);
\r
203 case XmlTypeCode.YearMonthDuration:
\r
204 if (rvalue.XmlType.TypeCode == XmlTypeCode.YearMonthDuration)
\r
205 return new XPathAtomicValue (new TimeSpan (lvalue.ValueAsDateTime.Ticks - rvalue.ValueAsDateTime.Ticks), XmlSchemaSimpleType.XdtYearMonthDuration);
\r
207 case XmlTypeCode.DayTimeDuration:
\r
208 if (rvalue.XmlType.TypeCode == XmlTypeCode.DayTimeDuration)
\r
209 return new XPathAtomicValue (new TimeSpan (lvalue.ValueAsDateTime.Ticks - rvalue.ValueAsDateTime.Ticks), XmlSchemaSimpleType.XdtDayTimeDuration);
\r
213 throw new XmlQueryException (String.Format ("Not allowed arithmetic operation: {0} - {1}", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r
219 public static XPathAtomicValue Multiply (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
221 // numeric, date, time, dateTime, yearMonthDuration, dayTimeDuration
\r
222 switch (lvalue.XmlType.TypeCode) {
\r
225 case XmlTypeCode.Integer:
\r
226 switch (rvalue.XmlType.TypeCode) {
\r
227 case XmlTypeCode.Integer:
\r
228 return new XPathAtomicValue (lvalue.ValueAsInt64 * rvalue.ValueAsInt64, rvalue.XmlType);
\r
229 case XmlTypeCode.Decimal:
\r
230 return new XPathAtomicValue (lvalue.ValueAsDecimal * rvalue.ValueAsDecimal, rvalue.XmlType);
\r
231 case XmlTypeCode.Float:
\r
232 case XmlTypeCode.Double:
\r
233 return new XPathAtomicValue (lvalue.ValueAsDouble * rvalue.ValueAsDouble, rvalue.XmlType);
\r
235 case XmlTypeCode.DayTimeDuration:
\r
236 case XmlTypeCode.YearMonthDuration:
\r
237 goto case XmlTypeCode.Decimal;
\r
241 case XmlTypeCode.Decimal:
\r
242 switch (rvalue.XmlType.TypeCode) {
\r
243 case XmlTypeCode.Integer:
\r
244 case XmlTypeCode.Decimal:
\r
245 return new XPathAtomicValue (lvalue.ValueAsDecimal * rvalue.ValueAsDecimal, rvalue.XmlType);
\r
246 case XmlTypeCode.Float:
\r
247 case XmlTypeCode.Double:
\r
248 return new XPathAtomicValue (lvalue.ValueAsDouble * rvalue.ValueAsDouble, rvalue.XmlType);
\r
250 case XmlTypeCode.YearMonthDuration:
\r
251 case XmlTypeCode.DayTimeDuration:
\r
252 return new XPathAtomicValue (new TimeSpan ((long) (lvalue.ValueAsDateTime.Ticks * rvalue.ValueAsDecimal)), rvalue.XmlType);
\r
256 case XmlTypeCode.Float:
\r
257 case XmlTypeCode.Double:
\r
258 switch (rvalue.XmlType.TypeCode) {
\r
259 case XmlTypeCode.Integer:
\r
260 case XmlTypeCode.Decimal:
\r
261 case XmlTypeCode.Float:
\r
262 case XmlTypeCode.Double:
\r
263 return new XPathAtomicValue (lvalue.ValueAsDouble * rvalue.ValueAsDouble, rvalue.XmlType);
\r
265 case XmlTypeCode.DayTimeDuration:
\r
266 case XmlTypeCode.YearMonthDuration:
\r
267 goto case XmlTypeCode.Decimal;
\r
272 case XmlTypeCode.DayTimeDuration:
\r
273 case XmlTypeCode.YearMonthDuration:
\r
274 switch (rvalue.XmlType.TypeCode) {
\r
275 case XmlTypeCode.Integer:
\r
276 case XmlTypeCode.Decimal:
\r
277 case XmlTypeCode.Float:
\r
278 case XmlTypeCode.Double:
\r
279 return Multiply (rvalue, lvalue);
\r
284 throw new XmlQueryException (String.Format ("Not allowed arithmetic operation: {0} * {1}", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r
290 public static XPathAtomicValue Divide (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
292 // numeric, date, time, dateTime, yearMonthDuration, dayTimeDuration
\r
293 switch (lvalue.XmlType.TypeCode) {
\r
296 case XmlTypeCode.Integer:
\r
297 switch (rvalue.XmlType.TypeCode) {
\r
298 case XmlTypeCode.Integer:
\r
299 return new XPathAtomicValue (lvalue.ValueAsInt64 / rvalue.ValueAsInt64, rvalue.XmlType);
\r
300 case XmlTypeCode.Decimal:
\r
301 return new XPathAtomicValue (lvalue.ValueAsDecimal / rvalue.ValueAsDecimal, rvalue.XmlType);
\r
302 case XmlTypeCode.Float:
\r
303 case XmlTypeCode.Double:
\r
304 return new XPathAtomicValue (lvalue.ValueAsDouble / rvalue.ValueAsDouble, rvalue.XmlType);
\r
308 case XmlTypeCode.Decimal:
\r
309 switch (rvalue.XmlType.TypeCode) {
\r
310 case XmlTypeCode.Integer:
\r
311 case XmlTypeCode.Decimal:
\r
312 return new XPathAtomicValue (lvalue.ValueAsDecimal / rvalue.ValueAsDecimal, rvalue.XmlType);
\r
313 case XmlTypeCode.Float:
\r
314 case XmlTypeCode.Double:
\r
315 return new XPathAtomicValue (lvalue.ValueAsDouble / rvalue.ValueAsDouble, rvalue.XmlType);
\r
319 case XmlTypeCode.Float:
\r
320 case XmlTypeCode.Double:
\r
321 switch (rvalue.XmlType.TypeCode) {
\r
322 case XmlTypeCode.Integer:
\r
323 case XmlTypeCode.Decimal:
\r
324 case XmlTypeCode.Float:
\r
325 case XmlTypeCode.Double:
\r
326 return new XPathAtomicValue (lvalue.ValueAsDouble / rvalue.ValueAsDouble, rvalue.XmlType);
\r
328 case XmlTypeCode.DayTimeDuration:
\r
329 case XmlTypeCode.YearMonthDuration:
\r
330 goto case XmlTypeCode.Decimal;
\r
335 case XmlTypeCode.DayTimeDuration:
\r
336 case XmlTypeCode.YearMonthDuration:
\r
337 switch (rvalue.XmlType.TypeCode) {
\r
338 case XmlTypeCode.Integer:
\r
339 case XmlTypeCode.Decimal:
\r
340 case XmlTypeCode.Float:
\r
341 case XmlTypeCode.Double:
\r
342 return new XPathAtomicValue (new DateTime ((long) (lvalue.ValueAsDateTime.Ticks / rvalue.ValueAsDouble)), rvalue.XmlType);
\r
347 throw new XmlQueryException (String.Format ("Not allowed arithmetic operation: {0} div {1}", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r
353 public static XPathAtomicValue IntDivide (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
355 return new XPathAtomicValue (lvalue.ValueAsInt64 / rvalue.ValueAsInt64, XmlSchemaSimpleType.XsInteger);
\r
361 public static XPathAtomicValue Remainder (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
363 return new XPathAtomicValue (lvalue.ValueAsInt64 % rvalue.ValueAsInt64, XmlSchemaSimpleType.XsInteger);
\r