1 // =================================
  2 // Copyright (c) 2024 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Collections;
  8 
  9 namespace System.XPath
 10 {
 11     public enum ObjectKind
 12     {
 13         nodeSetbooleannumberstring
 14     }
 15 
 16     public string ObjectKindStr(ObjectKind kind)
 17     {
 18         switch (kind)
 19         {
 20             case ObjectKind.nodeSet:
 21             {
 22                 return "node-set";
 23             }
 24             case ObjectKind.boolean:
 25             {
 26                 return "Boolean";
 27             }
 28             case ObjectKind.number:
 29             {
 30                 return "number";
 31             }
 32             case ObjectKind.string:
 33             {
 34                 return "string";
 35             }
 36         }
 37         return "<unknown object kind>";
 38     }
 39     
 40     public abstract class Object
 41     {
 42         public Object(ObjectKind kind_) : kind(kind_)
 43         {
 44         }
 45         public virtual default ~Object();
 46         public inline ObjectKind Kind() const
 47         {
 48             return kind;
 49         }
 50         public inline bool IsNodeSet() const
 51         {
 52             return kind == ObjectKind.nodeSet;
 53         }
 54         public inline bool IsBoolean() const
 55         {
 56             return kind == ObjectKind.boolean;
 57         }
 58         public inline bool IsNumber() const
 59         {
 60             return kind == ObjectKind.number;
 61         }
 62         public inline bool IsString() const
 63         {
 64             return kind == ObjectKind.string;
 65         }
 66         public abstract System.Xml.Element* ToXmlElement() const;
 67         private ObjectKind kind;
 68     }
 69 
 70     public class NodeSet : Object
 71     {
 72         public NodeSet() : base(ObjectKind.nodeSet)
 73         {
 74         }
 75         public inline const List<System.Xml.Node*>& Nodes() const
 76         {
 77             return nodes;
 78         }
 79         public inline int Count() const
 80         {
 81             return cast<int>(nodes.Count());
 82         }
 83         public void Add(System.Xml.Node* node)
 84         {
 85             if (Find(nodes.Begin()nodes.End()node) == nodes.End())
 86             {
 87                 nodes.Add(node);
 88             }
 89         }
 90         public System.Xml.Node* GetNode(int index) const
 91         {
 92             #assert(index >= 0 && index < nodes.Count());
 93             return nodes[index];
 94         }
 95         public override System.Xml.Element* ToXmlElement() const
 96         {
 97             System.Xml.Element* element = System.Xml.MakeElement("node-set");
 98             element->SetAttribute("count"ToString(nodes.Count()));
 99             int n = cast<int>(nodes.Count());
100             for (int i = 0; i < n; ++i;)
101             {
102                 System.Xml.Node* node = nodes[i];
103                 System.Xml.Element* nodeElement = System.Xml.MakeElement("node");
104                 nodeElement->SetAttribute("kind"System.Xml.NodeKindStr(node->Kind()));
105                 nodeElement->SetAttribute("name"node->Name());
106                 if (node->IsElementNode())
107                 {
108                     System.Xml.Element* elementNode = cast<System.Xml.Element*>(node);
109                     System.Xml.Element* attributesElement = System.Xml.MakeElement("attributes");
110                     nodeElement->AppendChild(attributesElement);
111                     for (const auto& attr : elementNode->Attributes())
112                     {
113                         System.Xml.AttributeNode* attributeNode = attr.second.Get();
114                         System.Xml.Element* attributeElement = System.Xml.MakeElement("attribute");
115                         attributeElement->SetAttribute("name"attributeNode->Name());
116                         attributeElement->SetAttribute("value"attributeNode->Value());
117                         attributesElement->AppendChild(attributeElement);
118                     }
119                 }
120                 else if (node->IsAttributeNode())
121                 {
122                     System.Xml.AttributeNode* attributeNode = cast<System.Xml.AttributeNode*>(node);
123                     System.Xml.Element* attributeElement = System.Xml.MakeElement("attribute");
124                     attributeElement->SetAttribute("name"attributeNode->Name());
125                     attributeElement->SetAttribute("value"attributeNode->Value());
126                     nodeElement->AppendChild(attributeElement);
127                 }
128                 else if (node->IsTextNode())
129                 {
130                     System.Xml.Text* textNode = cast<System.Xml.Text*>(node);
131                     System.Xml.Element* textElement = System.Xml.MakeElement("text");
132                     textElement->SetAttribute("value"textNode->Data());
133                 }
134                 else if (node->IsProcessingInstructionNode())
135                 {
136                     System.Xml.ProcessingInstruction* processingInstructionNode = cast<System.Xml.ProcessingInstruction*>(node);
137                     System.Xml.Element* processingInstructionElement = System.Xml.MakeElement("processing-instruction");
138                     processingInstructionElement->SetAttribute("target"processingInstructionNode->Target());
139                     processingInstructionElement->SetAttribute("data"processingInstructionNode->Data());
140                     nodeElement->AppendChild(processingInstructionElement);
141                 }
142                 else if (node->IsCommentNode())
143                 {
144                     System.Xml.Comment* commentNode = cast<System.Xml.Comment*>(node);
145                     System.Xml.Element* commentElement = System.Xml.MakeElement("comment");
146                     commentElement->SetAttribute("data"commentNode->Data());
147                     nodeElement->AppendChild(commentElement);
148                 }
149                 element->AppendChild(nodeElement);
150             }
151             return element;
152         }
153         private List<System.Xml.Node*> nodes;
154     }
155 
156     public class Boolean : Object
157     {
158         public Boolean() : base(ObjectKind.boolean)value(false)
159         {
160         }
161         public Boolean(bool value_) : base(ObjectKind.boolean)value(value_)
162         {
163         }
164         public inline bool Value() const
165         {
166             return value;
167         }
168         public override System.Xml.Element* ToXmlElement() const
169         {
170             System.Xml.Element* element = System.Xml.MakeElement("boolean");
171             element->SetAttribute("value"ToString(value));
172             return element;
173         }
174         private bool value;
175     }
176 
177     public class Number : Object
178     {
179         public Number() : base(ObjectKind.number)value(0)
180         {
181         }
182         public Number(double value_) : base(ObjectKind.number)value(value_)
183         {
184         }
185         public inline double Value() const
186         {
187             return value;
188         }
189         public override System.Xml.Element* ToXmlElement() const
190         {
191             System.Xml.Element* element = System.Xml.MakeElement("number");
192             element->SetAttribute("value"ToString(value));
193             return element;
194         }
195         private double value;
196     }
197 
198     public class Str : Object
199     {
200         public Str() : base(ObjectKind.string)value()
201         {
202         }
203         public Str(const string& value_) : base(ObjectKind.string)value(value_)
204         {
205         }
206         public inline const string& Value() const
207         {
208             return value;
209         }
210         public override System.Xml.Element* ToXmlElement() const
211         {
212             System.Xml.Element* element = System.Xml.MakeElement("string");
213             element->SetAttribute("value"value);
214             return element;
215         }
216         private string value;
217     }