1 // =================================
  2 // Copyright (c) 2024 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 
  8 namespace System.XPath
  9 {
 10     public class ExprCounter
 11     {
 12         public static int GetExprCount()
 13         {
 14             return exprCount++;
 15         }
 16         private static int exprCount;
 17     }
 18 
 19     [nodiscard]
 20     public Result<UniquePtr<Expr>> ParseXPathExpr(const string& xpathExpr)
 21     {
 22         auto utf32Result = ToUtf32(xpathExpr);
 23         if (utf32Result.Error())
 24         {
 25             return Result<UniquePtr<Expr>>(ErrorId(utf32Result.GetErrorId()));
 26         }
 27         const ustring& xpathExprString = utf32Result.Value();
 28         int exprCount = ExprCounter.GetExprCount();
 29         XPathLexer lexer(xpathExprString.Chars()xpathExprString.Chars() + xpathExprString.Length()"xpath_expression_" + ToString(exprCount));
 30         lexer.SetFileIndex(exprCount);
 31         System.Lex.XmlParsingLog log(Console.Error());
 32         if (System.XPath.DebugParse())
 33         {
 34             lexer.SetLog(&log);
 35         }
 36         Result<UniquePtr<Expr>> exprResult = XPathParser<XPathLexer>.Parse(lexer);
 37         if (exprResult.Error())
 38         {
 39             return exprResult;
 40         }
 41         if (System.XPath.Debug())
 42         {
 43             Expr* expr = exprResult.Value().Get();
 44             System.Xml.Document exprDoc;
 45             exprDoc.AppendChild(expr->ToXmlElement());
 46             System.Text.CodeFormatter formatter(Console.Error());
 47             formatter.SetIndentSize(1);
 48             auto result = exprDoc.Write(formatter);
 49             if (result.Error())
 50             {
 51                 return Result<UniquePtr<Expr>>(ErrorId(result.GetErrorId()));
 52             }
 53         }
 54         return exprResult;
 55     }
 56 
 57     [nodiscard]
 58     public Result<UniquePtr<Object>> Evaluate(Expr* exprSystem.Xml.Node* node)
 59     {
 60         Context context(node11);
 61         auto result = expr->Evaluate(context);
 62         if (result.Error())
 63         {
 64             return result;
 65         }
 66         if (System.XPath.Debug())
 67         {
 68             System.Xml.Document resultDoc;
 69             resultDoc.AppendChild(result.Value()->ToXmlElement());
 70             System.Text.CodeFormatter formatter(Console.Error());
 71             formatter.SetIndentSize(1);
 72             auto writeResult = resultDoc.Write(formatter);
 73             if (writeResult.Error())
 74             {
 75                 return Result<UniquePtr<Object>>(ErrorId(writeResult.GetErrorId()));
 76             }
 77         }
 78         return result;
 79     }
 80 
 81     [nodiscard]
 82     public Result<UniquePtr<Object>> Evaluate(const string& xpathExprSystem.Xml.Node* node)
 83     {
 84         Result<UniquePtr<Expr>> exprResult = ParseXPathExpr(xpathExpr);
 85         if (exprResult.Error())
 86         {
 87             return Result<UniquePtr<Object>>(ErrorId(exprResult.GetErrorId()));
 88         }
 89         Expr* expr = exprResult.Value().Get();
 90         return Evaluate(exprnode);
 91     }
 92 
 93     [nodiscard]
 94     public Result<UniquePtr<NodeSet>> EvaluateToNodeSet(Expr* exprSystem.Xml.Node* node)
 95     {
 96         Result<UniquePtr<Object>> result = Evaluate(exprnode);
 97         if (result.Error())
 98         {
 99             return Result<UniquePtr<NodeSet>>(ErrorId(result.GetErrorId()));
100         }
101         if (result.Value()->IsNodeSet())
102         {
103             return Result<UniquePtr<NodeSet>>(UniquePtr<NodeSet>(cast<NodeSet*>(result.Value().Release())));
104         }
105         else
106         {
107             int errorId = AllocateError("node-set expected");
108             return Result<UniquePtr<NodeSet>>(ErrorId(errorId));
109         }
110     }
111 
112     [nodiscard]
113     public Result<UniquePtr<NodeSet>> EvaluateToNodeSet(const string& xpathExprSystem.Xml.Node* node)
114     {
115         Result<UniquePtr<Expr>> exprResult = ParseXPathExpr(xpathExpr);
116         if (exprResult.Error())
117         {
118             return Result<UniquePtr<NodeSet>>(ErrorId(exprResult.GetErrorId()));
119         }
120         Expr* expr = exprResult.Value().Get();
121         return EvaluateToNodeSet(exprnode);
122     }