1 // =================================
  2 // Copyright (c) 2024 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 
  8 namespace System.Xml
  9 {
 10     public abstract class ParentNode : Node
 11     {
 12         public ParentNode(NodeKind kind_const System.Lex.Span& span_int fileIndex_const string& name_) : 
 13             base(kind_span_fileIndex_name_)firstChild(null)lastChild(null)
 14         {
 15         }
 16         public override ~ParentNode()
 17         {
 18             Node* child = firstChild;
 19             while (child != null)
 20             {
 21                 Node* toDel = child;
 22                 child = child->Next();
 23                 delete toDel;
 24             }
 25         }
 26         public Node* FirstChild() const
 27         {
 28             return firstChild;
 29         }
 30         public Node* LastChild() const
 31         {
 32             return lastChild;
 33         }
 34         public virtual void AppendChild(Node* child)
 35         {
 36             if (OwnerDocument() != null)
 37             {
 38                 OwnerDocument()->InvalidateIndex();
 39             }
 40             if (child->Parent() != null)
 41             {
 42                 child = child->Parent()->RemoveChild(child).Release();
 43             }
 44             if (child->IsDocumentFragmentNode())
 45             {
 46                 DocumentFragment* documentFragment = cast<DocumentFragment*>(child);
 47                 Node* docFragChild = documentFragment->FirstChild();
 48                 Node* nodeInserted = null;
 49                 while (docFragChild != null)
 50                 {
 51                     UniquePtr<Node> docFragChildRemoved = documentFragment->RemoveChild(docFragChild);
 52                     AppendChild(docFragChildRemoved.Release());
 53                     docFragChild = documentFragment->FirstChild();
 54                 }
 55             }
 56             else
 57             {
 58                 if (lastChild != null)
 59                 {
 60                     lastChild->LinkAfter(child);
 61                 }
 62                 if (firstChild == null)
 63                 {
 64                     firstChild = child;
 65                 }
 66                 child->SetOwnerDocument(OwnerDocument());
 67                 child->SetParent(this);
 68                 lastChild = child;
 69             }
 70         }
 71         public virtual void InsertBefore(Node* newChildNode* refChild)
 72         {
 73             if (refChild == null)
 74             {
 75                 AppendChild(newChild);
 76             }
 77             if (OwnerDocument() != null)
 78             {
 79                 OwnerDocument()->InvalidateIndex();
 80             }
 81             if (newChild->IsDocumentFragmentNode())
 82             {
 83                 DocumentFragment* documentFragment = cast<DocumentFragment*>(newChild);
 84                 Node* docFragChild = documentFragment->FirstChild();
 85                 Node* nodeInserted = null;
 86                 while (docFragChild != null)
 87                 {
 88                     UniquePtr<Node> docFragChildRemoved = documentFragment->RemoveChild(docFragChild);
 89                     InsertBefore(docFragChildRemoved.Release()refChild);
 90                     docFragChild = documentFragment->FirstChild();
 91                 }
 92             }
 93             else
 94             {
 95                 if (newChild->Parent() != null)
 96                 {
 97                     newChild = newChild->Parent()->RemoveChild(newChild).Release();
 98                 }
 99                 if (firstChild == refChild)
100                 {
101                     firstChild = newChild;
102                 }
103                 newChild->SetParent(this);
104                 newChild->SetOwnerDocument(OwnerDocument());
105                 refChild->LinkBefore(newChild);
106             }
107         }
108         public virtual UniquePtr<Node> RemoveChild(Node* child)
109         {
110             if (OwnerDocument() != null)
111             {
112                 OwnerDocument()->InvalidateIndex();
113             }
114             child->Unlink();
115             if (child == firstChild)
116             {
117                 firstChild = child->Next();
118             }
119             if (child == lastChild)
120             {
121                 lastChild = child->Prev();
122             }
123             UniquePtr<Node> removedNode = UniquePtr<Node>(child);
124             removedNode->SetOwnerDocument(null);
125             removedNode->SetParent(null);
126             return removedNode;
127         }
128         public virtual UniquePtr<Node> ReplaceChild(Node* newChildNode* oldChild)
129         {
130             if (OwnerDocument() != null)
131             {
132                 OwnerDocument()->InvalidateIndex();
133             }
134             if (newChild->Parent() != null)
135             {
136                 newChild = newChild->Parent()->RemoveChild(newChild).Release();
137             }
138             InsertBefore(newChildoldChild);
139             return RemoveChild(oldChild);
140         }
141         public override bool HasChildNodes() const
142         {
143             return firstChild != null;
144         }
145         public override void Accept(Visitor& visitor)
146         {
147             Node* child = firstChild;
148             while (child != null)
149             {
150                 child->Accept(visitor);
151                 child = child->Next();
152             }
153         }
154         [nodiscard]
155         public override Result<bool> Write(System.Text.CodeFormatter& formatter)
156         {
157             if (formatter.Error())
158             {
159                 return Result<bool>(ErrorId(formatter.GetErrorId()));
160             }
161             Node* child = firstChild;
162             while (child != null)
163             {
164                 child->Write(formatter);
165                 child = child->Next();
166             }
167             return Result<bool>(true);
168         }
169         public override void WalkChildren(NodeOperation& operation)
170         {
171             Node* child = firstChild;
172             while (child != null)
173             {
174                 operation.Apply(child);
175                 child = child->Next();
176             }
177         }
178         public override void WalkDescendant(NodeOperation& operation)
179         {
180             Node* child = firstChild;
181             while (child != null)
182             {
183                 child->WalkDescendantOrSelf(operation);
184                 child = child->Next();
185             }
186         }
187         public override void WalkDescendantOrSelf(NodeOperation& operation)
188         {
189             base->WalkDescendantOrSelf(operation);
190             Node* child = firstChild;
191             while (child != null)
192             {
193                 child->WalkDescendantOrSelf(operation);
194                 child = child->Next();
195             }
196         }
197         public override void WalkPreceding(NodeOperation& operation)
198         {
199             Node* preceding = Prev();
200             if (preceding != null)
201             {
202                 preceding->WalkPrecedingOrSelf(operation);
203             }
204         }
205         public override void WalkPrecedingOrSelf(NodeOperation& operation)
206         {
207             base->WalkPrecedingOrSelf(operation);
208             Node* child = lastChild;
209             while (child != null)
210             {
211                 child->WalkPrecedingOrSelf(operation);
212                 child = child->Prev();
213             }
214         }
215         private Node* firstChild;
216         private Node* lastChild;
217     }
218 }