1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3  * This file is part of the libe-book project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 #ifndef XMLTREENODE_H_INCLUDED
11 #define XMLTREENODE_H_INCLUDED
12 
13 #include <deque>
14 #include <string>
15 #include <utility>
16 
17 #include <boost/intrusive_ptr.hpp>
18 
19 #include "libebook_libcss.h"
20 
21 namespace libebook
22 {
23 
24 struct XMLTreeNode;
25 typedef boost::intrusive_ptr<XMLTreeNode> XMLTreeNodePtr_t;
26 
27 struct XMLTreeNode
28 {
29   enum NodeType
30   {
31     NODE_TYPE_DOCUMENT = 1 << 1,
32     NODE_TYPE_ELEMENT = 1 << 2,
33     NODE_TYPE_TEXT = 1 << 3,
34     NODE_TYPE_COMMENT = 1 << 4,
35     NODE_TYPE_DOCTYPE = 1 << 5
36   };
37 
38   struct QName
39   {
40     LWCStringPtr_t name;
41     LWCStringPtr_t ns;
42 
43     QName();
44     explicit QName(const LWCStringPtr_t &name, const LWCStringPtr_t &ns = LWCStringPtr_t());
45   };
46 
47   typedef std::pair<QName, QName> LinkId_t;
48 
49   struct Configuration
50   {
51     bool caseless;
52 
53     std::deque<QName> classes; //< A list of attributes representing a "class".
54     std::deque<QName> ids; //< a list of attributes representing an "ID".
55     std::deque<QName> langs; //< a list of attributes representing a "lang".
56 
57     /** A list of element / attribute pairs representing a "link".
58       *
59       * Either element or attribute name can be empty, matching
60       * anything. E.g., xlink:href attribute is always a link.
61       */
62     std::deque<LinkId_t> links;
63 
64     explicit Configuration(bool caseless_ = false);
65   };
66 
67   typedef std::shared_ptr<Configuration> ConfigurationPtr_t;
68 
69   struct ElementData
70   {
71     QName qname;
72     mutable int id;
73     mutable bool idSet;
74 
75     ElementData();
76     explicit ElementData(const LWCStringPtr_t &name, const LWCStringPtr_t &ns = LWCStringPtr_t());
77   };
78 
79   struct AttributeData
80   {
81     QName qname;
82     LWCStringPtr_t value;
83     mutable int id;
84     mutable bool idSet;
85 
86     AttributeData();
87     AttributeData(const LWCStringPtr_t &name, const LWCStringPtr_t &ns, const LWCStringPtr_t &val);
88     AttributeData(const LWCStringPtr_t &name, const LWCStringPtr_t &val);
89   };
90 
91 public:
92   explicit XMLTreeNode(NodeType nodeType, const ConfigurationPtr_t &config = ConfigurationPtr_t());
93   ~XMLTreeNode();
94 
95   NodeType type;
96   ConfigurationPtr_t configuration;
97 
98   ElementData self;
99   std::deque<AttributeData> attributes;
100   std::string text;
101 
102   XMLTreeNodePtr_t parent;
103   // siblings
104   XMLTreeNodePtr_t prev;
105   XMLTreeNodePtr_t next;
106   // children
107   XMLTreeNodePtr_t first;
108   XMLTreeNodePtr_t last;
109 
110   size_t elements;
111 
112   mutable int refcount;
113 
114   XMLTreeNodePtr_t clone(bool deep = false) const;
115 
116   XMLTreeNodePtr_t appendChild(const XMLTreeNodePtr_t &child);
117   XMLTreeNodePtr_t insertChildBefore(const XMLTreeNodePtr_t &child, const XMLTreeNodePtr_t &selected);
118   void removeChild(const XMLTreeNodePtr_t &child);
119   void transferChildren(const XMLTreeNodePtr_t &newParent);
120 
121   void addAttributes(const std::deque<AttributeData> &attrs);
122 
123   bool hasChildren(bool ignoreText = false) const;
124 
125 private:
126   // disable copying
127   XMLTreeNode(const XMLTreeNode &);
128   XMLTreeNode &operator=(const XMLTreeNode &);
129 };
130 
131 bool operator==(const XMLTreeNode::QName &lhs, const XMLTreeNode::QName &rhs);
132 bool operator!=(const XMLTreeNode::QName &lhs, const XMLTreeNode::QName &rhs);
133 bool caselessEqual(const XMLTreeNode::QName &lhs, const XMLTreeNode::QName &rhs);
134 
135 bool operator==(const XMLTreeNode::AttributeData &lhs, const XMLTreeNode::AttributeData &rhs);
136 bool operator!=(const XMLTreeNode::AttributeData &lhs, const XMLTreeNode::AttributeData &rhs);
137 
138 bool operator==(const XMLTreeNode::ElementData &lhs, const XMLTreeNode::ElementData &rhs);
139 bool operator!=(const XMLTreeNode::ElementData &lhs, const XMLTreeNode::ElementData &rhs);
140 
141 void intrusive_ptr_add_ref(XMLTreeNode *p);
142 void intrusive_ptr_release(XMLTreeNode *p);
143 
144 }
145 
146 #endif // XMLTREENODE_H_INCLUDED
147 
148 /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
149