1 using System;
2 using System.Collections;
3 using System.IO;
4
5
6
7
8
9 namespace System.XPath
10 {
11 using Axis = System.Dom.Axis;
12 using NodeType = System.Dom.NodeType;
13 public enum Operator
14 {
15 equal, notEqual, less, greater, lessOrEqual, greaterOrEqual, plus, minus, mul, div, mod, slash, slashSlash
16 }
17 public abstract class XPathExpr
18 {
19 public suppress XPathExpr(const XPathExpr&);
20 public suppress XPathExpr(XPathExpr&&);
21 public XPathExpr()
22 {
23 }
24 public virtual ~XPathExpr()
25 {
26 }
27 public suppress XPathExpr& operator=(const XPathExpr&);
28 public suppress XPathExpr&& operator=(XPathExpr&&);
29 public virtual UniquePtr<XPathObject> Evaluate(XPathContext& context)
30 {
31 return UniquePtr<XPathObject>();
32 }
33 public virtual ustring TextValue() const
34 {
35 return ustring();
36 }
37 public abstract UniquePtr<System.Dom.Node> ToDom() const;
38 }
39 public abstract class XPathUnaryExpr : XPathExpr
40 {
41 public XPathUnaryExpr(XPathExpr* operand_) :
42 operand(operand_)
43 {
44 }
45 public XPathExpr* Operand() const
46 {
47 return operand.Get();
48 }
49 private UniquePtr<XPathExpr> operand;
50 }
51 public abstract class XPathBinaryExpr : XPathExpr
52 {
53 public XPathBinaryExpr(XPathExpr* left_, XPathExpr* right_) :
54 left(left_), right(right_)
55 {
56 }
57 public XPathExpr* Left() const
58 {
59 return left.Get();
60 }
61 public XPathExpr* Right() const
62 {
63 return right.Get();
64 }
65 private UniquePtr<XPathExpr> left;
66 private UniquePtr<XPathExpr> right;
67 }
68 public class XPathOrExpr : XPathBinaryExpr
69 {
70 public XPathOrExpr(XPathExpr* left_, XPathExpr* right_) :
71 base(left_, right_)
72 {
73 }
74 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
75 {
76 XPathFunction* boolean = GetXPathLibraryFunction(u"boolean");
77 UniquePtr<XPathObject> left = Left()->Evaluate(context);
78 List<XPathObject*> leftArgs;
79 leftArgs.Add(left.Get());
80 UniquePtr<XPathObject> leftAsBoolean = boolean->Evaluate(context, leftArgs);
81 if (leftAsBoolean->Type() != XPathObjectType.boolean)
82 {
83 throw Exception("boolean result expected");
84 }
85 if (cast<XPathBoolean*>(leftAsBoolean.Get())->Value())
86 {
87 return leftAsBoolean;
88 }
89 UniquePtr<XPathObject> right = Right()->Evaluate(context);
90 List<XPathObject*> rightArgs;
91 rightArgs.Add(right.Get());
92 UniquePtr<XPathObject> rightAsBoolean = boolean->Evaluate(context, rightArgs);
93 if (rightAsBoolean->Type() != XPathObjectType.boolean)
94 {
95 throw Exception("boolean result expected");
96 }
97 return rightAsBoolean;
98 }
99 public override UniquePtr<System.Dom.Node> ToDom() const
100 {
101 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"or"));
102 element->AppendChild(Left()->ToDom());
103 element->AppendChild(Right()->ToDom());
104 return UniquePtr<System.Dom.Node>(element.Release());
105 }
106 }
107 public class XPathAndExpr : XPathBinaryExpr
108 {
109 public XPathAndExpr(XPathExpr* left_, XPathExpr* right_) :
110 base(left_, right_)
111 {
112 }
113 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
114 {
115 XPathFunction* boolean = GetXPathLibraryFunction(u"boolean");
116 UniquePtr<XPathObject> left = Left()->Evaluate(context);
117 List<XPathObject*> leftArgs;
118 leftArgs.Add(left.Get());
119 UniquePtr<XPathObject> leftAsBoolean = boolean->Evaluate(context, leftArgs);
120 if (leftAsBoolean->Type() != XPathObjectType.boolean)
121 {
122 throw Exception("boolean result expected");
123 }
124 if (!cast<XPathBoolean*>(leftAsBoolean.Get())->Value())
125 {
126 return leftAsBoolean;
127 }
128 UniquePtr<XPathObject> right = Right()->Evaluate(context);
129 List<XPathObject*> rightArgs;
130 rightArgs.Add(right.Get());
131 UniquePtr<XPathObject> rightAsBoolean = boolean->Evaluate(context, rightArgs);
132 if (rightAsBoolean->Type() != XPathObjectType.boolean)
133 {
134 throw Exception("boolean result expected");
135 }
136 return rightAsBoolean;
137 }
138 public override UniquePtr<System.Dom.Node> ToDom() const
139 {
140 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"and"));
141 element->AppendChild(Left()->ToDom());
142 element->AppendChild(Right()->ToDom());
143 return UniquePtr<System.Dom.Node>(element.Release());
144 }
145 }
146 public class XPathEqualExpr : XPathBinaryExpr
147 {
148 public XPathEqualExpr(XPathExpr* left_, XPathExpr* right_) :
149 base(left_, right_)
150 {
151 }
152 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
153 {
154 UniquePtr<XPathObject> left = Left()->Evaluate(context);
155 UniquePtr<XPathObject> right = Right()->Evaluate(context);
156 return CompareEquality(context, left.Get(), right.Get());
157 }
158 public override UniquePtr<System.Dom.Node> ToDom() const
159 {
160 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"equal"));
161 element->AppendChild(Left()->ToDom());
162 element->AppendChild(Right()->ToDom());
163 return UniquePtr<System.Dom.Node>(element.Release());
164 }
165 }
166 public class XPathNotEqualExpr : XPathBinaryExpr
167 {
168 public XPathNotEqualExpr(XPathExpr* left_, XPathExpr* right_) :
169 base(left_, right_)
170 {
171 }
172 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
173 {
174 UniquePtr<XPathObject> left = Left()->Evaluate(context);
175 UniquePtr<XPathObject> right = Right()->Evaluate(context);
176 UniquePtr<XPathObject> equal = CompareEquality(context, left.Get(), right.Get());
177 if (equal->Type() != XPathObjectType.boolean)
178 {
179 throw Exception("boolean result expected");
180 }
181 return UniquePtr<XPathObject>(new XPathBoolean(!cast<XPathBoolean*>(equal.Get())->Value()));
182 }
183 public override UniquePtr<System.Dom.Node> ToDom() const
184 {
185 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"notEqual"));
186 element->AppendChild(Left()->ToDom());
187 element->AppendChild(Right()->ToDom());
188 return UniquePtr<System.Dom.Node>(element.Release());
189 }
190 }
191 public class XPathLessExpr : XPathBinaryExpr
192 {
193 public XPathLessExpr(XPathExpr* left_, XPathExpr* right_) :
194 base(left_, right_)
195 {
196 }
197 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
198 {
199 UniquePtr<XPathObject> left = Left()->Evaluate(context);
200 UniquePtr<XPathObject> right = Right()->Evaluate(context);
201 return Compare(context, left.Get(), right.Get(), Operator.less);
202 }
203 public override UniquePtr<System.Dom.Node> ToDom() const
204 {
205 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"less"));
206 element->AppendChild(Left()->ToDom());
207 element->AppendChild(Right()->ToDom());
208 return UniquePtr<System.Dom.Node>(element.Release());
209 }
210 }
211 public class XPathGreaterExpr : XPathBinaryExpr
212 {
213 public XPathGreaterExpr(XPathExpr* left_, XPathExpr* right_) :
214 base(left_, right_)
215 {
216 }
217 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
218 {
219 UniquePtr<XPathObject> left = Left()->Evaluate(context);
220 UniquePtr<XPathObject> right = Right()->Evaluate(context);
221 return Compare(context, left.Get(), right.Get(), Operator.greater);
222 }
223 public override UniquePtr<System.Dom.Node> ToDom() const
224 {
225 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"greater"));
226 element->AppendChild(Left()->ToDom());
227 element->AppendChild(Right()->ToDom());
228 return UniquePtr<System.Dom.Node>(element.Release());
229 }
230 }
231 public class XPathLessOrEqualExpr : XPathBinaryExpr
232 {
233 public XPathLessOrEqualExpr(XPathExpr* left_, XPathExpr* right_) :
234 base(left_, right_)
235 {
236 }
237 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
238 {
239 UniquePtr<XPathObject> left = Left()->Evaluate(context);
240 UniquePtr<XPathObject> right = Right()->Evaluate(context);
241 return Compare(context, left.Get(), right.Get(), Operator.lessOrEqual);
242 }
243 public override UniquePtr<System.Dom.Node> ToDom() const
244 {
245 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"lessOrEqual"));
246 element->AppendChild(Left()->ToDom());
247 element->AppendChild(Right()->ToDom());
248 return UniquePtr<System.Dom.Node>(element.Release());
249 }
250 }
251 public class XPathGreaterOrEqualExpr : XPathBinaryExpr
252 {
253 public XPathGreaterOrEqualExpr(XPathExpr* left_, XPathExpr* right_) :
254 base(left_, right_)
255 {
256 }
257 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
258 {
259 UniquePtr<XPathObject> left = Left()->Evaluate(context);
260 UniquePtr<XPathObject> right = Right()->Evaluate(context);
261 return Compare(context, left.Get(), right.Get(), Operator.greaterOrEqual);
262 }
263 public override UniquePtr<System.Dom.Node> ToDom() const
264 {
265 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"greaterOrEqual"));
266 element->AppendChild(Left()->ToDom());
267 element->AppendChild(Right()->ToDom());
268 return UniquePtr<System.Dom.Node>(element.Release());
269 }
270 }
271 public class XPathAddExpr : XPathBinaryExpr
272 {
273 public XPathAddExpr(XPathExpr* left_, XPathExpr* right_) :
274 base(left_, right_)
275 {
276 }
277 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
278 {
279 UniquePtr<XPathObject> left = Left()->Evaluate(context);
280 UniquePtr<XPathObject> right = Right()->Evaluate(context);
281 XPathFunction* numberFunction = GetXPathLibraryFunction(u"number");
282 List<XPathObject*> leftArgs;
283 leftArgs.Add(left.Get());
284 UniquePtr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
285 if (leftAsNumber->Type() != XPathObjectType.number)
286 {
287 throw Exception("number result expected");
288 }
289 double leftNumber = cast<XPathNumber*>(leftAsNumber.Get())->Value();
290 List<XPathObject*> rightArgs;
291 rightArgs.Add(right.Get());
292 UniquePtr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
293 if (rightAsNumber->Type() != XPathObjectType.number)
294 {
295 throw Exception("number result expected");
296 }
297 double rightNumber = cast<XPathNumber*>(rightAsNumber.Get())->Value();
298 return UniquePtr<XPathObject>(new XPathNumber(leftNumber + rightNumber));
299 }
300 public override UniquePtr<System.Dom.Node> ToDom() const
301 {
302 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"add"));
303 element->AppendChild(Left()->ToDom());
304 element->AppendChild(Right()->ToDom());
305 return UniquePtr<System.Dom.Node>(element.Release());
306 }
307 }
308 public class XPathSubExpr : XPathBinaryExpr
309 {
310 public XPathSubExpr(XPathExpr* left_, XPathExpr* right_) :
311 base(left_, right_)
312 {
313 }
314 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
315 {
316 UniquePtr<XPathObject> left = Left()->Evaluate(context);
317 UniquePtr<XPathObject> right = Right()->Evaluate(context);
318 XPathFunction* numberFunction = GetXPathLibraryFunction(u"number");
319 List<XPathObject*> leftArgs;
320 leftArgs.Add(left.Get());
321 UniquePtr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
322 if (leftAsNumber->Type() != XPathObjectType.number)
323 {
324 throw Exception("number result expected");
325 }
326 double leftNumber = cast<XPathNumber*>(leftAsNumber.Get())->Value();
327 List<XPathObject*> rightArgs;
328 rightArgs.Add(right.Get());
329 UniquePtr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
330 if (rightAsNumber->Type() != XPathObjectType.number)
331 {
332 throw Exception("number result expected");
333 }
334 double rightNumber = cast<XPathNumber*>(rightAsNumber.Get())->Value();
335 return UniquePtr<XPathObject>(new XPathNumber(leftNumber - rightNumber));
336 }
337 public override UniquePtr<System.Dom.Node> ToDom() const
338 {
339 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"sub"));
340 element->AppendChild(Left()->ToDom());
341 element->AppendChild(Right()->ToDom());
342 return UniquePtr<System.Dom.Node>(element.Release());
343 }
344 }
345 public class XPathMulExpr : XPathBinaryExpr
346 {
347 public XPathMulExpr(XPathExpr* left_, XPathExpr* right_) :
348 base(left_, right_)
349 {
350 }
351 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
352 {
353 UniquePtr<XPathObject> left = Left()->Evaluate(context);
354 UniquePtr<XPathObject> right = Right()->Evaluate(context);
355 XPathFunction* numberFunction = GetXPathLibraryFunction(u"number");
356 List<XPathObject*> leftArgs;
357 leftArgs.Add(left.Get());
358 UniquePtr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
359 if (leftAsNumber->Type() != XPathObjectType.number)
360 {
361 throw Exception("number result expected");
362 }
363 double leftNumber = cast<XPathNumber*>(leftAsNumber.Get())->Value();
364 List<XPathObject*> rightArgs;
365 rightArgs.Add(right.Get());
366 UniquePtr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
367 if (rightAsNumber->Type() != XPathObjectType.number)
368 {
369 throw Exception("number result expected");
370 }
371 double rightNumber = cast<XPathNumber*>(rightAsNumber.Get())->Value();
372 return UniquePtr<XPathObject>(new XPathNumber(leftNumber * rightNumber));
373 }
374 public override UniquePtr<System.Dom.Node> ToDom() const
375 {
376 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"mul"));
377 element->AppendChild(Left()->ToDom());
378 element->AppendChild(Right()->ToDom());
379 return UniquePtr<System.Dom.Node>(element.Release());
380 }
381 }
382 public class XPathDivExpr : XPathBinaryExpr
383 {
384 public XPathDivExpr(XPathExpr* left_, XPathExpr* right_) :
385 base(left_, right_)
386 {
387 }
388 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
389 {
390 UniquePtr<XPathObject> left = Left()->Evaluate(context);
391 UniquePtr<XPathObject> right = Right()->Evaluate(context);
392 XPathFunction* numberFunction = GetXPathLibraryFunction(u"number");
393 List<XPathObject*> leftArgs;
394 leftArgs.Add(left.Get());
395 UniquePtr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
396 if (leftAsNumber->Type() != XPathObjectType.number)
397 {
398 throw Exception("number result expected");
399 }
400 double leftNumber = cast<XPathNumber*>(leftAsNumber.Get())->Value();
401 List<XPathObject*> rightArgs;
402 rightArgs.Add(right.Get());
403 UniquePtr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
404 if (rightAsNumber->Type() != XPathObjectType.number)
405 {
406 throw Exception("number result expected");
407 }
408 double rightNumber = cast<XPathNumber*>(rightAsNumber.Get())->Value();
409 return UniquePtr<XPathObject>(new XPathNumber(leftNumber / rightNumber));
410 }
411 public override UniquePtr<System.Dom.Node> ToDom() const
412 {
413 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"div"));
414 element->AppendChild(Left()->ToDom());
415 element->AppendChild(Right()->ToDom());
416 return UniquePtr<System.Dom.Node>(element.Release());
417 }
418 }
419 public class XPathModExpr : XPathBinaryExpr
420 {
421 public XPathModExpr(XPathExpr* left_, XPathExpr* right_) :
422 base(left_, right_)
423 {
424 }
425 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
426 {
427 UniquePtr<XPathObject> left = Left()->Evaluate(context);
428 UniquePtr<XPathObject> right = Right()->Evaluate(context);
429 XPathFunction* numberFunction = GetXPathLibraryFunction(u"number");
430 List<XPathObject*> leftArgs;
431 leftArgs.Add(left.Get());
432 UniquePtr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
433 if (leftAsNumber->Type() != XPathObjectType.number)
434 {
435 throw Exception("number result expected");
436 }
437 long leftNumber = cast<long>(cast<XPathNumber*>(leftAsNumber.Get())->Value());
438 List<XPathObject*> rightArgs;
439 rightArgs.Add(right.Get());
440 UniquePtr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
441 if (rightAsNumber->Type() != XPathObjectType.number)
442 {
443 throw Exception("number result expected");
444 }
445 long rightNumber = cast<long>(cast<XPathNumber*>(rightAsNumber.Get())->Value());
446 return UniquePtr<XPathObject>(new XPathNumber(double(leftNumber % rightNumber)));
447 }
448 public override UniquePtr<System.Dom.Node> ToDom() const
449 {
450 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"mod"));
451 element->AppendChild(Left()->ToDom());
452 element->AppendChild(Right()->ToDom());
453 return UniquePtr<System.Dom.Node>(element.Release());
454 }
455 }
456 public class XPathUnaryMinusExpr : XPathUnaryExpr
457 {
458 public XPathUnaryMinusExpr(XPathExpr* operand_) :
459 base(operand_)
460 {
461 }
462 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
463 {
464 UniquePtr<XPathObject> operand = Operand()->Evaluate(context);
465 XPathFunction* numberFunction = GetXPathLibraryFunction(u"number");
466 List<XPathObject*> operandArgs;
467 operandArgs.Add(operand.Get());
468 UniquePtr<XPathObject> operandAsNumber = numberFunction->Evaluate(context, operandArgs);
469 if (operandAsNumber->Type() != XPathObjectType.number)
470 {
471 throw Exception("number result expected");
472 }
473 double operandNumber = cast<XPathNumber*>(operandAsNumber.Get())->Value();
474 return UniquePtr<XPathObject>(new XPathNumber(-operandNumber));
475 }
476 public override UniquePtr<System.Dom.Node> ToDom() const
477 {
478 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"unaryMinus"));
479 element->AppendChild(Operand()->ToDom());
480 return UniquePtr<System.Dom.Node>(element.Release());
481 }
482 }
483 public class XPathUnionExpr : XPathBinaryExpr
484 {
485 public XPathUnionExpr(XPathExpr* left_, XPathExpr* right_) :
486 base(left_, right_)
487 {
488 }
489 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
490 {
491 UniquePtr<XPathNodeSet> result(new XPathNodeSet());
492 UniquePtr<XPathObject> leftResult = Left()->Evaluate(context);
493 if (leftResult->Type() != XPathObjectType.nodeSet)
494 {
495 throw Exception("node set expected");
496 }
497 XPathNodeSet* leftNodeSet = cast<XPathNodeSet*>(leftResult.Get());
498 int n = leftNodeSet->Length();
499 for (int i = 0; i < n; ++i;)
500 {
501 result->Add((*leftNodeSet)[i]);
502 }
503 UniquePtr<XPathObject> rightResult = Right()->Evaluate(context);
504 if (rightResult->Type() != XPathObjectType.nodeSet)
505 {
506 throw Exception("node set expected");
507 }
508 XPathNodeSet* rightNodeSet = cast<XPathNodeSet*>(rightResult.Get());
509 int m = rightNodeSet->Length();
510 for (int i = 0; i < m; ++i;)
511 {
512 result->Add((*rightNodeSet)[i]);
513 }
514 return UniquePtr<XPathObject>(result.Release());
515 }
516 public override UniquePtr<System.Dom.Node> ToDom() const
517 {
518 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"union"));
519 element->AppendChild(Left()->ToDom());
520 element->AppendChild(Right()->ToDom());
521 return UniquePtr<System.Dom.Node>(element.Release());
522 }
523 }
524 public class XPathCombineStepExpr : XPathBinaryExpr
525 {
526 public XPathCombineStepExpr(XPathExpr* left_, XPathExpr* right_) :
527 base(left_, right_)
528 {
529 }
530 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
531 {
532 UniquePtr<XPathNodeSet> result(new XPathNodeSet());
533 UniquePtr<XPathObject> leftResult = Left()->Evaluate(context);
534 if (leftResult->Type() != XPathObjectType.nodeSet)
535 {
536 throw Exception("node set expected");
537 }
538 XPathNodeSet* leftNodeSet = cast<XPathNodeSet*>(leftResult.Get());
539 int n = leftNodeSet->Length();
540 for (int i = 0; i < n; ++i;)
541 {
542 System.Dom.Node* node = (*leftNodeSet)[i];
543 XPathContext rightContext(node, i + 1, n);
544 UniquePtr<XPathObject> rightResult = Right()->Evaluate(rightContext);
545 if (rightResult->Type() != XPathObjectType.nodeSet)
546 {
547 throw Exception("node set expected");
548 }
549 XPathNodeSet* rightNodeSet = cast<XPathNodeSet*>(rightResult.Get());
550 int m = rightNodeSet->Length();
551 for (int i = 0; i < m; ++i;)
552 {
553 System.Dom.Node* node = (*rightNodeSet)[i];
554 result->Add(node);
555 }
556 }
557 return UniquePtr<XPathObject>(result.Release());
558 }
559 public override UniquePtr<System.Dom.Node> ToDom() const
560 {
561 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"combineStep"));
562 element->AppendChild(Left()->ToDom());
563 element->AppendChild(Right()->ToDom());
564 return UniquePtr<System.Dom.Node>(element.Release());
565 }
566 }
567 public class XPathRootNodeExpr : XPathExpr
568 {
569 public XPathRootNodeExpr()
570 {
571 }
572 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
573 {
574 UniquePtr<XPathNodeSet> nodeSet(new XPathNodeSet());
575 if (context.Node()->GetNodeType() == NodeType.documentNode)
576 {
577 nodeSet->Add(context.Node());
578 }
579 else
580 {
581 nodeSet->Add(context.Node()->OwnerDocument());
582 }
583 return UniquePtr<XPathObject>(nodeSet.Release());
584 }
585 public override UniquePtr<System.Dom.Node> ToDom() const
586 {
587 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"root"));
588 return UniquePtr<System.Dom.Node>(element.Release());
589 }
590 }
591 public class XPathFilterExpr : XPathUnaryExpr
592 {
593 public XPathFilterExpr(XPathExpr* expr_, XPathExpr* predicate_) :
594 base(expr_), predicate(predicate_)
595 {
596 }
597 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
598 {
599 UniquePtr<XPathObject> result = Operand()->Evaluate(context);
600 if (result->Type() != XPathObjectType.nodeSet)
601 {
602 throw Exception("node-set expected");
603 }
604 UniquePtr<XPathNodeSet> nodeSet(cast<XPathNodeSet*>(result.Release()));
605 UniquePtr<XPathNodeSet> filteredNodeSet(new XPathNodeSet());
606 int n = nodeSet->Length();
607 for (int i = 0; i < n; ++i;)
608 {
609 System.Dom.Node* node = (*nodeSet)[i];
610 XPathContext context(node, i + 1, n);
611 UniquePtr<XPathObject> result = predicate->Evaluate(context);
612 bool booleanResult = false;
613 if (result->Type() == XPathObjectType.number)
614 {
615 XPathNumber* number = cast<XPathNumber*>(result.Get());
616 if (number->Value() == context.Position())
617 {
618 booleanResult = true;
619 }
620 }
621 else
622 {
623 XPathFunction* boolean = GetXPathLibraryFunction(u"boolean");
624 List<XPathObject*> args;
625 args.Add(result.Get());
626 UniquePtr<XPathObject> resultAsBoolean = boolean->Evaluate(context, args);
627 booleanResult = cast<XPathBoolean*>(resultAsBoolean.Get())->Value();
628 }
629 if (booleanResult)
630 {
631 filteredNodeSet->Add(node);
632 }
633 }
634 Swap(nodeSet, filteredNodeSet);
635 return UniquePtr<XPathObject>(nodeSet.Release());
636 }
637 public override UniquePtr<System.Dom.Node> ToDom() const
638 {
639 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"filter"));
640 element->AppendChild(Operand()->ToDom());
641 UniquePtr<System.Dom.Element> predicateElement(new System.Dom.Element(u"predicate"));
642 predicateElement->AppendChild(predicate->ToDom());
643 element->AppendChild(UniquePtr<System.Dom.Node>(predicateElement.Release()));
644 return UniquePtr<System.Dom.Node>(element.Release());
645 }
646 private UniquePtr<XPathExpr> predicate;
647 }
648 public abstract class XPathNodeTestExpr : XPathExpr
649 {
650 public virtual bool Select(System.Dom.Node* node, System.Dom.Axis axis) const
651 {
652 return true;
653 }
654 }
655 public class XPathLocationStepExpr : XPathExpr
656 {
657 public suppress XPathLocationStepExpr(const XPathLocationStepExpr&);
658 public suppress XPathLocationStepExpr(XPathLocationStepExpr&&);
659 public XPathLocationStepExpr(System.Dom.Axis axis_, XPathNodeTestExpr* nodeTest_) :
660 axis(axis_), nodeTest(nodeTest_)
661 {
662 }
663 public suppress XPathLocationStepExpr& operator=(const XPathLocationStepExpr&);
664 public suppress XPathLocationStepExpr&& operator=(XPathLocationStepExpr&&);
665 public void AddPredicate(XPathExpr* predicate)
666 {
667 predicates.Add(UniquePtr<XPathExpr>(predicate));
668 }
669 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
670 {
671 UniquePtr<XPathNodeSet> nodeSet(new XPathNodeSet());
672 NodeSelectionOp selectNodes(nodeTest.Get(), *nodeSet, axis);
673 context.Node()->Walk(selectNodes, axis);
674 for (const UniquePtr<XPathExpr>& predicate : predicates)
675 {
676 UniquePtr<XPathNodeSet> filteredNodeSet(new XPathNodeSet());
677 int n = nodeSet->Length();
678 for (int i = 0; i < n; ++i;)
679 {
680 System.Dom.Node* node = (*nodeSet)[i];
681 XPathContext context(node, i + 1, n);
682 UniquePtr<XPathObject> result = predicate->Evaluate(context);
683 bool booleanResult = false;
684 if (result->Type() == XPathObjectType.number)
685 {
686 XPathNumber* number = cast<XPathNumber*>(result.Get());
687 if (number->Value() == context.Position())
688 {
689 booleanResult = true;
690 }
691 }
692 else
693 {
694 XPathFunction* boolean = GetXPathLibraryFunction(u"boolean");
695 List<XPathObject*> args;
696 args.Add(result.Get());
697 UniquePtr<XPathObject> resultAsBoolean = boolean->Evaluate(context, args);
698 booleanResult = cast<XPathBoolean*>(resultAsBoolean.Get())->Value();
699 }
700 if (booleanResult)
701 {
702 filteredNodeSet->Add(node);
703 }
704 }
705 Swap(nodeSet, filteredNodeSet);
706 }
707 return UniquePtr<XPathObject>(nodeSet.Release());
708 }
709 public override UniquePtr<System.Dom.Node> ToDom() const
710 {
711 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"locationStep"));
712 System.Dom.Element* axisElement = new System.Dom.Element(u"axis");
713 ustring axisName = System.Dom.AxisName(axis);
714 axisElement->SetAttribute(u"name", axisName);
715 element->AppendChild(UniquePtr<System.Dom.Node>(axisElement));
716 System.Dom.Element* nodeTestElement = new System.Dom.Element(u"nodeTest");
717 nodeTestElement->AppendChild(nodeTest->ToDom());
718 element->AppendChild(UniquePtr<System.Dom.Node>(nodeTestElement));
719 UniquePtr<System.Dom.Element> predicatesElement(new System.Dom.Element(u"predicates"));
720 for (const UniquePtr<XPathExpr>& predicate : predicates)
721 {
722 predicatesElement->AppendChild(predicate->ToDom());
723 }
724 element->AppendChild(UniquePtr<System.Dom.Node>(predicatesElement.Release()));
725 return UniquePtr<System.Dom.Node>(element.Release());
726 }
727 private System.Dom.Axis axis;
728 private UniquePtr<XPathNodeTestExpr> nodeTest;
729 private List<UniquePtr<XPathExpr>> predicates;
730 }
731 public class XPathPILiteralTest : XPathNodeTestExpr
732 {
733 public XPathPILiteralTest(XPathExpr* literal_) :
734 literal(literal_)
735 {
736 }
737 public override bool Select(System.Dom.Node* node, System.Dom.Axis axis) const
738 {
739 if (node->GetNodeType() == NodeType.processingInstructionNode)
740 {
741 System.Dom.ProcessingInstruction* pi = cast<System.Dom.ProcessingInstruction*>(node);
742 if (pi->Target() == literal->TextValue())
743 {
744 return true;
745 }
746 }
747 return false;
748 }
749 public override UniquePtr<System.Dom.Node> ToDom() const
750 {
751 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"piLiteralTest"));
752 element->AppendChild(literal->ToDom());
753 return UniquePtr<System.Dom.Node>(element.Release());
754 }
755 private UniquePtr<XPathExpr> literal;
756 }
757 public class XPathCommentNodeTest : XPathNodeTestExpr
758 {
759 public override bool Select(System.Dom.Node* node, System.Dom.Axis axis) const
760 {
761 return node->GetNodeType() == NodeType.commentNode;
762 }
763 public override UniquePtr<System.Dom.Node> ToDom() const
764 {
765 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"commentNodeTest"));
766 return UniquePtr<System.Dom.Node>(element.Release());
767 }
768 }
769 public class XPathTextNodeTest : XPathNodeTestExpr
770 {
771 public override bool Select(System.Dom.Node* node, System.Dom.Axis axis) const
772 {
773 return node->GetNodeType() == NodeType.textNode;
774 }
775 public override UniquePtr<System.Dom.Node> ToDom() const
776 {
777 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"textNodeTest"));
778 return UniquePtr<System.Dom.Node>(element.Release());
779 }
780 }
781 public class XPathPINodeTest : XPathNodeTestExpr
782 {
783 public override bool Select(System.Dom.Node* node, System.Dom.Axis axis) const
784 {
785 return node->GetNodeType() == NodeType.processingInstructionNode;
786 }
787 public override UniquePtr<System.Dom.Node> ToDom() const
788 {
789 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"piNodeTest"));
790 return UniquePtr<System.Dom.Node>(element.Release());
791 }
792 }
793 public class XPathAnyNodeTest : XPathNodeTestExpr
794 {
795 public override bool Select(System.Dom.Node* node, System.Dom.Axis axis) const
796 {
797 return true;
798 }
799 public override UniquePtr<System.Dom.Node> ToDom() const
800 {
801 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"anyNodeTest"));
802 return UniquePtr<System.Dom.Node>(element.Release());
803 }
804 }
805 public class XPathPrincipalNodeTest : XPathNodeTestExpr
806 {
807 public override bool Select(System.Dom.Node* node, System.Dom.Axis axis) const
808 {
809 if (axis == Axis.attribute)
810 {
811 return node->GetNodeType() == NodeType.attributeNode;
812 }
813 else if (axis == Axis.ns)
814 {
815 return false;
816 }
817 else
818 {
819 return node->GetNodeType() == NodeType.elementNode;
820 }
821 }
822 public override UniquePtr<System.Dom.Node> ToDom() const
823 {
824 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"principalNodeTest"));
825 return UniquePtr<System.Dom.Node>(element.Release());
826 }
827 }
828 public class XPathPrefixTest : XPathNodeTestExpr
829 {
830 public XPathPrefixTest(const ustring& name_) :
831 name(name_)
832 {
833 }
834 public override bool Select(System.Dom.Node* node, System.Dom.Axis axis) const
835 {
836 if (axis == Axis.attribute)
837 {
838 if (node->GetNodeType() == NodeType.attributeNode)
839 {
840 System.Dom.Attr* attr = cast<System.Dom.Attr*>(node);
841 if (attr->Prefix() == name)
842 {
843 return true;
844 }
845 }
846 }
847 else if (axis == Axis.ns)
848 {
849 return false;
850 }
851 else if (node->GetNodeType() == NodeType.elementNode)
852 {
853 System.Dom.Element* element = cast<System.Dom.Element*>(node);
854 if (element->Prefix() == name)
855 {
856 return true;
857 }
858 }
859 return false;
860 }
861 public override UniquePtr<System.Dom.Node> ToDom() const
862 {
863 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"prefixTest"));
864 element->SetAttribute(u"prefix", name);
865 return UniquePtr<System.Dom.Node>(element.Release());
866 }
867 private ustring name;
868 }
869 public class XPathNameTest : XPathNodeTestExpr
870 {
871 public XPathNameTest(const ustring& name_) :
872 name(name_)
873 {
874 }
875 public override bool Select(System.Dom.Node* node, System.Dom.Axis axis) const
876 {
877 if (axis == Axis.attribute)
878 {
879 if (node->GetNodeType() == NodeType.attributeNode)
880 {
881 System.Dom.Attr* attr = cast<System.Dom.Attr*>(node);
882 if (attr->Name() == name)
883 {
884 return true;
885 }
886 }
887 }
888 else if (axis != Axis.ns)
889 {
890 if (node->GetNodeType() == NodeType.elementNode)
891 {
892 System.Dom.Element* element = cast<System.Dom.Element*>(node);
893 if (element->Name() == name)
894 {
895 return true;
896 }
897 }
898 }
899 return false;
900 }
901 public override UniquePtr<System.Dom.Node> ToDom() const
902 {
903 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"nameTest"));
904 element->SetAttribute(u"name", name);
905 return UniquePtr<System.Dom.Node>(element.Release());
906 }
907 private ustring name;
908 }
909 public class XPathVariableReference : XPathExpr
910 {
911 public XPathVariableReference(const ustring& name_) :
912 name(name_)
913 {
914 }
915 public override UniquePtr<System.Dom.Node> ToDom() const
916 {
917 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"variableReference"));
918 element->SetAttribute(u"name", name);
919 return UniquePtr<System.Dom.Node>(element.Release());
920 }
921 private ustring name;
922 }
923 public class XPathLiteral : XPathExpr
924 {
925 public XPathLiteral(const ustring& value_) :
926 value(value_)
927 {
928 }
929 public override ustring TextValue() const
930 {
931 return value;
932 }
933 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
934 {
935 return UniquePtr<XPathObject>(new XPathString(value));
936 }
937 public override UniquePtr<System.Dom.Node> ToDom() const
938 {
939 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"literal"));
940 element->SetAttribute(u"value", value);
941 return UniquePtr<System.Dom.Node>(element.Release());
942 }
943 private ustring value;
944 }
945 public class XPathNumberExpr : XPathExpr
946 {
947 public XPathNumberExpr(const ustring& value_)
948 {
949 string s = ToUtf8(value_);
950 value = ParseDouble(ToUtf8(value_));
951 }
952 public XPathNumberExpr(double value_) :
953 value(value_)
954 {
955 }
956 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
957 {
958 return UniquePtr<XPathObject>(new XPathNumber(value));
959 }
960 public override UniquePtr<System.Dom.Node> ToDom() const
961 {
962 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"number"));
963 element->SetAttribute(u"value", ToUtf32(ToString(value)));
964 return UniquePtr<System.Dom.Node>(element.Release());
965 }
966 private double value;
967 }
968 public class XPathFunctionCall : XPathExpr
969 {
970 public XPathFunctionCall(const ustring& functionName_) :
971 functionName(functionName_)
972 {
973 }
974 public void AddArgument(XPathExpr* argument)
975 {
976 arguments.Add(UniquePtr<XPathExpr>(argument));
977 }
978 public override UniquePtr<XPathObject> Evaluate(XPathContext& context)
979 {
980 XPathFunction* function = GetXPathLibraryFunction(functionName);
981 if (arguments.Count() < function->MinArity() || arguments.Count() > function->MaxArity())
982 {
983 throw Exception("function \'" + ToUtf8(functionName) + "\' takes " + ToString(function->MinArity()) + "..." + ToString(function->MaxArity()) + " arguments (" + ToString(arguments.Count()) + " arguments provided)");
984 }
985 List<UniquePtr<XPathObject>> ownedArgs;
986 List<XPathObject*> args;
987 for (const UniquePtr<XPathExpr>& argument : arguments)
988 {
989 UniquePtr<XPathObject> arg = argument->Evaluate(context);
990 args.Add(arg.Get());
991 ownedArgs.Add(Rvalue(arg));
992 }
993 UniquePtr<XPathObject> result = function->Evaluate(context, args);
994 return result;
995 }
996 public override UniquePtr<System.Dom.Node> ToDom() const
997 {
998 UniquePtr<System.Dom.Element> element(new System.Dom.Element(u"functionCall"));
999 element->AppendChild(UniquePtr<System.Dom.Node>(new System.Dom.Element(functionName)));
1000 UniquePtr<System.Dom.Element> argumentsElement(new System.Dom.Element(u"arguments"));
1001 for (const UniquePtr<XPathExpr>& argument : arguments)
1002 {
1003 argumentsElement->AppendChild(argument->ToDom());
1004 }
1005 element->AppendChild(UniquePtr<System.Dom.Node>(argumentsElement.Release()));
1006 return UniquePtr<System.Dom.Node>(element.Release());
1007 }
1008 private ustring functionName;
1009 private List<UniquePtr<XPathExpr>> arguments;
1010 }
1011 public UniquePtr<XPathObject> CompareNodeSets(XPathContext& context, XPathObject* left, XPathObject* right, Operator comparisonOp)
1012 {
1013 if (left->Type() == XPathObjectType.nodeSet && right->Type() == XPathObjectType.nodeSet)
1014 {
1015 XPathNodeSet* leftNodeSet = cast<XPathNodeSet*>(left);
1016 XPathNodeSet* rightNodeSet = cast<XPathNodeSet*>(right);
1017 int n = leftNodeSet->Length();
1018 for (int i = 0; i < n; ++i;)
1019 {
1020 System.Dom.Node* leftNode = (*leftNodeSet)[i];
1021 ustring leftStr = StringValue(leftNode);
1022 int m = rightNodeSet->Length();
1023 for (int j = 0; j < m; ++j;)
1024 {
1025 System.Dom.Node* rightNode = (*rightNodeSet)[j];
1026 ustring rightStr = StringValue(rightNode);
1027 switch (comparisonOp)
1028 {
1029 case Operator.equal:
1030 {
1031 if (leftStr == rightStr)
1032 {
1033 UniquePtr<XPathObject> result(new XPathBoolean(true));
1034 return result;
1035 }
1036 break;
1037 }
1038 case Operator.notEqual:
1039 {
1040 if (leftStr != rightStr)
1041 {
1042 UniquePtr<XPathObject> result(new XPathBoolean(true));
1043 return result;
1044 }
1045 break;
1046 }
1047 case Operator.less:
1048 {
1049 if (leftStr < rightStr)
1050 {
1051 UniquePtr<XPathObject> result(new XPathBoolean(true));
1052 return result;
1053 }
1054 break;
1055 }
1056 case Operator.greater:
1057 {
1058 if (leftStr > rightStr)
1059 {
1060 UniquePtr<XPathObject> result(new XPathBoolean(true));
1061 return result;
1062 }
1063 break;
1064 }
1065 case Operator.lessOrEqual:
1066 {
1067 if (leftStr <= rightStr)
1068 {
1069 UniquePtr<XPathObject> result(new XPathBoolean(true));
1070 return result;
1071 }
1072 break;
1073 }
1074 case Operator.greaterOrEqual:
1075 {
1076 if (leftStr >= rightStr)
1077 {
1078 UniquePtr<XPathObject> result(new XPathBoolean(true));
1079 return result;
1080 }
1081 break;
1082 }
1083 }
1084 }
1085 }
1086 }
1087 else if (left->Type() == XPathObjectType.nodeSet)
1088 {
1089 XPathFunction* numberFunction = GetXPathLibraryFunction(u"number");
1090 XPathFunction* booleanFunction = GetXPathLibraryFunction(u"boolean");
1091 if (right->Type() == XPathObjectType.number)
1092 {
1093 double rightNumber = cast<XPathNumber*>(right)->Value();
1094 XPathNodeSet* leftNodeSet = cast<XPathNodeSet*>(left);
1095 int n = leftNodeSet->Length();
1096 for (int i = 0; i < n; ++i;)
1097 {
1098 System.Dom.Node* leftNode = (*leftNodeSet)[i];
1099 XPathString leftAsString(StringValue(leftNode));
1100 List<XPathObject*> leftArgs;
1101 leftArgs.Add(&leftAsString);
1102 UniquePtr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
1103 if (leftAsNumber->Type() != XPathObjectType.number)
1104 {
1105 throw Exception("number result expected");
1106 }
1107 double leftNumber = cast<XPathNumber*>(leftAsNumber.Get())->Value();
1108 switch (comparisonOp)
1109 {
1110 case Operator.equal:
1111 {
1112 if (leftNumber == rightNumber)
1113 {
1114 UniquePtr<XPathObject> result(new XPathBoolean(true));
1115 return result;
1116 }
1117 break;
1118 }
1119 case Operator.notEqual:
1120 {
1121 if (leftNumber != rightNumber)
1122 {
1123 UniquePtr<XPathObject> result(new XPathBoolean(true));
1124 return result;
1125 }
1126 break;
1127 }
1128 case Operator.less:
1129 {
1130 if (leftNumber < rightNumber)
1131 {
1132 UniquePtr<XPathObject> result(new XPathBoolean(true));
1133 return result;
1134 }
1135 break;
1136 }
1137 case Operator.greater:
1138 {
1139 if (leftNumber > rightNumber)
1140 {
1141 UniquePtr<XPathObject> result(new XPathBoolean(true));
1142 return result;
1143 }
1144 break;
1145 }
1146 case Operator.lessOrEqual:
1147 {
1148 if (leftNumber <= rightNumber)
1149 {
1150 UniquePtr<XPathObject> result(new XPathBoolean(true));
1151 return result;
1152 }
1153 break;
1154 }
1155 case Operator.greaterOrEqual:
1156 {
1157 if (leftNumber >= rightNumber)
1158 {
1159 UniquePtr<XPathObject> result(new XPathBoolean(true));
1160 return result;
1161 }
1162 break;
1163 }
1164 }
1165 }
1166 }
1167 else if (right->Type() == XPathObjectType.string)
1168 {
1169 ustring rightString = cast<XPathString*>(right)->Value();
1170 XPathNodeSet* leftNodeSet = cast<XPathNodeSet*>(left);
1171 int n = leftNodeSet->Length();
1172 for (int i = 0; i < n; ++i;)
1173 {
1174 System.Dom.Node* leftNode = (*leftNodeSet)[i];
1175 ustring leftString = StringValue(leftNode);
1176 switch (comparisonOp)
1177 {
1178 case Operator.equal:
1179 {
1180 if (leftString == rightString)
1181 {
1182 UniquePtr<XPathObject> result(new XPathBoolean(true));
1183 return result;
1184 }
1185 break;
1186 }
1187 case Operator.notEqual:
1188 {
1189 if (leftString != rightString)
1190 {
1191 UniquePtr<XPathObject> result(new XPathBoolean(true));
1192 return result;
1193 }
1194 break;
1195 }
1196 case Operator.less:
1197 {
1198 if (leftString < rightString)
1199 {
1200 UniquePtr<XPathObject> result(new XPathBoolean(true));
1201 return result;
1202 }
1203 break;
1204 }
1205 case Operator.greater:
1206 {
1207 if (leftString > rightString)
1208 {
1209 UniquePtr<XPathObject> result(new XPathBoolean(true));
1210 return result;
1211 }
1212 break;
1213 }
1214 case Operator.lessOrEqual:
1215 {
1216 if (leftString <= rightString)
1217 {
1218 UniquePtr<XPathObject> result(new XPathBoolean(true));
1219 return result;
1220 }
1221 break;
1222 }
1223 case Operator.greaterOrEqual:
1224 {
1225 if (leftString >= rightString)
1226 {
1227 UniquePtr<XPathObject> result(new XPathBoolean(true));
1228 return result;
1229 }
1230 break;
1231 }
1232 }
1233 }
1234 }
1235 else if (right->Type() == XPathObjectType.boolean)
1236 {
1237 bool rightBool = cast<XPathBoolean*>(right)->Value();
1238 List<XPathObject*> leftArgs;
1239 leftArgs.Add(left);
1240 UniquePtr<XPathObject> leftAsBool = booleanFunction->Evaluate(context, leftArgs);
1241 if (leftAsBool->Type() != XPathObjectType.boolean)
1242 {
1243 throw Exception("boolean result expected");
1244 }
1245 bool leftBool = cast<XPathBoolean*>(leftAsBool.Get())->Value();
1246 switch (comparisonOp)
1247 {
1248 case Operator.equal:
1249 {
1250 if (leftBool == rightBool)
1251 {
1252 UniquePtr<XPathObject> result(new XPathBoolean(true));
1253 return result;
1254 }
1255 break;
1256 }
1257 case Operator.notEqual:
1258 {
1259 if (leftBool != rightBool)
1260 {
1261 UniquePtr<XPathObject> result(new XPathBoolean(true));
1262 return result;
1263 }
1264 break;
1265 }
1266 case Operator.less:
1267 {
1268 if (cast<int>(leftBool) < cast<int>(rightBool))
1269 {
1270 UniquePtr<XPathObject> result(new XPathBoolean(true));
1271 return result;
1272 }
1273 break;
1274 }
1275 case Operator.greater:
1276 {
1277 if (cast<int>(leftBool) > cast<int>(rightBool))
1278 {
1279 UniquePtr<XPathObject> result(new XPathBoolean(true));
1280 return result;
1281 }
1282 break;
1283 }
1284 case Operator.lessOrEqual:
1285 {
1286 if (cast<int>(leftBool) <= cast<int>(rightBool))
1287 {
1288 UniquePtr<XPathObject> result(new XPathBoolean(true));
1289 return result;
1290 }
1291 break;
1292 }
1293 case Operator.greaterOrEqual:
1294 {
1295 if (cast<int>(leftBool) >= cast<int>(rightBool))
1296 {
1297 UniquePtr<XPathObject> result(new XPathBoolean(true));
1298 return result;
1299 }
1300 break;
1301 }
1302 }
1303 }
1304 }
1305 else if (right->Type() == XPathObjectType.nodeSet)
1306 {
1307 XPathFunction* numberFunction = GetXPathLibraryFunction(u"number");
1308 XPathFunction* booleanFunction = GetXPathLibraryFunction(u"boolean");
1309 if (left->Type() == XPathObjectType.number)
1310 {
1311 double leftNumber = cast<XPathNumber*>(left)->Value();
1312 XPathNodeSet* rightNodeSet = cast<XPathNodeSet*>(right);
1313 int n = rightNodeSet->Length();
1314 for (int i = 0; i < n; ++i;)
1315 {
1316 System.Dom.Node* rightNode = (*rightNodeSet)[i];
1317 XPathString rightAsString(StringValue(rightNode));
1318 List<XPathObject*> rightArgs;
1319 rightArgs.Add(&rightAsString);
1320 UniquePtr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
1321 if (rightAsNumber->Type() != XPathObjectType.number)
1322 {
1323 throw Exception("number result expected");
1324 }
1325 double rightNumber = cast<XPathNumber*>(rightAsNumber.Get())->Value();
1326 switch (comparisonOp)
1327 {
1328 case Operator.equal:
1329 {
1330 if (leftNumber == rightNumber)
1331 {
1332 UniquePtr<XPathObject> result(new XPathBoolean(true));
1333 return result;
1334 }
1335 break;
1336 }
1337 case Operator.notEqual:
1338 {
1339 if (leftNumber != rightNumber)
1340 {
1341 UniquePtr<XPathObject> result(new XPathBoolean(true));
1342 return result;
1343 }
1344 break;
1345 }
1346 case Operator.less:
1347 {
1348 if (leftNumber < rightNumber)
1349 {
1350 UniquePtr<XPathObject> result(new XPathBoolean(true));
1351 return result;
1352 }
1353 break;
1354 }
1355 case Operator.greater:
1356 {
1357 if (leftNumber > rightNumber)
1358 {
1359 UniquePtr<XPathObject> result(new XPathBoolean(true));
1360 return result;
1361 }
1362 break;
1363 }
1364 case Operator.lessOrEqual:
1365 {
1366 if (leftNumber <= rightNumber)
1367 {
1368 UniquePtr<XPathObject> result(new XPathBoolean(true));
1369 return result;
1370 }
1371 break;
1372 }
1373 case Operator.greaterOrEqual:
1374 {
1375 if (leftNumber >= rightNumber)
1376 {
1377 UniquePtr<XPathObject> result(new XPathBoolean(true));
1378 return result;
1379 }
1380 break;
1381 }
1382 }
1383 }
1384 }
1385 else if (left->Type() == XPathObjectType.string)
1386 {
1387 ustring leftString = cast<XPathString*>(left)->Value();
1388 XPathNodeSet* rightNodeSet = cast<XPathNodeSet*>(right);
1389 int n = rightNodeSet->Length();
1390 for (int i = 0; i < n; ++i;)
1391 {
1392 System.Dom.Node* rightNode = (*rightNodeSet)[i];
1393 ustring rightString = StringValue(rightNode);
1394 switch (comparisonOp)
1395 {
1396 case Operator.equal:
1397 {
1398 if (leftString == rightString)
1399 {
1400 UniquePtr<XPathObject> result(new XPathBoolean(true));
1401 return result;
1402 }
1403 break;
1404 }
1405 case Operator.notEqual:
1406 {
1407 if (leftString != rightString)
1408 {
1409 UniquePtr<XPathObject> result(new XPathBoolean(true));
1410 return result;
1411 }
1412 break;
1413 }
1414 case Operator.less:
1415 {
1416 if (leftString < rightString)
1417 {
1418 UniquePtr<XPathObject> result(new XPathBoolean(true));
1419 return result;
1420 }
1421 break;
1422 }
1423 case Operator.greater:
1424 {
1425 if (leftString > rightString)
1426 {
1427 UniquePtr<XPathObject> result(new XPathBoolean(true));
1428 return result;
1429 }
1430 break;
1431 }
1432 case Operator.lessOrEqual:
1433 {
1434 if (leftString <= rightString)
1435 {
1436 UniquePtr<XPathObject> result(new XPathBoolean(true));
1437 return result;
1438 }
1439 break;
1440 }
1441 case Operator.greaterOrEqual:
1442 {
1443 if (leftString >= rightString)
1444 {
1445 UniquePtr<XPathObject> result(new XPathBoolean(true));
1446 return result;
1447 }
1448 break;
1449 }
1450 }
1451 }
1452 }
1453 else if (left->Type() == XPathObjectType.boolean)
1454 {
1455 bool leftBool = cast<XPathBoolean*>(left)->Value();
1456 List<XPathObject*> rightArgs;
1457 rightArgs.Add(right);
1458 UniquePtr<XPathObject> rightAsBool = booleanFunction->Evaluate(context, rightArgs);
1459 if (rightAsBool->Type() != XPathObjectType.boolean)
1460 {
1461 throw Exception("boolean result expected");
1462 }
1463 bool rightBool = cast<XPathBoolean*>(rightAsBool.Get())->Value();
1464 switch (comparisonOp)
1465 {
1466 case Operator.equal:
1467 {
1468 if (leftBool == rightBool)
1469 {
1470 UniquePtr<XPathObject> result(new XPathBoolean(true));
1471 return result;
1472 }
1473 break;
1474 }
1475 case Operator.notEqual:
1476 {
1477 if (leftBool != rightBool)
1478 {
1479 UniquePtr<XPathObject> result(new XPathBoolean(true));
1480 return result;
1481 }
1482 break;
1483 }
1484 case Operator.less:
1485 {
1486 if (cast<int>(leftBool) < cast<int>(rightBool))
1487 {
1488 UniquePtr<XPathObject> result(new XPathBoolean(true));
1489 return result;
1490 }
1491 break;
1492 }
1493 case Operator.greater:
1494 {
1495 if (cast<int>(leftBool) > cast<int>(rightBool))
1496 {
1497 UniquePtr<XPathObject> result(new XPathBoolean(true));
1498 return result;
1499 }
1500 break;
1501 }
1502 case Operator.lessOrEqual:
1503 {
1504 if (cast<int>(leftBool) <= cast<int>(rightBool))
1505 {
1506 UniquePtr<XPathObject> result(new XPathBoolean(true));
1507 return result;
1508 }
1509 break;
1510 }
1511 case Operator.greaterOrEqual:
1512 {
1513 if (cast<int>(leftBool) >= cast<int>(rightBool))
1514 {
1515 UniquePtr<XPathObject> result(new XPathBoolean(true));
1516 return result;
1517 }
1518 break;
1519 }
1520 }
1521 }
1522 }
1523 UniquePtr<XPathObject> result(new XPathBoolean(false));
1524 return result;
1525 }
1526 public UniquePtr<XPathObject> CompareEquality(XPathContext& context, XPathObject* left, XPathObject* right)
1527 {
1528 if (left->Type() == XPathObjectType.nodeSet || right->Type() == XPathObjectType.nodeSet)
1529 {
1530 return CompareNodeSets(context, left, right, Operator.equal);
1531 }
1532 else
1533 {
1534 XPathFunction* numberFunction = GetXPathLibraryFunction(u"number");
1535 XPathFunction* booleanFunction = GetXPathLibraryFunction(u"boolean");
1536 XPathFunction* stringFunction = GetXPathLibraryFunction(u"string");
1537 if (left->Type() == XPathObjectType.number || right->Type() == XPathObjectType.number)
1538 {
1539 List<XPathObject*> leftArgs;
1540 leftArgs.Add(left);
1541 UniquePtr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
1542 if (leftAsNumber->Type() != XPathObjectType.number)
1543 {
1544 throw Exception("number result expected");
1545 }
1546 double leftNumber = cast<XPathNumber*>(leftAsNumber.Get())->Value();
1547 List<XPathObject*> rightArgs;
1548 rightArgs.Add(right);
1549 UniquePtr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
1550 if (rightAsNumber->Type() != XPathObjectType.number)
1551 {
1552 throw Exception("number result expected");
1553 }
1554 double rightNumber = cast<XPathNumber*>(rightAsNumber.Get())->Value();
1555 if (leftNumber == rightNumber)
1556 {
1557 UniquePtr<XPathObject> result(new XPathBoolean(true));
1558 return result;
1559 }
1560 else
1561 {
1562 UniquePtr<XPathObject> result(new XPathBoolean(false));
1563 return result;
1564 }
1565 }
1566 else
1567 {
1568 List<XPathObject*> leftArgs;
1569 leftArgs.Add(left);
1570 UniquePtr<XPathObject> leftAsString = stringFunction->Evaluate(context, leftArgs);
1571 if (leftAsString->Type() != XPathObjectType.string)
1572 {
1573 throw Exception("string result expected");
1574 }
1575 ustring leftString = cast<XPathString*>(leftAsString.Get())->Value();
1576 List<XPathObject*> rightArgs;
1577 rightArgs.Add(right);
1578 UniquePtr<XPathObject> rightAsString = stringFunction->Evaluate(context, rightArgs);
1579 if (rightAsString->Type() != XPathObjectType.string)
1580 {
1581 throw Exception("string result expected");
1582 }
1583 ustring rightString = cast<XPathString*>(rightAsString.Get())->Value();
1584 if (leftString == rightString)
1585 {
1586 UniquePtr<XPathObject> result(new XPathBoolean(true));
1587 return result;
1588 }
1589 else
1590 {
1591 UniquePtr<XPathObject> result(new XPathBoolean(false));
1592 return result;
1593 }
1594 }
1595 }
1596 UniquePtr<XPathObject> result(new XPathBoolean(false));
1597 return result;
1598 }
1599 public UniquePtr<XPathObject> Compare(XPathContext& context, XPathObject* left, XPathObject* right, Operator comparisonOp)
1600 {
1601 if (left->Type() == XPathObjectType.nodeSet || right->Type() == XPathObjectType.nodeSet)
1602 {
1603 return CompareNodeSets(context, left, right, comparisonOp);
1604 }
1605 else
1606 {
1607 XPathFunction* numberFunction = GetXPathLibraryFunction(u"number");
1608 List<XPathObject*> leftArgs;
1609 leftArgs.Add(left);
1610 UniquePtr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
1611 if (leftAsNumber->Type() != XPathObjectType.number)
1612 {
1613 throw Exception("number result expected");
1614 }
1615 double leftNumber = cast<XPathNumber*>(leftAsNumber.Get())->Value();
1616 List<XPathObject*> rightArgs;
1617 rightArgs.Add(right);
1618 UniquePtr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
1619 if (rightAsNumber->Type() != XPathObjectType.number)
1620 {
1621 throw Exception("number result expected");
1622 }
1623 double rightNumber = cast<XPathNumber*>(rightAsNumber.Get())->Value();
1624 switch (comparisonOp)
1625 {
1626 case Operator.less:
1627 {
1628 if (leftNumber < rightNumber)
1629 {
1630 UniquePtr<XPathObject> result(new XPathBoolean(true));
1631 return result;
1632 }
1633 else
1634 {
1635 UniquePtr<XPathObject> result(new XPathBoolean(false));
1636 return result;
1637 }
1638 break;
1639 }
1640 case Operator.greater:
1641 {
1642 if (leftNumber > rightNumber)
1643 {
1644 UniquePtr<XPathObject> result(new XPathBoolean(true));
1645 return result;
1646 }
1647 else
1648 {
1649 UniquePtr<XPathObject> result(new XPathBoolean(false));
1650 return result;
1651 }
1652 break;
1653 }
1654 case Operator.lessOrEqual:
1655 {
1656 if (leftNumber <= rightNumber)
1657 {
1658 UniquePtr<XPathObject> result(new XPathBoolean(true));
1659 return result;
1660 }
1661 else
1662 {
1663 UniquePtr<XPathObject> result(new XPathBoolean(false));
1664 return result;
1665 }
1666 break;
1667 }
1668 case Operator.greaterOrEqual:
1669 {
1670 if (leftNumber >= rightNumber)
1671 {
1672 UniquePtr<XPathObject> result(new XPathBoolean(true));
1673 return result;
1674 }
1675 else
1676 {
1677 UniquePtr<XPathObject> result(new XPathBoolean(false));
1678 return result;
1679 }
1680 break;
1681 }
1682 }
1683 }
1684 UniquePtr<XPathObject> result(new XPathBoolean(false));
1685 return result;
1686 }
1687 public class NodeSelectionOp : System.Dom.NodeOp
1688 {
1689 public NodeSelectionOp(XPathNodeTestExpr* nodeTest_, XPathNodeSet& nodeSet_, System.Dom.Axis axis_) :
1690 nodeTest(nodeTest_), nodeSet(nodeSet_), axis(axis_)
1691 {
1692 }
1693 public override void Apply(System.Dom.Node* node)
1694 {
1695 if (nodeTest->Select(node, axis))
1696 {
1697 nodeSet.Add(node);
1698 }
1699 }
1700 private XPathNodeTestExpr* nodeTest;
1701 private XPathNodeSet& nodeSet;
1702 private System.Dom.Axis axis;
1703 }
1704 public class AxisMap
1705 {
1706 static AxisMap() : instance(new AxisMap())
1707 {
1708 }
1709 public static AxisMap& Instance()
1710 {
1711 return *instance;
1712 }
1713 public AxisMap()
1714 {
1715 axisMap[u"ancestor"] = Axis.ancestor;
1716 axisMap[u"ancestor-or-self"] = Axis.ancestorOrSelf;
1717 axisMap[u"attribute"] = Axis.attribute;
1718 axisMap[u"child"] = Axis.child;
1719 axisMap[u"descendant"] = Axis.descendant;
1720 axisMap[u"descendant-or-self"] = Axis.descendantOrSelf;
1721 axisMap[u"following"] = Axis.following;
1722 axisMap[u"following-sibling"] = Axis.followingSibling;
1723 axisMap[u"namespace"] = Axis.ns;
1724 axisMap[u"parent"] = Axis.parent;
1725 axisMap[u"preceding"] = Axis.preceding;
1726 axisMap[u"preceding-sibling"] = Axis.precedingSibling;
1727 axisMap[u"self"] = Axis.self;
1728 }
1729 public System.Dom.Axis GetAxis(const ustring& axis) const
1730 {
1731 Map<ustring, System.Dom.Axis>.ConstIterator it = axisMap.CFind(axis);
1732 if (it != axisMap.CEnd())
1733 {
1734 return it->second;
1735 }
1736 else
1737 {
1738 throw Exception("axis \'" + ToUtf8(axis) + "\' not found");
1739 }
1740 }
1741 private static UniquePtr<AxisMap> instance;
1742 private Map<ustring, System.Dom.Axis> axisMap;
1743 }
1744 public System.Dom.Axis GetAxis(const ustring& axisName)
1745 {
1746 return AxisMap.Instance().GetAxis(axisName);
1747 }
1748 }