1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <sngxml/dom/Node.hpp>
  7 #include <sngxml/dom/Document.hpp>
  8 #include <sngxml/dom/DocumentFragment.hpp>
  9 #include <sngxml/dom/Exception.hpp>
 10 #include <algorithm>
 11 
 12 namespace sngxml { namespace dom {
 13 
 14 NodeOp::~NodeOp()
 15 {
 16 }
 17 
 18 void NodeOp::Apply(Node* node)
 19 {
 20 }
 21 
 22 std::u32string AxisName(Axis axis)
 23 {
 24     switch (axis)
 25     {
 26     case Axis::child: return U"child";
 27     case Axis::descendant: return U"descendant";
 28     case Axis::parent: return U"parent";
 29     case Axis::ancestor: return U"ancestor";
 30     case Axis::followingSibling: return U"followingSibling";
 31     case Axis::precedingSibling: return U"precedingSibling";
 32     case Axis::following: return U"following";
 33     case Axis::preceding: return U"preceding";
 34     case Axis::attribute: return U"attribute";
 35     case Axis::ns: return U"namespace";
 36     case Axis::self: return U"self";
 37     case Axis::descendantOrSelf: return U"descendantOrSelf";
 38     case Axis::ancestorOrSelf: return U"ancestorOrSelf";
 39     }
 40     return std::u32string();
 41 }
 42 
 43 Node::Node(NodeType nodeType_const std::u32string& name_) : nodeType(nodeType_)name(name_)parent(nullptr)previousSibling(nullptr)nextSibling(nullptr)ownerDocument(nullptr)
 44 {
 45 }
 46 
 47 Node::~Node()
 48 {
 49 }
 50 
 51 std::u32string Node::Prefix() const
 52 {
 53     if (nodeType == NodeType::elementNode || nodeType == NodeType::attributeNode)
 54     {
 55         auto colonPos = name.find(':');
 56         if (colonPos != std::u32string::npos)
 57         {
 58             return name.substr(0colonPos);
 59         }
 60     }
 61     return std::u32string();
 62 }
 63 
 64 void Node::SetPrefix(const std::u32string& prefix)
 65 {
 66     if (nodeType == NodeType::elementNode || nodeType == NodeType::attributeNode)
 67     {
 68         auto colonPos = name.find(':');
 69         if (prefix.empty())
 70         {
 71             if (colonPos != std::u32string::npos)
 72             {
 73                 name = name.substr(colonPos + 1);
 74             }
 75         }
 76         else
 77         {
 78             if (colonPos != std::u32string::npos)
 79             {
 80                 name = prefix + U":" + name.substr(colonPos + 1);
 81             }
 82             else
 83             {
 84                 name = prefix + U":" + name;
 85             }
 86         }
 87     }
 88     else
 89     {
 90         throw DomException("cannot set prefix for this node type");
 91     }
 92 }
 93 
 94 std::u32string Node::LocalName() const
 95 {
 96     if (nodeType == NodeType::elementNode || nodeType == NodeType::attributeNode)
 97     {
 98         auto colonPos = name.find(':');
 99         if (colonPos != std::u32string::npos)
100         {
101             return name.substr(colonPos + 1);
102         }
103         else
104         {
105             return name;
106         }
107     }
108     else
109     {
110         return std::u32string();
111     }
112 }
113 
114 void Node::Walk(NodeOp& nodeOpAxis axis)
115 {
116     switch (axis)
117     {
118         case Axis::child: WalkChildren(nodeOp); break;
119         case Axis::descendant: WalkDescendant(nodeOp); break;
120         case Axis::descendantOrSelf: WalkDescendantOrSelf(nodeOp); break;
121         case Axis::parent: WalkParent(nodeOp); break;
122         case Axis::ancestor: WalkAncestor(nodeOp); break;
123         case Axis::ancestorOrSelf: WalkAncestorOrSelf(nodeOp); break;
124         case Axis::followingSibling: WalkFollowingSibling(nodeOp); break;
125         case Axis::precedingSibling: WalkPrecedingSibling(nodeOp); break;
126         case Axis::following: WalkFollowing(nodeOp); break;
127         case Axis::preceding: WalkPreceding(nodeOp); break;
128         case Axis::attribute: WalkAttribute(nodeOp); break;
129         case Axis::self: nodeOp.Apply(this); break;
130     }
131 }
132 
133 void Node::WalkChildren(NodeOp& nodeOp)
134 {
135 }
136 
137 void Node::WalkDescendant(NodeOp& nodeOp)
138 {
139 }
140 
141 void Node::WalkDescendantOrSelf(NodeOp& nodeOp)
142 {
143     nodeOp.Apply(this);
144 }
145 
146 void Node::WalkParent(NodeOp& nodeOp)
147 {
148     if (parent)
149     {
150         nodeOp.Apply(parent);
151     }
152 }
153 
154 void Node::WalkFollowing(NodeOp& nodeOp)
155 {
156     Node* ns = nextSibling;
157     if (ns)
158     {
159         ns->WalkDescendantOrSelf(nodeOp);
160         ns = ns->nextSibling;
161     }
162 }
163 
164 void Node::WalkPreceding(NodeOp& nodeOp)
165 {
166 }
167 
168 void Node::WalkPrecedingOrSelf(NodeOp& nodeOp)
169 {
170     nodeOp.Apply(this);
171 }
172 
173 void Node::WalkAncestor(NodeOp& nodeOp)
174 {
175     if (parent)
176     {
177         parent->WalkAncestorOrSelf(nodeOp);
178     }
179 }
180 
181 void Node::WalkAncestorOrSelf(NodeOp& nodeOp)
182 {
183     nodeOp.Apply(this);
184     if (parent)
185     {
186         parent->WalkAncestorOrSelf(nodeOp);
187     }
188 }
189 
190 void Node::WalkFollowingSibling(NodeOp& nodeOp)
191 {
192     Node* ns = nextSibling;
193     if (ns)
194     {
195         nodeOp.Apply(ns);
196         ns = ns->nextSibling;
197     }
198 }
199 
200 void Node::WalkPrecedingSibling(NodeOp& nodeOp)
201 {
202     Node* ps = previousSibling;
203     if (ps)
204     {
205         nodeOp.Apply(ps);
206         ps = ps->previousSibling;
207     }
208 }
209 
210 void Node::WalkAttribute(NodeOp& nodeOp)
211 {
212 }
213 
214 void Node::InternalLinkBefore(Node* newNode)
215 {
216     newNode->previousSibling = previousSibling;
217     newNode->nextSibling = this;
218     previousSibling = newNode;
219 }
220 
221 void Node::InternalLinkAfter(Node* newNode)
222 {
223     newNode->previousSibling = this;
224     newNode->nextSibling = nextSibling;
225     nextSibling = newNode;
226 }
227 
228 void Node::InternalUnlink()
229 {
230     if (previousSibling)
231     {
232         previousSibling->nextSibling = nextSibling;
233     }
234     if (nextSibling)
235     {
236         nextSibling->previousSibling = previousSibling;
237     }
238 }
239 
240 void Node::InternalSetNamespaceUri(const std::u32string& namespaceUri_)
241 {
242     namespaceUri = namespaceUri_;
243 }
244 
245 ParentNode::ParentNode(NodeType nodeType_const std::u32string& name_) : Node(nodeType_name_)firstChild(nullptr)lastChild(nullptr)
246 {
247 }
248 
249 ParentNode::~ParentNode()
250 {
251     Node* child = firstChild;
252     while (child != nullptr)
253     {
254         Node* toDel = child;
255         child = child->NextSibling();
256         delete toDel;
257     }
258 }
259 
260 NodeList ParentNode::ChildNodes() const
261 {
262     NodeList result;
263     Node* child = firstChild;
264     while (child != nullptr)
265     {
266         result.InternalAddNode(child);
267         child = child->NextSibling();
268     }
269     return result;
270 }
271 
272 void ParentNode::Write(CodeFormatter& formatter)
273 {
274     Node* child = firstChild;
275     while (child != nullptr)
276     {
277         child->Write(formatter);
278         child = child->NextSibling();
279     }
280 }
281 
282 void ParentNode::CloneChildrenTo(ParentNode* clone) const
283 {
284     Node* child = firstChild;
285     while (child != nullptr)
286     {
287         clone->AppendChild(child->CloneNode(true));
288         child = child->NextSibling();
289     }
290 }
291 
292 Node* ParentNode::InsertBefore(std::std::unique_ptr<Node>&&newChildNode*refChild)
293 {
294     if (refChild == nullptr)
295     {
296         return AppendChild(std::move(newChild));
297     }
298     else
299     {
300         if (OwnerDocument())
301         {
302             OwnerDocument()->InternalInvalidateIndex();
303         }
304         if (newChild->GetNodeType() == NodeType::documentFragmentNode)
305         {
306             DocumentFragment* documentFragment = static_cast<DocumentFragment*>(newChild.get());
307             Node* docFragChild = documentFragment->FirstChild();
308             Node* nodeInserted = nullptr;
309             while (docFragChild != nullptr)
310             {
311                 std::unique_ptr<Node> docFragChildRemoved = documentFragment->RemoveChild(docFragChild);
312                 nodeInserted = InsertBefore(std::move(docFragChildRemoved)refChild);
313                 docFragChild = documentFragment->FirstChild();
314             }
315             return nodeInserted;
316         }
317         else
318         {
319             if (newChild->Parent())
320             {
321                 newChild.reset(newChild->Parent()->RemoveChild(newChild.get()).release());
322             }
323             if (firstChild == refChild)
324             {
325                 firstChild = newChild.get();
326             }
327             newChild->InternalSetParent(this);
328             newChild->InternalSetOwnerDocument(OwnerDocument());
329             Node* nodeInserted = newChild.get();
330             refChild->InternalLinkBefore(newChild.release());
331             return nodeInserted;
332         }
333     }
334 }
335 
336 std::std::unique_ptr<Node>ParentNode::RemoveChild(Node*oldChild)
337 {
338     if (!oldChild)
339     {
340         throw DomException("could not remove node: given old child is null");
341     }
342     if (oldChild->Parent() != this)
343     {
344         throw DomException("could not remove node: given old child is not child of this node");
345     }
346     if (OwnerDocument())
347     {
348         OwnerDocument()->InternalInvalidateIndex();
349     }
350     oldChild->InternalUnlink();
351     if (oldChild == firstChild)
352     {
353         firstChild = oldChild->NextSibling();
354     }
355     if (oldChild == lastChild)
356     {
357         lastChild = oldChild->PreviousSibling();
358     }
359     std::unique_ptr<Node> removedNode = std::unique_ptr<Node>(oldChild);
360     removedNode->InternalSetOwnerDocument(nullptr);
361     removedNode->InternalSetParent(nullptr);
362     return removedNode;
363 }
364 
365 std::std::unique_ptr<Node>ParentNode::ReplaceChild(std::std::unique_ptr<Node>&&newChildNode*oldChild)
366 {
367     if (!oldChild)
368     {
369         throw DomException("could not replace node: given old child is null");
370     }
371     if (oldChild->Parent() != this)
372     {
373         throw DomException("could not replace node: given old child is not child of this node");
374     }
375     if (OwnerDocument())
376     {
377         OwnerDocument()->InternalInvalidateIndex();
378     }
379     if (newChild->Parent())
380     {
381         newChild.reset(newChild->Parent()->RemoveChild(newChild.get()).release());
382     }
383     InsertBefore(std::move(newChild)oldChild);
384     return RemoveChild(oldChild);
385 }
386 
387 Node* ParentNode::AppendChild(std::std::unique_ptr<Node>&&newChild)
388 {
389     if (OwnerDocument())
390     {
391         OwnerDocument()->InternalInvalidateIndex();
392     }
393     if (newChild->Parent())
394     {
395         newChild.reset(newChild->Parent()->RemoveChild(newChild.get()).release());
396     }
397     if (newChild->GetNodeType() == NodeType::documentFragmentNode)
398     {
399         DocumentFragment* documentFragment = static_cast<DocumentFragment*>(newChild.get());
400         Node* docFragChild = documentFragment->FirstChild();
401         Node* nodeInserted = nullptr;
402         while (docFragChild != nullptr)
403         {
404             std::unique_ptr<Node> docFragChildRemoved = documentFragment->RemoveChild(docFragChild);
405             nodeInserted = AppendChild(std::move(docFragChildRemoved));
406             docFragChild = documentFragment->FirstChild();
407         }
408         return nodeInserted;
409     }
410     else
411     {
412         if (lastChild)
413         {
414             lastChild->InternalLinkAfter(newChild.get());
415         }
416         if (!firstChild)
417         {
418             firstChild = newChild.get();
419         }
420         newChild->InternalSetOwnerDocument(OwnerDocument());
421         newChild->InternalSetParent(this);
422         lastChild = newChild.release();
423         return lastChild;
424     }
425 }
426 
427 void ParentNode::Accept(Visitor& visitor)
428 {
429     Node* child = firstChild;
430     while (child != nullptr)
431     {
432         child->Accept(visitor);
433         child = child->NextSibling();
434     }
435 }
436 
437 void ParentNode::WalkChildren(NodeOp& nodeOp)
438 {
439     Node* child = firstChild;
440     while (child != nullptr)
441     {
442         nodeOp.Apply(child);
443         child = child->NextSibling();
444     }
445 }
446 
447 void ParentNode::WalkDescendant(NodeOp& nodeOp)
448 {
449     Node* child = firstChild;
450     while (child != nullptr)
451     {
452         child->WalkDescendantOrSelf(nodeOp);
453         child = child->NextSibling();
454     }
455 }
456 
457 void ParentNode::WalkDescendantOrSelf(NodeOp& nodeOp)
458 {
459     Node::WalkDescendantOrSelf(nodeOp);
460     Node* child = firstChild;
461     while (child != nullptr)
462     {
463         child->WalkDescendantOrSelf(nodeOp);
464         child = child->NextSibling();
465     }
466 }
467 
468 void ParentNode::WalkPrecedingOrSelf(NodeOp& nodeOp)
469 {
470     Node::WalkPrecedingOrSelf(nodeOp);
471     Node* child = lastChild;
472     while (child != nullptr)
473     {
474         child->WalkPrecedingOrSelf(nodeOp);
475         child = child->PreviousSibling();
476     }
477 }
478 
479 void ParentNode::WalkPreceding(NodeOp& nodeOp)
480 {
481     Node* preceding = PreviousSibling();
482     if (preceding)
483     {
484         preceding->WalkPrecedingOrSelf(nodeOp);
485     }
486 }
487 
488 void NodeList::InternalAddNode(Node* node)
489 {
490     if (std::find(nodes.begin()nodes.end()node) == nodes.end())
491     {
492         nodes.push_back(node);
493     }
494 }
495 
496 } } // namespace sngxml::dom