neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
html.hpp
Go to the documentation of this file.
1// html.hpp
2/*
3neogfx C++ App/Game Engine
4Copyright (c) 2015, 2020 Leigh Johnston. All Rights Reserved.
5
6This program is free software: you can redistribute it and / or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#pragma once
21
22#include <neogfx/neogfx.hpp>
29#include <neogfx/gfx/color.hpp>
30
31namespace neogfx
32{
33 template <typename CharT, typename Alloc = std::allocator<CharT> >
35 {
36 public:
37 // types
38 enum type_e { Document = 0x1, Element = 0x2, Text = 0x4, Comment = 0x8, All = 0xFF };
39 typedef Alloc allocator_type;
42 typedef node* node_ptr;
43 private:
44 // types
45 typedef std::list<node_ptr, typename allocator_type::template rebind<node_ptr>::other> node_list;
46 /* Why std::list of pointers instead of std::vector of pointers? std::vector is not compatible with chunk allocator
47 and timings indicate performance benefit of std::list with chunk allocator compared to std::vector when parsing large (~10MB) html files. */
48 public:
49 // types
50 class const_iterator;
52 {
53 friend class const_iterator;
54 public:
55 iterator() : iNode(0), iIterator(), iFilter(node::All) {}
56 iterator(node& aNode, typename node::node_list::iterator aIterator, typename node::type_e aFilter = node::All) : iNode(&aNode), iIterator(aIterator), iFilter(aFilter) {}
57 iterator(const iterator& aOther) : iNode(aOther.iNode), iIterator(aOther.iIterator), iFilter(aOther.iFilter) {}
58 iterator& operator=(const iterator& aOther) { iNode = aOther.iNode; iIterator = aOther.iIterator; iFilter = aOther.iFilter; return *this; }
59 public:
60 node& operator*() const { return static_cast<node&>(**iIterator); }
61 node* operator->() const { return static_cast<node*>(&**iIterator); }
63 {
64 ++iIterator;
65 iterator endIterator = iNode->end(iFilter);
66 while (*this != endIterator && !((*iIterator)->type() & iFilter))
67 ++iIterator;
68 return *this;
69 }
71 {
72 --iIterator;
73 iterator beginIterator = iNode->begin(iFilter);
74 while (*this != beginIterator && !((*iIterator)->type() & iFilter))
75 --iIterator;
76 return *this;
77 }
78 iterator operator++(int) { iterator temp(*this); operator++(); return temp; }
79 iterator operator--(int) { iterator temp(*this); operator--(); return temp; }
80 bool operator==(const iterator& aOther) const { return iIterator == aOther.iIterator; }
81 bool operator!=(const iterator& aOther) const { return !(*this == aOther); }
82 typename node::node_list::iterator base() const { return iIterator; }
83 private:
84 node* iNode;
85 typename node::node_list::iterator iIterator;
86 typename node::type_e iFilter;
87 };
89 {
90 public:
91 const_iterator() : iNode(0), iIterator(), iFilter(node::All) {}
92 const_iterator(const node& aNode, typename node::node_list::const_iterator aIterator, typename node::type_e aFilter = node::All) : iNode(&aNode), iIterator(aIterator), iFilter(aFilter) {}
93 const_iterator(const const_iterator& aOther) : iNode(aOther.iNode), iIterator(aOther.iIterator), iFilter(aOther.iFilter) {}
94 const_iterator(const iterator aIterator) : iNode(aIterator.iNode), iIterator(typename node::node_list::const_iterator(aIterator.iIterator)), iFilter(aIterator.iFilter) {}
95 const_iterator& operator=(const const_iterator& aOther) { iNode = aOther.iNode; iIterator = aOther.iIterator; iFilter = aOther.iFilter; return *this; }
96 const_iterator& operator=(const iterator& aOther) { iNode = aOther.iNode; iIterator = aOther.iIterator; iFilter = aOther.iFilter; return *this; }
97 public:
98 const node& operator*() const { return static_cast<const node&>(**iIterator); }
99 const node* operator->() const { return static_cast<const node*>(&**iIterator); }
101 {
102 ++iIterator;
103 const_iterator endIterator = iNode->end(iFilter);
104 while (*this != endIterator && !((*iIterator)->type() & iFilter))
105 ++iIterator;
106 return *this;
107 }
109 {
110 --iIterator;
111 const_iterator beginIterator = iNode->begin(iFilter);
112 while (*this != beginIterator && !((*iIterator)->type() & iFilter))
113 --iIterator;
114 return *this;
115 }
116 const_iterator operator++(int) { const_iterator temp(*this); operator++(); return temp; }
117 const_iterator operator--(int) { const_iterator temp(*this); operator--(); return temp; }
118 bool operator==(const const_iterator& aOther) const { return iIterator == aOther.iIterator; }
119 bool operator!=(const const_iterator& aOther) const { return !(*this == aOther); }
120 typename node::node_list::const_iterator base() const { return iIterator; }
121 private:
122 const node* iNode;
123 typename node::node_list::const_iterator iIterator;
124 typename node::type_e iFilter;
125 };
126
127 public:
128 // construction
129 html_node(type_e aType = Document) : iType(aType) {}
130 virtual ~html_node() { clear(); }
131
132 public:
133 // operations
134 type_e type() const { return iType; }
135 // access
136 bool empty() const { return iContent.empty(); }
137 const node& back() const { return *iContent.back(); }
138 node& back() { return *iContent.back(); }
139 const_iterator begin(type_e aFilter = All) const;
140 const_iterator end(type_e aFilter = All) const;
142 iterator end(type_e aFilter = All);
143 const_iterator find(const string& aName) const;
144 template <typename Exception>
145 const_iterator find_or_throw(const string& aName) const;
146 iterator find(const string& aName);
147 iterator find_or_append(const string& aName);
148 template <typename Exception>
149 iterator find_or_throw(const string& aName);
150 // modifiers
151 void push_back(node_ptr aNode)
152 {
153 std::unique_ptr<node> newNode(aNode);
154 iContent.push_back(0);
155 iContent.back() = newNode.release();
156 }
158 {
159 std::unique_ptr<node> newNode(aNode);
160 typename node_list::iterator i = iContent.insert(aIterator.base(), 0);
161 *i = newNode.release();
162 return iterator(*this, i);
163 }
164 void erase(iterator aIterator)
165 {
166 delete *aIterator.base();
167 iContent.erase(aIterator.base());
168 }
169 void clear()
170 {
171 for (typename node_list::iterator i = iContent.begin(); i != iContent.end(); ++i)
172 delete *i;
173 iContent.clear();
174 }
175
176 private:
177 // implementation
178 const node_list& content() const { return iContent; }
179 node_list& content() { return iContent; }
180 html_node(const html_node&) = delete; // not allowed
181 html_node& operator=(const html_node&) = delete; // not allowed
182
183 private:
184 // attributes
185 type_e iType;
186 node_list iContent;
187 };
188
189 template <typename CharT, typename Alloc = std::allocator<CharT> >
190 class html_element : public html_node<CharT, Alloc>
191 {
192 public:
207
208 public:
209 // allocation
210 static void* operator new(std::size_t) { return typename Alloc::template rebind<html_element>::other().allocate(1); }
211 static void operator delete(void* ptr) { return typename Alloc::template rebind<html_element>::other().deallocate(static_cast<html_element*>(ptr), 1); }
212
213 public:
214 // types
217 typedef typename node::string string;
218 typedef std::pair<const string, string> attribute;
219 typedef std::map<string, string, std::less<string>, typename allocator_type::template rebind<attribute>::other> attribute_list;
221 {
222 public:
223 iterator(typename node::iterator aIterator) : node::iterator(aIterator) {}
224 html_element& operator*() const { return static_cast<html_element&>(node::iterator::operator*()); }
225 html_element* operator->() const { return static_cast<html_element*>(node::iterator::operator->()); }
226 };
228 {
229 public:
230 const_iterator(typename node::const_iterator aIterator) : node::const_iterator(aIterator) {}
231 const_iterator(const iterator& aIterator) : node::const_iterator(aIterator) {}
232 const html_element& operator*() const { return static_cast<const html_element&>(node::const_iterator::operator*()); }
233 const html_element* operator->() const { return static_cast<const html_element*>(node::const_iterator::operator->()); }
234 };
235
236 public:
237 // construction
238 html_element(type_e aType) : node(node::Element), iType(aType), iUseEmptyElementTag(true) {}
239
240 public:
241 // operations
242 type_e type() const { return iType; }
243 using node::insert;
244 typename node::iterator insert(typename node::iterator aPosition, const CharT* aName) { return node::insert(aPosition, new html_element(aName)); }
245 html_element& append(const CharT* aName) { node::push_back(new html_element(aName)); return static_cast<html_element&>(node::back()); }
246 const attribute_list& attributes() const { return iAttributes; }
247 bool has_attribute(const string& aAttributeName) const;
248 const string& attribute_value(const string& aAttributeName) const;
249 const string& attribute_value(const string& aNewAttributeName, const string& aOldAttributeName) const;
254 const string& text() const;
255 bool use_empty_element_tag() const { return iUseEmptyElementTag; }
256 type_e& type() { return iType; }
257 attribute_list& attributes() { return iAttributes; }
258 void set_attribute(const string& aAttributeName, const string& aAttributeValue);
259 void append_text(const string& aText);
260 void set_use_empty_element_tag(bool aUseEmptyElementTag) { iUseEmptyElementTag = aUseEmptyElementTag; }
261
262 private:
263 // attributes
264 type_e iType;
265 attribute_list iAttributes;
266 mutable string iText;
267 bool iUseEmptyElementTag;
268 };
269
270 template <typename CharT, typename Alloc = std::allocator<CharT> >
271 class html_text : public html_node<CharT, Alloc>
272 {
273 public:
274 // allocation
275 static void* operator new(std::size_t) { return typename Alloc::template rebind<html_text>::other().allocate(1); }
276 static void operator delete(void* ptr) { return typename Alloc::template rebind<html_text>::other().deallocate(static_cast<html_text*>(ptr), 1); }
277
278 public:
279 // types
281 typedef typename node::string string;
282
283 public:
284 // construction
285 html_text(const string& aContent = string()) : node(node::Text), iContent(aContent) {}
286
287 public:
288 // operations
289 const string& content() const { return iContent; }
290 string& content() { return iContent; }
291
292 private:
293 // attributes
294 string iContent;
295 };
296
297 template <typename CharT, typename Alloc = std::allocator<CharT> >
298 class html_comment : public html_node<CharT, Alloc>
299 {
300 public:
301 // allocation
302 static void* operator new(std::size_t) { return typename Alloc::template rebind<html_comment>::other().allocate(1); }
303 static void operator delete(void* ptr) { return typename Alloc::template rebind<html_comment>::other().deallocate(static_cast<html_comment*>(ptr), 1); }
304
305 public:
306 // types
308 typedef typename node::string string;
309
310 public:
311 // construction
312 html_comment(const string& aContent = string()) : node(node::Comment), iContent(aContent) {}
313
314 public:
315 // operations
316 const string& content() const { return iContent; }
317 string& content() { return iContent; }
318
319 private:
320 // attributes
321 string iContent;
322 };
323
324 class html
325 {
326 public:
327 struct failed_to_open_html : std::runtime_error { failed_to_open_html() : std::runtime_error("neogfx::html::failed_to_open_html") {} };
328 public:
329 html(std::string const& aFragment);
330 html(std::istream& aDocument);
331 private:
332 void parse();
333 private:
334 std::shared_ptr<std::istream> iDocument;
335 };
336}
html_comment(const string &aContent=string())
Definition html.hpp:312
html_node< CharT, Alloc > node
Definition html.hpp:307
node::string string
Definition html.hpp:308
const string & content() const
Definition html.hpp:316
string & content()
Definition html.hpp:317
const_iterator(const iterator &aIterator)
Definition html.hpp:231
const html_element * operator->() const
Definition html.hpp:233
const html_element & operator*() const
Definition html.hpp:232
const_iterator(typename node::const_iterator aIterator)
Definition html.hpp:230
iterator(typename node::iterator aIterator)
Definition html.hpp:223
html_element * operator->() const
Definition html.hpp:225
html_element & operator*() const
Definition html.hpp:224
node::string string
Definition html.hpp:217
html_element & append(const CharT *aName)
Definition html.hpp:245
html_element(type_e aType)
Definition html.hpp:238
void set_use_empty_element_tag(bool aUseEmptyElementTag)
Definition html.hpp:260
node::iterator insert(typename node::iterator aPosition, const CharT *aName)
Definition html.hpp:244
std::map< string, string, std::less< string >, typename allocator_type::template rebind< attribute >::other > attribute_list
Definition html.hpp:219
const string & text() const
iterator begin()
Definition html.hpp:252
void set_attribute(const string &aAttributeName, const string &aAttributeValue)
void append_text(const string &aText)
bool use_empty_element_tag() const
Definition html.hpp:255
html_node< CharT, Alloc > node
Definition html.hpp:215
type_e & type()
Definition html.hpp:256
const string & attribute_value(const string &aAttributeName) const
const_iterator begin() const
Definition html.hpp:250
attribute_list & attributes()
Definition html.hpp:257
std::pair< const string, string > attribute
Definition html.hpp:218
const string & attribute_value(const string &aNewAttributeName, const string &aOldAttributeName) const
const attribute_list & attributes() const
Definition html.hpp:246
type_e type() const
Definition html.hpp:242
iterator end()
Definition html.hpp:253
const_iterator end() const
Definition html.hpp:251
bool has_attribute(const string &aAttributeName) const
node::allocator_type allocator_type
Definition html.hpp:216
const node * operator->() const
Definition html.hpp:99
const_iterator operator--(int)
Definition html.hpp:117
const_iterator & operator--()
Definition html.hpp:108
const_iterator(const node &aNode, typename node::node_list::const_iterator aIterator, typename node::type_e aFilter=node::All)
Definition html.hpp:92
const_iterator & operator=(const iterator &aOther)
Definition html.hpp:96
const_iterator(const const_iterator &aOther)
Definition html.hpp:93
const_iterator(const iterator aIterator)
Definition html.hpp:94
const_iterator & operator=(const const_iterator &aOther)
Definition html.hpp:95
const node & operator*() const
Definition html.hpp:98
node::node_list::const_iterator base() const
Definition html.hpp:120
const_iterator operator++(int)
Definition html.hpp:116
bool operator==(const const_iterator &aOther) const
Definition html.hpp:118
bool operator!=(const const_iterator &aOther) const
Definition html.hpp:119
const_iterator & operator++()
Definition html.hpp:100
node & operator*() const
Definition html.hpp:60
iterator & operator--()
Definition html.hpp:70
node::node_list::iterator base() const
Definition html.hpp:82
iterator operator--(int)
Definition html.hpp:79
iterator & operator=(const iterator &aOther)
Definition html.hpp:58
bool operator==(const iterator &aOther) const
Definition html.hpp:80
node * operator->() const
Definition html.hpp:61
iterator operator++(int)
Definition html.hpp:78
iterator & operator++()
Definition html.hpp:62
iterator(const iterator &aOther)
Definition html.hpp:57
bool operator!=(const iterator &aOther) const
Definition html.hpp:81
iterator(node &aNode, typename node::node_list::iterator aIterator, typename node::type_e aFilter=node::All)
Definition html.hpp:56
iterator begin(type_e aFilter=All)
iterator find_or_append(const string &aName)
const node & back() const
Definition html.hpp:137
const_iterator begin(type_e aFilter=All) const
node & back()
Definition html.hpp:138
html_node(type_e aType=Document)
Definition html.hpp:129
Alloc allocator_type
Definition html.hpp:39
bool empty() const
Definition html.hpp:136
void push_back(node_ptr aNode)
Definition html.hpp:151
void erase(iterator aIterator)
Definition html.hpp:164
neolib::basic_quick_string< CharT > string
Definition html.hpp:40
iterator end(type_e aFilter=All)
html_node< CharT, allocator_type > node
Definition html.hpp:41
iterator find_or_throw(const string &aName)
iterator insert(iterator aIterator, node_ptr aNode)
Definition html.hpp:157
const_iterator find(const string &aName) const
iterator find(const string &aName)
virtual ~html_node()
Definition html.hpp:130
node * node_ptr
Definition html.hpp:42
const_iterator end(type_e aFilter=All) const
type_e type() const
Definition html.hpp:134
const_iterator find_or_throw(const string &aName) const
const string & content() const
Definition html.hpp:289
html_text(const string &aContent=string())
Definition html.hpp:285
string & content()
Definition html.hpp:290
html_node< CharT, Alloc > node
Definition html.hpp:280
node::string string
Definition html.hpp:281
html(std::istream &aDocument)
html(std::string const &aFragment)