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