isotree 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -1
  3. data/LICENSE.txt +2 -2
  4. data/README.md +32 -14
  5. data/ext/isotree/ext.cpp +144 -31
  6. data/ext/isotree/extconf.rb +7 -7
  7. data/lib/isotree/isolation_forest.rb +110 -30
  8. data/lib/isotree/version.rb +1 -1
  9. data/vendor/isotree/LICENSE +1 -1
  10. data/vendor/isotree/README.md +165 -27
  11. data/vendor/isotree/include/isotree.hpp +2111 -0
  12. data/vendor/isotree/include/isotree_oop.hpp +394 -0
  13. data/vendor/isotree/inst/COPYRIGHTS +62 -0
  14. data/vendor/isotree/src/RcppExports.cpp +525 -52
  15. data/vendor/isotree/src/Rwrapper.cpp +1931 -268
  16. data/vendor/isotree/src/c_interface.cpp +953 -0
  17. data/vendor/isotree/src/crit.hpp +4232 -0
  18. data/vendor/isotree/src/dist.hpp +1886 -0
  19. data/vendor/isotree/src/exp_depth_table.hpp +134 -0
  20. data/vendor/isotree/src/extended.hpp +1444 -0
  21. data/vendor/isotree/src/external_facing_generic.hpp +399 -0
  22. data/vendor/isotree/src/fit_model.hpp +2401 -0
  23. data/vendor/isotree/src/{dealloc.cpp → headers_joined.hpp} +38 -22
  24. data/vendor/isotree/src/helpers_iforest.hpp +813 -0
  25. data/vendor/isotree/src/{impute.cpp → impute.hpp} +353 -122
  26. data/vendor/isotree/src/indexer.cpp +515 -0
  27. data/vendor/isotree/src/instantiate_template_headers.cpp +118 -0
  28. data/vendor/isotree/src/instantiate_template_headers.hpp +240 -0
  29. data/vendor/isotree/src/isoforest.hpp +1659 -0
  30. data/vendor/isotree/src/isotree.hpp +1804 -392
  31. data/vendor/isotree/src/isotree_exportable.hpp +99 -0
  32. data/vendor/isotree/src/merge_models.cpp +159 -16
  33. data/vendor/isotree/src/mult.hpp +1321 -0
  34. data/vendor/isotree/src/oop_interface.cpp +842 -0
  35. data/vendor/isotree/src/oop_interface.hpp +278 -0
  36. data/vendor/isotree/src/other_helpers.hpp +219 -0
  37. data/vendor/isotree/src/predict.hpp +1932 -0
  38. data/vendor/isotree/src/python_helpers.hpp +134 -0
  39. data/vendor/isotree/src/ref_indexer.hpp +154 -0
  40. data/vendor/isotree/src/robinmap/LICENSE +21 -0
  41. data/vendor/isotree/src/robinmap/README.md +483 -0
  42. data/vendor/isotree/src/robinmap/include/tsl/robin_growth_policy.h +406 -0
  43. data/vendor/isotree/src/robinmap/include/tsl/robin_hash.h +1620 -0
  44. data/vendor/isotree/src/robinmap/include/tsl/robin_map.h +807 -0
  45. data/vendor/isotree/src/robinmap/include/tsl/robin_set.h +660 -0
  46. data/vendor/isotree/src/serialize.cpp +4300 -139
  47. data/vendor/isotree/src/sql.cpp +141 -59
  48. data/vendor/isotree/src/subset_models.cpp +174 -0
  49. data/vendor/isotree/src/utils.hpp +3808 -0
  50. data/vendor/isotree/src/xoshiro.hpp +467 -0
  51. data/vendor/isotree/src/ziggurat.hpp +405 -0
  52. metadata +38 -104
  53. data/vendor/cereal/LICENSE +0 -24
  54. data/vendor/cereal/README.md +0 -85
  55. data/vendor/cereal/include/cereal/access.hpp +0 -351
  56. data/vendor/cereal/include/cereal/archives/adapters.hpp +0 -163
  57. data/vendor/cereal/include/cereal/archives/binary.hpp +0 -169
  58. data/vendor/cereal/include/cereal/archives/json.hpp +0 -1019
  59. data/vendor/cereal/include/cereal/archives/portable_binary.hpp +0 -334
  60. data/vendor/cereal/include/cereal/archives/xml.hpp +0 -956
  61. data/vendor/cereal/include/cereal/cereal.hpp +0 -1089
  62. data/vendor/cereal/include/cereal/details/helpers.hpp +0 -422
  63. data/vendor/cereal/include/cereal/details/polymorphic_impl.hpp +0 -796
  64. data/vendor/cereal/include/cereal/details/polymorphic_impl_fwd.hpp +0 -65
  65. data/vendor/cereal/include/cereal/details/static_object.hpp +0 -127
  66. data/vendor/cereal/include/cereal/details/traits.hpp +0 -1411
  67. data/vendor/cereal/include/cereal/details/util.hpp +0 -84
  68. data/vendor/cereal/include/cereal/external/base64.hpp +0 -134
  69. data/vendor/cereal/include/cereal/external/rapidjson/allocators.h +0 -284
  70. data/vendor/cereal/include/cereal/external/rapidjson/cursorstreamwrapper.h +0 -78
  71. data/vendor/cereal/include/cereal/external/rapidjson/document.h +0 -2652
  72. data/vendor/cereal/include/cereal/external/rapidjson/encodedstream.h +0 -299
  73. data/vendor/cereal/include/cereal/external/rapidjson/encodings.h +0 -716
  74. data/vendor/cereal/include/cereal/external/rapidjson/error/en.h +0 -74
  75. data/vendor/cereal/include/cereal/external/rapidjson/error/error.h +0 -161
  76. data/vendor/cereal/include/cereal/external/rapidjson/filereadstream.h +0 -99
  77. data/vendor/cereal/include/cereal/external/rapidjson/filewritestream.h +0 -104
  78. data/vendor/cereal/include/cereal/external/rapidjson/fwd.h +0 -151
  79. data/vendor/cereal/include/cereal/external/rapidjson/internal/biginteger.h +0 -290
  80. data/vendor/cereal/include/cereal/external/rapidjson/internal/diyfp.h +0 -271
  81. data/vendor/cereal/include/cereal/external/rapidjson/internal/dtoa.h +0 -245
  82. data/vendor/cereal/include/cereal/external/rapidjson/internal/ieee754.h +0 -78
  83. data/vendor/cereal/include/cereal/external/rapidjson/internal/itoa.h +0 -308
  84. data/vendor/cereal/include/cereal/external/rapidjson/internal/meta.h +0 -186
  85. data/vendor/cereal/include/cereal/external/rapidjson/internal/pow10.h +0 -55
  86. data/vendor/cereal/include/cereal/external/rapidjson/internal/regex.h +0 -740
  87. data/vendor/cereal/include/cereal/external/rapidjson/internal/stack.h +0 -232
  88. data/vendor/cereal/include/cereal/external/rapidjson/internal/strfunc.h +0 -69
  89. data/vendor/cereal/include/cereal/external/rapidjson/internal/strtod.h +0 -290
  90. data/vendor/cereal/include/cereal/external/rapidjson/internal/swap.h +0 -46
  91. data/vendor/cereal/include/cereal/external/rapidjson/istreamwrapper.h +0 -128
  92. data/vendor/cereal/include/cereal/external/rapidjson/memorybuffer.h +0 -70
  93. data/vendor/cereal/include/cereal/external/rapidjson/memorystream.h +0 -71
  94. data/vendor/cereal/include/cereal/external/rapidjson/msinttypes/inttypes.h +0 -316
  95. data/vendor/cereal/include/cereal/external/rapidjson/msinttypes/stdint.h +0 -300
  96. data/vendor/cereal/include/cereal/external/rapidjson/ostreamwrapper.h +0 -81
  97. data/vendor/cereal/include/cereal/external/rapidjson/pointer.h +0 -1414
  98. data/vendor/cereal/include/cereal/external/rapidjson/prettywriter.h +0 -277
  99. data/vendor/cereal/include/cereal/external/rapidjson/rapidjson.h +0 -656
  100. data/vendor/cereal/include/cereal/external/rapidjson/reader.h +0 -2230
  101. data/vendor/cereal/include/cereal/external/rapidjson/schema.h +0 -2497
  102. data/vendor/cereal/include/cereal/external/rapidjson/stream.h +0 -223
  103. data/vendor/cereal/include/cereal/external/rapidjson/stringbuffer.h +0 -121
  104. data/vendor/cereal/include/cereal/external/rapidjson/writer.h +0 -709
  105. data/vendor/cereal/include/cereal/external/rapidxml/license.txt +0 -52
  106. data/vendor/cereal/include/cereal/external/rapidxml/manual.html +0 -406
  107. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml.hpp +0 -2624
  108. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml_iterators.hpp +0 -175
  109. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml_print.hpp +0 -428
  110. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml_utils.hpp +0 -123
  111. data/vendor/cereal/include/cereal/macros.hpp +0 -154
  112. data/vendor/cereal/include/cereal/specialize.hpp +0 -139
  113. data/vendor/cereal/include/cereal/types/array.hpp +0 -79
  114. data/vendor/cereal/include/cereal/types/atomic.hpp +0 -55
  115. data/vendor/cereal/include/cereal/types/base_class.hpp +0 -203
  116. data/vendor/cereal/include/cereal/types/bitset.hpp +0 -176
  117. data/vendor/cereal/include/cereal/types/boost_variant.hpp +0 -164
  118. data/vendor/cereal/include/cereal/types/chrono.hpp +0 -72
  119. data/vendor/cereal/include/cereal/types/common.hpp +0 -129
  120. data/vendor/cereal/include/cereal/types/complex.hpp +0 -56
  121. data/vendor/cereal/include/cereal/types/concepts/pair_associative_container.hpp +0 -73
  122. data/vendor/cereal/include/cereal/types/deque.hpp +0 -62
  123. data/vendor/cereal/include/cereal/types/forward_list.hpp +0 -68
  124. data/vendor/cereal/include/cereal/types/functional.hpp +0 -43
  125. data/vendor/cereal/include/cereal/types/list.hpp +0 -62
  126. data/vendor/cereal/include/cereal/types/map.hpp +0 -36
  127. data/vendor/cereal/include/cereal/types/memory.hpp +0 -425
  128. data/vendor/cereal/include/cereal/types/optional.hpp +0 -66
  129. data/vendor/cereal/include/cereal/types/polymorphic.hpp +0 -483
  130. data/vendor/cereal/include/cereal/types/queue.hpp +0 -132
  131. data/vendor/cereal/include/cereal/types/set.hpp +0 -103
  132. data/vendor/cereal/include/cereal/types/stack.hpp +0 -76
  133. data/vendor/cereal/include/cereal/types/string.hpp +0 -61
  134. data/vendor/cereal/include/cereal/types/tuple.hpp +0 -123
  135. data/vendor/cereal/include/cereal/types/unordered_map.hpp +0 -36
  136. data/vendor/cereal/include/cereal/types/unordered_set.hpp +0 -99
  137. data/vendor/cereal/include/cereal/types/utility.hpp +0 -47
  138. data/vendor/cereal/include/cereal/types/valarray.hpp +0 -89
  139. data/vendor/cereal/include/cereal/types/variant.hpp +0 -109
  140. data/vendor/cereal/include/cereal/types/vector.hpp +0 -112
  141. data/vendor/cereal/include/cereal/version.hpp +0 -52
  142. data/vendor/isotree/src/Makevars +0 -4
  143. data/vendor/isotree/src/crit.cpp +0 -912
  144. data/vendor/isotree/src/dist.cpp +0 -749
  145. data/vendor/isotree/src/extended.cpp +0 -790
  146. data/vendor/isotree/src/fit_model.cpp +0 -1090
  147. data/vendor/isotree/src/helpers_iforest.cpp +0 -324
  148. data/vendor/isotree/src/isoforest.cpp +0 -771
  149. data/vendor/isotree/src/mult.cpp +0 -607
  150. data/vendor/isotree/src/predict.cpp +0 -853
  151. data/vendor/isotree/src/utils.cpp +0 -1566
@@ -1,2624 +0,0 @@
1
- #ifndef CEREAL_RAPIDXML_HPP_INCLUDED
2
- #define CEREAL_RAPIDXML_HPP_INCLUDED
3
-
4
- // Copyright (C) 2006, 2009 Marcin Kalicinski
5
- // Version 1.13
6
- // Revision $DateTime: 2009/05/13 01:46:17 $
7
-
8
- // If standard library is disabled, user must provide implementations of required functions and typedefs
9
- #if !defined(CEREAL_RAPIDXML_NO_STDLIB)
10
- #include <cstdlib> // For std::size_t
11
- #include <cassert> // For assert
12
- #include <new> // For placement new
13
- #endif
14
-
15
- // On MSVC, disable "conditional expression is constant" warning (level 4).
16
- // This warning is almost impossible to avoid with certain types of templated code
17
- #ifdef _MSC_VER
18
- #pragma warning(push)
19
- #pragma warning(disable:4127) // Conditional expression is constant
20
- #pragma warning(disable:4100) // unreferenced formal parameter
21
- #endif
22
-
23
- ///////////////////////////////////////////////////////////////////////////
24
- // CEREAL_RAPIDXML_PARSE_ERROR
25
-
26
- #if defined(CEREAL_RAPIDXML_NO_EXCEPTIONS)
27
-
28
- #define CEREAL_RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); }
29
-
30
- namespace cereal {
31
- namespace rapidxml
32
- {
33
- //! When exceptions are disabled by defining CEREAL_RAPIDXML_NO_EXCEPTIONS,
34
- //! this function is called to notify user about the error.
35
- //! It must be defined by the user.
36
- //! <br><br>
37
- //! This function cannot return. If it does, the results are undefined.
38
- //! <br><br>
39
- //! A very simple definition might look like that:
40
- //! <pre>
41
- //! void %rapidxml::%parse_error_handler(const char *what, void *where)
42
- //! {
43
- //! std::cout << "Parse error: " << what << "\n";
44
- //! std::abort();
45
- //! }
46
- //! </pre>
47
- //! \param what Human readable description of the error.
48
- //! \param where Pointer to character data where error was detected.
49
- void parse_error_handler(const char *what, void *where);
50
- }
51
- } // end namespace cereal
52
-
53
- #else
54
-
55
- #include <exception> // For std::exception
56
-
57
- #define CEREAL_RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where)
58
-
59
- namespace cereal {
60
- namespace rapidxml
61
- {
62
-
63
- //! Parse error exception.
64
- //! This exception is thrown by the parser when an error occurs.
65
- //! Use what() function to get human-readable error message.
66
- //! Use where() function to get a pointer to position within source text where error was detected.
67
- //! <br><br>
68
- //! If throwing exceptions by the parser is undesirable,
69
- //! it can be disabled by defining CEREAL_RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included.
70
- //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception.
71
- //! This function must be defined by the user.
72
- //! <br><br>
73
- //! This class derives from <code>std::exception</code> class.
74
- class parse_error: public std::exception
75
- {
76
-
77
- public:
78
-
79
- //! Constructs parse error
80
- parse_error(const char *what_, void *where_)
81
- : m_what(what_)
82
- , m_where(where_)
83
- {
84
- }
85
-
86
- //! Gets human readable description of error.
87
- //! \return Pointer to null terminated description of the error.
88
- virtual const char *what() const CEREAL_NOEXCEPT override
89
- {
90
- return m_what;
91
- }
92
-
93
- //! Gets pointer to character data where error happened.
94
- //! Ch should be the same as char type of xml_document that produced the error.
95
- //! \return Pointer to location within the parsed string where error occured.
96
- template<class Ch>
97
- Ch *where() const
98
- {
99
- return reinterpret_cast<Ch *>(m_where);
100
- }
101
-
102
- private:
103
-
104
- const char *m_what;
105
- void *m_where;
106
-
107
- };
108
- }
109
- } // end namespace cereal
110
-
111
- #endif
112
-
113
- ///////////////////////////////////////////////////////////////////////////
114
- // Pool sizes
115
-
116
- #ifndef CEREAL_RAPIDXML_STATIC_POOL_SIZE
117
- // Size of static memory block of memory_pool.
118
- // Define CEREAL_RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
119
- // No dynamic memory allocations are performed by memory_pool until static memory is exhausted.
120
- #define CEREAL_RAPIDXML_STATIC_POOL_SIZE (64 * 1024)
121
- #endif
122
-
123
- #ifndef CEREAL_RAPIDXML_DYNAMIC_POOL_SIZE
124
- // Size of dynamic memory block of memory_pool.
125
- // Define CEREAL_RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
126
- // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool.
127
- #define CEREAL_RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024)
128
- #endif
129
-
130
- #ifndef CEREAL_RAPIDXML_ALIGNMENT
131
- // Memory allocation alignment.
132
- // Define CEREAL_RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer.
133
- // All memory allocations for nodes, attributes and strings will be aligned to this value.
134
- // This must be a power of 2 and at least 1, otherwise memory_pool will not work.
135
- #define CEREAL_RAPIDXML_ALIGNMENT sizeof(void *)
136
- #endif
137
-
138
- namespace cereal {
139
- namespace rapidxml
140
- {
141
- // Forward declarations
142
- template<class Ch> class xml_node;
143
- template<class Ch> class xml_attribute;
144
- template<class Ch> class xml_document;
145
-
146
- //! Enumeration listing all node types produced by the parser.
147
- //! Use xml_node::type() function to query node type.
148
- enum node_type
149
- {
150
- node_document, //!< A document node. Name and value are empty.
151
- node_element, //!< An element node. Name contains element name. Value contains text of first data node.
152
- node_data, //!< A data node. Name is empty. Value contains data text.
153
- node_cdata, //!< A CDATA node. Name is empty. Value contains data text.
154
- node_comment, //!< A comment node. Name is empty. Value contains comment text.
155
- node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
156
- node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
157
- node_pi //!< A PI node. Name contains target. Value contains instructions.
158
- };
159
-
160
- ///////////////////////////////////////////////////////////////////////
161
- // Parsing flags
162
-
163
- //! Parse flag instructing the parser to not create data nodes.
164
- //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified.
165
- //! Can be combined with other flags by use of | operator.
166
- //! <br><br>
167
- //! See xml_document::parse() function.
168
- const int parse_no_data_nodes = 0x1;
169
-
170
- //! Parse flag instructing the parser to not use text of first data node as a value of parent element.
171
- //! Can be combined with other flags by use of | operator.
172
- //! Note that child data nodes of element node take precendence over its value when printing.
173
- //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored.
174
- //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.
175
- //! <br><br>
176
- //! See xml_document::parse() function.
177
- const int parse_no_element_values = 0x2;
178
-
179
- //! Parse flag instructing the parser to not place zero terminators after strings in the source text.
180
- //! By default zero terminators are placed, modifying source text.
181
- //! Can be combined with other flags by use of | operator.
182
- //! <br><br>
183
- //! See xml_document::parse() function.
184
- const int parse_no_string_terminators = 0x4;
185
-
186
- //! Parse flag instructing the parser to not translate entities in the source text.
187
- //! By default entities are translated, modifying source text.
188
- //! Can be combined with other flags by use of | operator.
189
- //! <br><br>
190
- //! See xml_document::parse() function.
191
- const int parse_no_entity_translation = 0x8;
192
-
193
- //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters.
194
- //! By default, UTF-8 handling is enabled.
195
- //! Can be combined with other flags by use of | operator.
196
- //! <br><br>
197
- //! See xml_document::parse() function.
198
- const int parse_no_utf8 = 0x10;
199
-
200
- //! Parse flag instructing the parser to create XML declaration node.
201
- //! By default, declaration node is not created.
202
- //! Can be combined with other flags by use of | operator.
203
- //! <br><br>
204
- //! See xml_document::parse() function.
205
- const int parse_declaration_node = 0x20;
206
-
207
- //! Parse flag instructing the parser to create comments nodes.
208
- //! By default, comment nodes are not created.
209
- //! Can be combined with other flags by use of | operator.
210
- //! <br><br>
211
- //! See xml_document::parse() function.
212
- const int parse_comment_nodes = 0x40;
213
-
214
- //! Parse flag instructing the parser to create DOCTYPE node.
215
- //! By default, doctype node is not created.
216
- //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one.
217
- //! Can be combined with other flags by use of | operator.
218
- //! <br><br>
219
- //! See xml_document::parse() function.
220
- const int parse_doctype_node = 0x80;
221
-
222
- //! Parse flag instructing the parser to create PI nodes.
223
- //! By default, PI nodes are not created.
224
- //! Can be combined with other flags by use of | operator.
225
- //! <br><br>
226
- //! See xml_document::parse() function.
227
- const int parse_pi_nodes = 0x100;
228
-
229
- //! Parse flag instructing the parser to validate closing tag names.
230
- //! If not set, name inside closing tag is irrelevant to the parser.
231
- //! By default, closing tags are not validated.
232
- //! Can be combined with other flags by use of | operator.
233
- //! <br><br>
234
- //! See xml_document::parse() function.
235
- const int parse_validate_closing_tags = 0x200;
236
-
237
- //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes.
238
- //! By default, whitespace is not trimmed.
239
- //! This flag does not cause the parser to modify source text.
240
- //! Can be combined with other flags by use of | operator.
241
- //! <br><br>
242
- //! See xml_document::parse() function.
243
- const int parse_trim_whitespace = 0x400;
244
-
245
- //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character.
246
- //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag.
247
- //! By default, whitespace is not normalized.
248
- //! If this flag is specified, source text will be modified.
249
- //! Can be combined with other flags by use of | operator.
250
- //! <br><br>
251
- //! See xml_document::parse() function.
252
- const int parse_normalize_whitespace = 0x800;
253
-
254
- // Compound flags
255
-
256
- //! Parse flags which represent default behaviour of the parser.
257
- //! This is always equal to 0, so that all other flags can be simply ored together.
258
- //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values.
259
- //! This also means that meaning of each flag is a <i>negation</i> of the default setting.
260
- //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default,
261
- //! and using the flag will disable it.
262
- //! <br><br>
263
- //! See xml_document::parse() function.
264
- const int parse_default = 0;
265
-
266
- //! A combination of parse flags that forbids any modifications of the source text.
267
- //! This also results in faster parsing. However, note that the following will occur:
268
- //! <ul>
269
- //! <li>names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends</li>
270
- //! <li>entities will not be translated</li>
271
- //! <li>whitespace will not be normalized</li>
272
- //! </ul>
273
- //! See xml_document::parse() function.
274
- const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;
275
-
276
- //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.
277
- //! <br><br>
278
- //! See xml_document::parse() function.
279
- const int parse_fastest = parse_non_destructive | parse_no_data_nodes;
280
-
281
- //! A combination of parse flags resulting in largest amount of data being extracted.
282
- //! This usually results in slowest parsing.
283
- //! <br><br>
284
- //! See xml_document::parse() function.
285
- const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
286
-
287
- ///////////////////////////////////////////////////////////////////////
288
- // Internals
289
-
290
- //! \cond internal
291
- namespace internal
292
- {
293
-
294
- // Struct that contains lookup tables for the parser
295
- // It must be a template to allow correct linking (because it has static data members, which are defined in a header file).
296
- template<int Dummy>
297
- struct lookup_tables
298
- {
299
- static const unsigned char lookup_whitespace[256]; // Whitespace table
300
- static const unsigned char lookup_node_name[256]; // Node name table
301
- static const unsigned char lookup_text[256]; // Text table
302
- static const unsigned char lookup_text_pure_no_ws[256]; // Text table
303
- static const unsigned char lookup_text_pure_with_ws[256]; // Text table
304
- static const unsigned char lookup_attribute_name[256]; // Attribute name table
305
- static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote
306
- static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote
307
- static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes
308
- static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes
309
- static const unsigned char lookup_digits[256]; // Digits
310
- static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters
311
- };
312
-
313
- // Find length of the string
314
- template<class Ch>
315
- inline std::size_t measure(const Ch *p)
316
- {
317
- const Ch *tmp = p;
318
- while (*tmp)
319
- ++tmp;
320
- return static_cast<std::size_t>(tmp - p);
321
- }
322
-
323
- // Compare strings for equality
324
- template<class Ch>
325
- inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive)
326
- {
327
- if (size1 != size2)
328
- return false;
329
- if (case_sensitive)
330
- {
331
- for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
332
- if (*p1 != *p2)
333
- return false;
334
- }
335
- else
336
- {
337
- for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
338
- if (lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p1)] != lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p2)])
339
- return false;
340
- }
341
- return true;
342
- }
343
-
344
- template<class Ch>
345
- inline bool preserve_space(xml_node<Ch>* node)
346
- {
347
- const Ch preserve_value[] = { Ch('p'), Ch('r'), Ch('e'), Ch('s'), Ch('e'), Ch('r'), Ch('v'), Ch('e') };
348
- const xml_attribute<Ch>* space = node->first_attribute("xml:space");
349
- return space && internal::compare(space->value(), space->value_size(), preserve_value, sizeof(preserve_value) / sizeof(Ch), true);
350
- }
351
- }
352
- //! \endcond
353
-
354
- ///////////////////////////////////////////////////////////////////////
355
- // Memory pool
356
-
357
- //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation.
358
- //! In most cases, you will not need to use this class directly.
359
- //! However, if you need to create nodes manually or modify names/values of nodes,
360
- //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory.
361
- //! Not only is this faster than allocating them by using <code>new</code> operator,
362
- //! but also their lifetime will be tied to the lifetime of document,
363
- //! possibly simplyfing memory management.
364
- //! <br><br>
365
- //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool.
366
- //! You can also call allocate_string() function to allocate strings.
367
- //! Such strings can then be used as names or values of nodes without worrying about their lifetime.
368
- //! Note that there is no <code>free()</code> function -- all allocations are freed at once when clear() function is called,
369
- //! or when the pool is destroyed.
370
- //! <br><br>
371
- //! It is also possible to create a standalone memory_pool, and use it
372
- //! to allocate nodes, whose lifetime will not be tied to any document.
373
- //! <br><br>
374
- //! Pool maintains <code>CEREAL_RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory.
375
- //! Until static memory is exhausted, no dynamic memory allocations are done.
376
- //! When static memory is exhausted, pool allocates additional blocks of memory of size <code>CEREAL_RAPIDXML_DYNAMIC_POOL_SIZE</code> each,
377
- //! by using global <code>new[]</code> and <code>delete[]</code> operators.
378
- //! This behaviour can be changed by setting custom allocation routines.
379
- //! Use set_allocator() function to set them.
380
- //! <br><br>
381
- //! Allocations for nodes, attributes and strings are aligned at <code>CEREAL_RAPIDXML_ALIGNMENT</code> bytes.
382
- //! This value defaults to the size of pointer on target architecture.
383
- //! <br><br>
384
- //! To obtain absolutely top performance from the parser,
385
- //! it is important that all nodes are allocated from a single, contiguous block of memory.
386
- //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably.
387
- //! If required, you can tweak <code>CEREAL_RAPIDXML_STATIC_POOL_SIZE</code>, <code>CEREAL_RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>CEREAL_RAPIDXML_ALIGNMENT</code>
388
- //! to obtain best wasted memory to performance compromise.
389
- //! To do it, define their values before rapidxml.hpp file is included.
390
- //! \tparam Ch Character type of created nodes.
391
- template<class Ch = char>
392
- class memory_pool
393
- {
394
-
395
- public:
396
-
397
- //! \cond internal
398
- typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory
399
- typedef void (free_func)(void *); // Type of user-defined function used to free memory
400
- //! \endcond
401
-
402
- //! Constructs empty pool with default allocator functions.
403
- memory_pool()
404
- : m_alloc_func(0)
405
- , m_free_func(0)
406
- {
407
- init();
408
- }
409
-
410
- //! Destroys pool and frees all the memory.
411
- //! This causes memory occupied by nodes allocated by the pool to be freed.
412
- //! Nodes allocated from the pool are no longer valid.
413
- ~memory_pool()
414
- {
415
- clear();
416
- }
417
-
418
- //! Allocates a new node from the pool, and optionally assigns name and value to it.
419
- //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
420
- //! If exceptions are disabled by defining CEREAL_RAPIDXML_NO_EXCEPTIONS, this function
421
- //! will call rapidxml::parse_error_handler() function.
422
- //! \param type Type of node to create.
423
- //! \param name Name to assign to the node, or 0 to assign no name.
424
- //! \param value Value to assign to the node, or 0 to assign no value.
425
- //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
426
- //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
427
- //! \return Pointer to allocated node. This pointer will never be NULL.
428
- xml_node<Ch> *allocate_node(node_type type,
429
- const Ch *name = 0, const Ch *value = 0,
430
- std::size_t name_size = 0, std::size_t value_size = 0)
431
- {
432
- void *memory = allocate_aligned(sizeof(xml_node<Ch>));
433
- xml_node<Ch> *node = new(memory) xml_node<Ch>(type);
434
- if (name)
435
- {
436
- if (name_size > 0)
437
- node->name(name, name_size);
438
- else
439
- node->name(name);
440
- }
441
- if (value)
442
- {
443
- if (value_size > 0)
444
- node->value(value, value_size);
445
- else
446
- node->value(value);
447
- }
448
- return node;
449
- }
450
-
451
- //! Allocates a new attribute from the pool, and optionally assigns name and value to it.
452
- //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
453
- //! If exceptions are disabled by defining CEREAL_RAPIDXML_NO_EXCEPTIONS, this function
454
- //! will call rapidxml::parse_error_handler() function.
455
- //! \param name Name to assign to the attribute, or 0 to assign no name.
456
- //! \param value Value to assign to the attribute, or 0 to assign no value.
457
- //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
458
- //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
459
- //! \return Pointer to allocated attribute. This pointer will never be NULL.
460
- xml_attribute<Ch> *allocate_attribute(const Ch *name = 0, const Ch *value = 0,
461
- std::size_t name_size = 0, std::size_t value_size = 0)
462
- {
463
- void *memory = allocate_aligned(sizeof(xml_attribute<Ch>));
464
- xml_attribute<Ch> *attribute = new(memory) xml_attribute<Ch>;
465
- if (name)
466
- {
467
- if (name_size > 0)
468
- attribute->name(name, name_size);
469
- else
470
- attribute->name(name);
471
- }
472
- if (value)
473
- {
474
- if (value_size > 0)
475
- attribute->value(value, value_size);
476
- else
477
- attribute->value(value);
478
- }
479
- return attribute;
480
- }
481
-
482
- //! Allocates a char array of given size from the pool, and optionally copies a given string to it.
483
- //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
484
- //! If exceptions are disabled by defining CEREAL_RAPIDXML_NO_EXCEPTIONS, this function
485
- //! will call rapidxml::parse_error_handler() function.
486
- //! \param source String to initialize the allocated memory with, or 0 to not initialize it.
487
- //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.
488
- //! \return Pointer to allocated char array. This pointer will never be NULL.
489
- Ch *allocate_string(const Ch *source = 0, std::size_t size = 0)
490
- {
491
- assert(source || size); // Either source or size (or both) must be specified
492
- if (size == 0)
493
- size = internal::measure(source) + 1;
494
- Ch *result = static_cast<Ch *>(allocate_aligned(size * sizeof(Ch)));
495
- if (source)
496
- for (std::size_t i = 0; i < size; ++i)
497
- result[i] = source[i];
498
- return result;
499
- }
500
-
501
- //! Clones an xml_node and its hierarchy of child nodes and attributes.
502
- //! Nodes and attributes are allocated from this memory pool.
503
- //! Names and values are not cloned, they are shared between the clone and the source.
504
- //! Result node can be optionally specified as a second parameter,
505
- //! in which case its contents will be replaced with cloned source node.
506
- //! This is useful when you want to clone entire document.
507
- //! \param source Node to clone.
508
- //! \param result Node to put results in, or 0 to automatically allocate result node
509
- //! \return Pointer to cloned node. This pointer will never be NULL.
510
- xml_node<Ch> *clone_node(const xml_node<Ch> *source, xml_node<Ch> *result = 0)
511
- {
512
- // Prepare result node
513
- if (result)
514
- {
515
- result->remove_all_attributes();
516
- result->remove_all_nodes();
517
- result->type(source->type());
518
- }
519
- else
520
- result = allocate_node(source->type());
521
-
522
- // Clone name and value
523
- result->name(source->name(), source->name_size());
524
- result->value(source->value(), source->value_size());
525
-
526
- // Clone child nodes and attributes
527
- for (xml_node<Ch> *child = source->first_node(); child; child = child->next_sibling())
528
- result->append_node(clone_node(child));
529
- for (xml_attribute<Ch> *attr = source->first_attribute(); attr; attr = attr->next_attribute())
530
- result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size()));
531
-
532
- return result;
533
- }
534
-
535
- //! Clears the pool.
536
- //! This causes memory occupied by nodes allocated by the pool to be freed.
537
- //! Any nodes or strings allocated from the pool will no longer be valid.
538
- void clear()
539
- {
540
- while (m_begin != m_static_memory)
541
- {
542
- char *previous_begin = reinterpret_cast<header *>(align(m_begin))->previous_begin;
543
- if (m_free_func)
544
- m_free_func(m_begin);
545
- else
546
- delete[] m_begin;
547
- m_begin = previous_begin;
548
- }
549
- init();
550
- }
551
-
552
- //! Sets or resets the user-defined memory allocation functions for the pool.
553
- //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined.
554
- //! Allocation function must not return invalid pointer on failure. It should either throw,
555
- //! stop the program, or use <code>longjmp()</code> function to pass control to other place of program.
556
- //! If it returns invalid pointer, results are undefined.
557
- //! <br><br>
558
- //! User defined allocation functions must have the following forms:
559
- //! <br><code>
560
- //! <br>void *allocate(std::size_t size);
561
- //! <br>void free(void *pointer);
562
- //! </code><br>
563
- //! \param af Allocation function, or 0 to restore default function
564
- //! \param ff Free function, or 0 to restore default function
565
- void set_allocator(alloc_func *af, free_func *ff)
566
- {
567
- assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet
568
- m_alloc_func = af;
569
- m_free_func = ff;
570
- }
571
-
572
- private:
573
-
574
- struct header
575
- {
576
- char *previous_begin;
577
- };
578
-
579
- void init()
580
- {
581
- m_begin = m_static_memory;
582
- m_ptr = align(m_begin);
583
- m_end = m_static_memory + sizeof(m_static_memory);
584
- }
585
-
586
- char *align(char *ptr)
587
- {
588
- std::size_t alignment = ((CEREAL_RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (CEREAL_RAPIDXML_ALIGNMENT - 1))) & (CEREAL_RAPIDXML_ALIGNMENT - 1));
589
- return ptr + alignment;
590
- }
591
-
592
- char *allocate_raw(std::size_t size)
593
- {
594
- // Allocate
595
- void *memory;
596
- if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[]
597
- {
598
- memory = m_alloc_func(size);
599
- assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp
600
- }
601
- else
602
- {
603
- memory = new char[size];
604
- #ifdef CEREAL_RAPIDXML_NO_EXCEPTIONS
605
- if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc
606
- CEREAL_RAPIDXML_PARSE_ERROR("out of memory", 0);
607
- #endif
608
- }
609
- return static_cast<char *>(memory);
610
- }
611
-
612
- void *allocate_aligned(std::size_t size)
613
- {
614
- // Calculate aligned pointer
615
- char *result = align(m_ptr);
616
-
617
- // If not enough memory left in current pool, allocate a new pool
618
- if (result + size > m_end)
619
- {
620
- // Calculate required pool size (may be bigger than CEREAL_RAPIDXML_DYNAMIC_POOL_SIZE)
621
- std::size_t pool_size = CEREAL_RAPIDXML_DYNAMIC_POOL_SIZE;
622
- if (pool_size < size)
623
- pool_size = size;
624
-
625
- // Allocate
626
- std::size_t alloc_size = sizeof(header) + (2 * CEREAL_RAPIDXML_ALIGNMENT - 2) + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation
627
- char *raw_memory = allocate_raw(alloc_size);
628
-
629
- // Setup new pool in allocated memory
630
- char *pool = align(raw_memory);
631
- header *new_header = reinterpret_cast<header *>(pool);
632
- new_header->previous_begin = m_begin;
633
- m_begin = raw_memory;
634
- m_ptr = pool + sizeof(header);
635
- m_end = raw_memory + alloc_size;
636
-
637
- // Calculate aligned pointer again using new pool
638
- result = align(m_ptr);
639
- }
640
-
641
- // Update pool and return aligned pointer
642
- m_ptr = result + size;
643
- return result;
644
- }
645
-
646
- char *m_begin; // Start of raw memory making up current pool
647
- char *m_ptr; // First free byte in current pool
648
- char *m_end; // One past last available byte in current pool
649
- char m_static_memory[CEREAL_RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory
650
- alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used
651
- free_func *m_free_func; // Free function, or 0 if default is to be used
652
- };
653
-
654
- ///////////////////////////////////////////////////////////////////////////
655
- // XML base
656
-
657
- //! Base class for xml_node and xml_attribute implementing common functions:
658
- //! name(), name_size(), value(), value_size() and parent().
659
- //! \tparam Ch Character type to use
660
- template<class Ch = char>
661
- class xml_base
662
- {
663
-
664
- public:
665
-
666
- ///////////////////////////////////////////////////////////////////////////
667
- // Construction & destruction
668
-
669
- // Construct a base with empty name, value and parent
670
- xml_base()
671
- : m_name(0)
672
- , m_value(0)
673
- , m_parent(0)
674
- {
675
- }
676
-
677
- ///////////////////////////////////////////////////////////////////////////
678
- // Node data access
679
-
680
- //! Gets name of the node.
681
- //! Interpretation of name depends on type of node.
682
- //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
683
- //! <br><br>
684
- //! Use name_size() function to determine length of the name.
685
- //! \return Name of node, or empty string if node has no name.
686
- Ch *name() const
687
- {
688
- return m_name ? m_name : nullstr();
689
- }
690
-
691
- //! Gets size of node name, not including terminator character.
692
- //! This function works correctly irrespective of whether name is or is not zero terminated.
693
- //! \return Size of node name, in characters.
694
- std::size_t name_size() const
695
- {
696
- return m_name ? m_name_size : 0;
697
- }
698
-
699
- //! Gets value of node.
700
- //! Interpretation of value depends on type of node.
701
- //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
702
- //! <br><br>
703
- //! Use value_size() function to determine length of the value.
704
- //! \return Value of node, or empty string if node has no value.
705
- Ch *value() const
706
- {
707
- return m_value ? m_value : nullstr();
708
- }
709
-
710
- //! Gets size of node value, not including terminator character.
711
- //! This function works correctly irrespective of whether value is or is not zero terminated.
712
- //! \return Size of node value, in characters.
713
- std::size_t value_size() const
714
- {
715
- return m_value ? m_value_size : 0;
716
- }
717
-
718
- ///////////////////////////////////////////////////////////////////////////
719
- // Node modification
720
-
721
- //! Sets name of node to a non zero-terminated string.
722
- //! See \ref ownership_of_strings.
723
- //! <br><br>
724
- //! Note that node does not own its name or value, it only stores a pointer to it.
725
- //! It will not delete or otherwise free the pointer on destruction.
726
- //! It is reponsibility of the user to properly manage lifetime of the string.
727
- //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
728
- //! on destruction of the document the string will be automatically freed.
729
- //! <br><br>
730
- //! Size of name must be specified separately, because name does not have to be zero terminated.
731
- //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).
732
- //! \param name_ Name of node to set. Does not have to be zero terminated.
733
- //! \param size Size of name, in characters. This does not include zero terminator, if one is present.
734
- void name(const Ch *name_, std::size_t size)
735
- {
736
- m_name = const_cast<Ch *>(name_);
737
- m_name_size = size;
738
- }
739
-
740
- //! Sets name of node to a zero-terminated string.
741
- //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t).
742
- //! \param name_ Name of node to set. Must be zero terminated.
743
- void name(const Ch *name_)
744
- {
745
- this->name(name_, internal::measure(name_));
746
- }
747
-
748
- //! Sets value of node to a non zero-terminated string.
749
- //! See \ref ownership_of_strings.
750
- //! <br><br>
751
- //! Note that node does not own its name or value, it only stores a pointer to it.
752
- //! It will not delete or otherwise free the pointer on destruction.
753
- //! It is reponsibility of the user to properly manage lifetime of the string.
754
- //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
755
- //! on destruction of the document the string will be automatically freed.
756
- //! <br><br>
757
- //! Size of value must be specified separately, because it does not have to be zero terminated.
758
- //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).
759
- //! <br><br>
760
- //! If an element has a child node of type node_data, it will take precedence over element value when printing.
761
- //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.
762
- //! \param value_ value of node to set. Does not have to be zero terminated.
763
- //! \param size Size of value, in characters. This does not include zero terminator, if one is present.
764
- void value(const Ch *value_, std::size_t size)
765
- {
766
- m_value = const_cast<Ch *>(value_);
767
- m_value_size = size;
768
- }
769
-
770
- //! Sets value of node to a zero-terminated string.
771
- //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t).
772
- //! \param value_ Vame of node to set. Must be zero terminated.
773
- void value(const Ch *value_)
774
- {
775
- this->value(value_, internal::measure(value_));
776
- }
777
-
778
- ///////////////////////////////////////////////////////////////////////////
779
- // Related nodes access
780
-
781
- //! Gets node parent.
782
- //! \return Pointer to parent node, or 0 if there is no parent.
783
- xml_node<Ch> *parent() const
784
- {
785
- return m_parent;
786
- }
787
-
788
- protected:
789
-
790
- // Return empty string
791
- static Ch *nullstr()
792
- {
793
- static Ch zero = Ch('\0');
794
- return &zero;
795
- }
796
-
797
- Ch *m_name; // Name of node, or 0 if no name
798
- Ch *m_value; // Value of node, or 0 if no value
799
- std::size_t m_name_size; // Length of node name, or undefined of no name
800
- std::size_t m_value_size; // Length of node value, or undefined if no value
801
- xml_node<Ch> *m_parent; // Pointer to parent node, or 0 if none
802
-
803
- };
804
-
805
- //! Class representing attribute node of XML document.
806
- //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base).
807
- //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing.
808
- //! Thus, this text must persist in memory for the lifetime of attribute.
809
- //! \tparam Ch Character type to use.
810
- template<class Ch = char>
811
- class xml_attribute: public xml_base<Ch>
812
- {
813
-
814
- friend class xml_node<Ch>;
815
-
816
- public:
817
-
818
- ///////////////////////////////////////////////////////////////////////////
819
- // Construction & destruction
820
-
821
- //! Constructs an empty attribute with the specified type.
822
- //! Consider using memory_pool of appropriate xml_document if allocating attributes manually.
823
- xml_attribute()
824
- {
825
- }
826
-
827
- ///////////////////////////////////////////////////////////////////////////
828
- // Related nodes access
829
-
830
- //! Gets document of which attribute is a child.
831
- //! \return Pointer to document that contains this attribute, or 0 if there is no parent document.
832
- xml_document<Ch> *document() const
833
- {
834
- if (xml_node<Ch> *node = this->parent())
835
- {
836
- while (node->parent())
837
- node = node->parent();
838
- return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
839
- }
840
- else
841
- return 0;
842
- }
843
-
844
- //! Gets previous attribute, optionally matching attribute name.
845
- //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
846
- //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
847
- //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
848
- //! \return Pointer to found attribute, or 0 if not found.
849
- xml_attribute<Ch> *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
850
- {
851
- if (name)
852
- {
853
- if (name_size == 0)
854
- name_size = internal::measure(name);
855
- for (xml_attribute<Ch> *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute)
856
- if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
857
- return attribute;
858
- return 0;
859
- }
860
- else
861
- return this->m_parent ? m_prev_attribute : 0;
862
- }
863
-
864
- //! Gets next attribute, optionally matching attribute name.
865
- //! \param name_ Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
866
- //! \param name_size_ Size of name, in characters, or 0 to have size calculated automatically from string
867
- //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
868
- //! \return Pointer to found attribute, or 0 if not found.
869
- xml_attribute<Ch> *next_attribute(const Ch *name_ = 0, std::size_t name_size_ = 0, bool case_sensitive = true) const
870
- {
871
- if (name_)
872
- {
873
- if (name_size_ == 0)
874
- name_size_ = internal::measure(name_);
875
- for (xml_attribute<Ch> *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute)
876
- if (internal::compare(attribute->name(), attribute->name_size(), name_, name_size_, case_sensitive))
877
- return attribute;
878
- return 0;
879
- }
880
- else
881
- return this->m_parent ? m_next_attribute : 0;
882
- }
883
-
884
- private:
885
-
886
- xml_attribute<Ch> *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero
887
- xml_attribute<Ch> *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero
888
-
889
- };
890
-
891
- ///////////////////////////////////////////////////////////////////////////
892
- // XML node
893
-
894
- //! Class representing a node of XML document.
895
- //! Each node may have associated name and value strings, which are available through name() and value() functions.
896
- //! Interpretation of name and value depends on type of the node.
897
- //! Type of node can be determined by using type() function.
898
- //! <br><br>
899
- //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing.
900
- //! Thus, this text must persist in the memory for the lifetime of node.
901
- //! \tparam Ch Character type to use.
902
- template<class Ch = char>
903
- class xml_node: public xml_base<Ch>
904
- {
905
-
906
- public:
907
-
908
- ///////////////////////////////////////////////////////////////////////////
909
- // Construction & destruction
910
-
911
- //! Constructs an empty node with the specified type.
912
- //! Consider using memory_pool of appropriate document to allocate nodes manually.
913
- //! \param type_ Type of node to construct.
914
- xml_node(node_type type_)
915
- : m_type(type_)
916
- , m_first_node(0)
917
- , m_first_attribute(0)
918
- {
919
- }
920
-
921
- ///////////////////////////////////////////////////////////////////////////
922
- // Node data access
923
-
924
- //! Gets type of node.
925
- //! \return Type of node.
926
- node_type type() const
927
- {
928
- return m_type;
929
- }
930
-
931
- ///////////////////////////////////////////////////////////////////////////
932
- // Related nodes access
933
-
934
- //! Gets document of which node is a child.
935
- //! \return Pointer to document that contains this node, or 0 if there is no parent document.
936
- xml_document<Ch> *document() const
937
- {
938
- xml_node<Ch> *node = const_cast<xml_node<Ch> *>(this);
939
- while (node->parent())
940
- node = node->parent();
941
- return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
942
- }
943
-
944
- //! Gets first child node, optionally matching node name.
945
- //! \param name_ Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
946
- //! \param name_size_ Size of name, in characters, or 0 to have size calculated automatically from string
947
- //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
948
- //! \return Pointer to found child, or 0 if not found.
949
- xml_node<Ch> *first_node(const Ch *name_ = 0, std::size_t name_size_ = 0, bool case_sensitive = true) const
950
- {
951
- if (name_)
952
- {
953
- if (name_size_ == 0)
954
- name_size_ = internal::measure(name_);
955
- for (xml_node<Ch> *child = m_first_node; child; child = child->next_sibling())
956
- if (internal::compare(child->name(), child->name_size(), name_, name_size_, case_sensitive))
957
- return child;
958
- return 0;
959
- }
960
- else
961
- return m_first_node;
962
- }
963
-
964
- //! Gets last child node, optionally matching node name.
965
- //! Behaviour is undefined if node has no children.
966
- //! Use first_node() to test if node has children.
967
- //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
968
- //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
969
- //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
970
- //! \return Pointer to found child, or 0 if not found.
971
- xml_node<Ch> *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
972
- {
973
- assert(m_first_node); // Cannot query for last child if node has no children
974
- if (name)
975
- {
976
- if (name_size == 0)
977
- name_size = internal::measure(name);
978
- for (xml_node<Ch> *child = m_last_node; child; child = child->previous_sibling())
979
- if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
980
- return child;
981
- return 0;
982
- }
983
- else
984
- return m_last_node;
985
- }
986
-
987
- //! Gets previous sibling node, optionally matching node name.
988
- //! Behaviour is undefined if node has no parent.
989
- //! Use parent() to test if node has a parent.
990
- //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
991
- //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
992
- //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
993
- //! \return Pointer to found sibling, or 0 if not found.
994
- xml_node<Ch> *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
995
- {
996
- assert(this->m_parent); // Cannot query for siblings if node has no parent
997
- if (name)
998
- {
999
- if (name_size == 0)
1000
- name_size = internal::measure(name);
1001
- for (xml_node<Ch> *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling)
1002
- if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
1003
- return sibling;
1004
- return 0;
1005
- }
1006
- else
1007
- return m_prev_sibling;
1008
- }
1009
-
1010
- //! Gets next sibling node, optionally matching node name.
1011
- //! Behaviour is undefined if node has no parent.
1012
- //! Use parent() to test if node has a parent.
1013
- //! \param name_ Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
1014
- //! \param name_size_ Size of name, in characters, or 0 to have size calculated automatically from string
1015
- //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
1016
- //! \return Pointer to found sibling, or 0 if not found.
1017
- xml_node<Ch> *next_sibling(const Ch *name_ = 0, std::size_t name_size_ = 0, bool case_sensitive = true) const
1018
- {
1019
- assert(this->m_parent); // Cannot query for siblings if node has no parent
1020
- if (name_)
1021
- {
1022
- if (name_size_ == 0)
1023
- name_size_ = internal::measure(name_);
1024
- for (xml_node<Ch> *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling)
1025
- if (internal::compare(sibling->name(), sibling->name_size(), name_, name_size_, case_sensitive))
1026
- return sibling;
1027
- return 0;
1028
- }
1029
- else
1030
- return m_next_sibling;
1031
- }
1032
-
1033
- //! Gets first attribute of node, optionally matching attribute name.
1034
- //! \param name_ Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
1035
- //! \param name_size_ Size of name, in characters, or 0 to have size calculated automatically from string
1036
- //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
1037
- //! \return Pointer to found attribute, or 0 if not found.
1038
- xml_attribute<Ch> *first_attribute(const Ch *name_ = 0, std::size_t name_size_ = 0, bool case_sensitive = true) const
1039
- {
1040
- if (name_)
1041
- {
1042
- if (name_size_ == 0)
1043
- name_size_ = internal::measure(name_);
1044
- for (xml_attribute<Ch> *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute)
1045
- if (internal::compare(attribute->name(), attribute->name_size(), name_, name_size_, case_sensitive))
1046
- return attribute;
1047
- return 0;
1048
- }
1049
- else
1050
- return m_first_attribute;
1051
- }
1052
-
1053
- //! Gets last attribute of node, optionally matching attribute name.
1054
- //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
1055
- //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
1056
- //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
1057
- //! \return Pointer to found attribute, or 0 if not found.
1058
- xml_attribute<Ch> *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
1059
- {
1060
- if (name)
1061
- {
1062
- if (name_size == 0)
1063
- name_size = internal::measure(name);
1064
- for (xml_attribute<Ch> *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute)
1065
- if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
1066
- return attribute;
1067
- return 0;
1068
- }
1069
- else
1070
- return m_first_attribute ? m_last_attribute : 0;
1071
- }
1072
-
1073
- ///////////////////////////////////////////////////////////////////////////
1074
- // Node modification
1075
-
1076
- //! Sets type of node.
1077
- //! \param type_ Type of node to set.
1078
- void type(node_type type_)
1079
- {
1080
- m_type = type_;
1081
- }
1082
-
1083
- ///////////////////////////////////////////////////////////////////////////
1084
- // Node manipulation
1085
-
1086
- //! Prepends a new child node.
1087
- //! The prepended child becomes the first child, and all existing children are moved one position back.
1088
- //! \param child Node to prepend.
1089
- void prepend_node(xml_node<Ch> *child)
1090
- {
1091
- assert(child && !child->parent() && child->type() != node_document);
1092
- if (first_node())
1093
- {
1094
- child->m_next_sibling = m_first_node;
1095
- m_first_node->m_prev_sibling = child;
1096
- }
1097
- else
1098
- {
1099
- child->m_next_sibling = 0;
1100
- m_last_node = child;
1101
- }
1102
- m_first_node = child;
1103
- child->m_parent = this;
1104
- child->m_prev_sibling = 0;
1105
- }
1106
-
1107
- //! Appends a new child node.
1108
- //! The appended child becomes the last child.
1109
- //! \param child Node to append.
1110
- void append_node(xml_node<Ch> *child)
1111
- {
1112
- assert(child && !child->parent() && child->type() != node_document);
1113
- if (first_node())
1114
- {
1115
- child->m_prev_sibling = m_last_node;
1116
- m_last_node->m_next_sibling = child;
1117
- }
1118
- else
1119
- {
1120
- child->m_prev_sibling = 0;
1121
- m_first_node = child;
1122
- }
1123
- m_last_node = child;
1124
- child->m_parent = this;
1125
- child->m_next_sibling = 0;
1126
- }
1127
-
1128
- //! Inserts a new child node at specified place inside the node.
1129
- //! All children after and including the specified node are moved one position back.
1130
- //! \param where Place where to insert the child, or 0 to insert at the back.
1131
- //! \param child Node to insert.
1132
- void insert_node(xml_node<Ch> *where, xml_node<Ch> *child)
1133
- {
1134
- assert(!where || where->parent() == this);
1135
- assert(child && !child->parent() && child->type() != node_document);
1136
- if (where == m_first_node)
1137
- prepend_node(child);
1138
- else if (where == 0)
1139
- append_node(child);
1140
- else
1141
- {
1142
- child->m_prev_sibling = where->m_prev_sibling;
1143
- child->m_next_sibling = where;
1144
- where->m_prev_sibling->m_next_sibling = child;
1145
- where->m_prev_sibling = child;
1146
- child->m_parent = this;
1147
- }
1148
- }
1149
-
1150
- //! Removes first child node.
1151
- //! If node has no children, behaviour is undefined.
1152
- //! Use first_node() to test if node has children.
1153
- void remove_first_node()
1154
- {
1155
- assert(first_node());
1156
- xml_node<Ch> *child = m_first_node;
1157
- m_first_node = child->m_next_sibling;
1158
- if (child->m_next_sibling)
1159
- child->m_next_sibling->m_prev_sibling = 0;
1160
- else
1161
- m_last_node = 0;
1162
- child->m_parent = 0;
1163
- }
1164
-
1165
- //! Removes last child of the node.
1166
- //! If node has no children, behaviour is undefined.
1167
- //! Use first_node() to test if node has children.
1168
- void remove_last_node()
1169
- {
1170
- assert(first_node());
1171
- xml_node<Ch> *child = m_last_node;
1172
- if (child->m_prev_sibling)
1173
- {
1174
- m_last_node = child->m_prev_sibling;
1175
- child->m_prev_sibling->m_next_sibling = 0;
1176
- }
1177
- else
1178
- m_first_node = 0;
1179
- child->m_parent = 0;
1180
- }
1181
-
1182
- //! Removes specified child from the node
1183
- // \param where Pointer to child to be removed.
1184
- void remove_node(xml_node<Ch> *where)
1185
- {
1186
- assert(where && where->parent() == this);
1187
- assert(first_node());
1188
- if (where == m_first_node)
1189
- remove_first_node();
1190
- else if (where == m_last_node)
1191
- remove_last_node();
1192
- else
1193
- {
1194
- where->m_prev_sibling->m_next_sibling = where->m_next_sibling;
1195
- where->m_next_sibling->m_prev_sibling = where->m_prev_sibling;
1196
- where->m_parent = 0;
1197
- }
1198
- }
1199
-
1200
- //! Removes all child nodes (but not attributes).
1201
- void remove_all_nodes()
1202
- {
1203
- for (xml_node<Ch> *node = first_node(); node; node = node->m_next_sibling)
1204
- node->m_parent = 0;
1205
- m_first_node = 0;
1206
- }
1207
-
1208
- //! Prepends a new attribute to the node.
1209
- //! \param attribute Attribute to prepend.
1210
- void prepend_attribute(xml_attribute<Ch> *attribute)
1211
- {
1212
- assert(attribute && !attribute->parent());
1213
- if (first_attribute())
1214
- {
1215
- attribute->m_next_attribute = m_first_attribute;
1216
- m_first_attribute->m_prev_attribute = attribute;
1217
- }
1218
- else
1219
- {
1220
- attribute->m_next_attribute = 0;
1221
- m_last_attribute = attribute;
1222
- }
1223
- m_first_attribute = attribute;
1224
- attribute->m_parent = this;
1225
- attribute->m_prev_attribute = 0;
1226
- }
1227
-
1228
- //! Appends a new attribute to the node.
1229
- //! \param attribute Attribute to append.
1230
- void append_attribute(xml_attribute<Ch> *attribute)
1231
- {
1232
- assert(attribute && !attribute->parent());
1233
- if (first_attribute())
1234
- {
1235
- attribute->m_prev_attribute = m_last_attribute;
1236
- m_last_attribute->m_next_attribute = attribute;
1237
- }
1238
- else
1239
- {
1240
- attribute->m_prev_attribute = 0;
1241
- m_first_attribute = attribute;
1242
- }
1243
- m_last_attribute = attribute;
1244
- attribute->m_parent = this;
1245
- attribute->m_next_attribute = 0;
1246
- }
1247
-
1248
- //! Inserts a new attribute at specified place inside the node.
1249
- //! All attributes after and including the specified attribute are moved one position back.
1250
- //! \param where Place where to insert the attribute, or 0 to insert at the back.
1251
- //! \param attribute Attribute to insert.
1252
- void insert_attribute(xml_attribute<Ch> *where, xml_attribute<Ch> *attribute)
1253
- {
1254
- assert(!where || where->parent() == this);
1255
- assert(attribute && !attribute->parent());
1256
- if (where == m_first_attribute)
1257
- prepend_attribute(attribute);
1258
- else if (where == 0)
1259
- append_attribute(attribute);
1260
- else
1261
- {
1262
- attribute->m_prev_attribute = where->m_prev_attribute;
1263
- attribute->m_next_attribute = where;
1264
- where->m_prev_attribute->m_next_attribute = attribute;
1265
- where->m_prev_attribute = attribute;
1266
- attribute->m_parent = this;
1267
- }
1268
- }
1269
-
1270
- //! Removes first attribute of the node.
1271
- //! If node has no attributes, behaviour is undefined.
1272
- //! Use first_attribute() to test if node has attributes.
1273
- void remove_first_attribute()
1274
- {
1275
- assert(first_attribute());
1276
- xml_attribute<Ch> *attribute = m_first_attribute;
1277
- if (attribute->m_next_attribute)
1278
- {
1279
- attribute->m_next_attribute->m_prev_attribute = 0;
1280
- }
1281
- else
1282
- m_last_attribute = 0;
1283
- attribute->m_parent = 0;
1284
- m_first_attribute = attribute->m_next_attribute;
1285
- }
1286
-
1287
- //! Removes last attribute of the node.
1288
- //! If node has no attributes, behaviour is undefined.
1289
- //! Use first_attribute() to test if node has attributes.
1290
- void remove_last_attribute()
1291
- {
1292
- assert(first_attribute());
1293
- xml_attribute<Ch> *attribute = m_last_attribute;
1294
- if (attribute->m_prev_attribute)
1295
- {
1296
- attribute->m_prev_attribute->m_next_attribute = 0;
1297
- m_last_attribute = attribute->m_prev_attribute;
1298
- }
1299
- else
1300
- m_first_attribute = 0;
1301
- attribute->m_parent = 0;
1302
- }
1303
-
1304
- //! Removes specified attribute from node.
1305
- //! \param where Pointer to attribute to be removed.
1306
- void remove_attribute(xml_attribute<Ch> *where)
1307
- {
1308
- assert(first_attribute() && where->parent() == this);
1309
- if (where == m_first_attribute)
1310
- remove_first_attribute();
1311
- else if (where == m_last_attribute)
1312
- remove_last_attribute();
1313
- else
1314
- {
1315
- where->m_prev_attribute->m_next_attribute = where->m_next_attribute;
1316
- where->m_next_attribute->m_prev_attribute = where->m_prev_attribute;
1317
- where->m_parent = 0;
1318
- }
1319
- }
1320
-
1321
- //! Removes all attributes of node.
1322
- void remove_all_attributes()
1323
- {
1324
- for (xml_attribute<Ch> *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute)
1325
- attribute->m_parent = 0;
1326
- m_first_attribute = 0;
1327
- }
1328
-
1329
- private:
1330
-
1331
- ///////////////////////////////////////////////////////////////////////////
1332
- // Restrictions
1333
-
1334
- // No copying
1335
- xml_node(const xml_node &);
1336
- void operator =(const xml_node &);
1337
-
1338
- ///////////////////////////////////////////////////////////////////////////
1339
- // Data members
1340
-
1341
- // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0.
1342
- // This is required for maximum performance, as it allows the parser to omit initialization of
1343
- // unneded/redundant values.
1344
- //
1345
- // The rules are as follows:
1346
- // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively
1347
- // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage
1348
- // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage
1349
-
1350
- node_type m_type; // Type of node; always valid
1351
- xml_node<Ch> *m_first_node; // Pointer to first child node, or 0 if none; always valid
1352
- xml_node<Ch> *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero
1353
- xml_attribute<Ch> *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid
1354
- xml_attribute<Ch> *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero
1355
- xml_node<Ch> *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
1356
- xml_node<Ch> *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
1357
-
1358
- };
1359
-
1360
- ///////////////////////////////////////////////////////////////////////////
1361
- // XML document
1362
-
1363
- //! This class represents root of the DOM hierarchy.
1364
- //! It is also an xml_node and a memory_pool through public inheritance.
1365
- //! Use parse() function to build a DOM tree from a zero-terminated XML text string.
1366
- //! parse() function allocates memory for nodes and attributes by using functions of xml_document,
1367
- //! which are inherited from memory_pool.
1368
- //! To access root node of the document, use the document itself, as if it was an xml_node.
1369
- //! \tparam Ch Character type to use.
1370
- template<class Ch = char>
1371
- class xml_document: public xml_node<Ch>, public memory_pool<Ch>
1372
- {
1373
-
1374
- public:
1375
-
1376
- //! Constructs empty XML document
1377
- xml_document()
1378
- : xml_node<Ch>(node_document)
1379
- {
1380
- }
1381
-
1382
- //! Parses zero-terminated XML string according to given flags.
1383
- //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used.
1384
- //! The string must persist for the lifetime of the document.
1385
- //! In case of error, rapidxml::parse_error exception will be thrown.
1386
- //! <br><br>
1387
- //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning.
1388
- //! Make sure that data is zero-terminated.
1389
- //! <br><br>
1390
- //! Document can be parsed into multiple times.
1391
- //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.
1392
- //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.
1393
- template<int Flags>
1394
- void parse(Ch *text)
1395
- {
1396
- assert(text);
1397
-
1398
- // Remove current contents
1399
- this->remove_all_nodes();
1400
- this->remove_all_attributes();
1401
-
1402
- // Parse BOM, if any
1403
- parse_bom<Flags>(text);
1404
-
1405
- // Parse children
1406
- while (1)
1407
- {
1408
- // Skip whitespace before node
1409
- skip<whitespace_pred, Flags>(text);
1410
- if (*text == 0)
1411
- break;
1412
-
1413
- // Parse and append new child
1414
- if (*text == Ch('<'))
1415
- {
1416
- ++text; // Skip '<'
1417
- if (xml_node<Ch> *node = parse_node<Flags>(text))
1418
- this->append_node(node);
1419
- }
1420
- else
1421
- CEREAL_RAPIDXML_PARSE_ERROR("expected <", text);
1422
- }
1423
-
1424
- }
1425
-
1426
- //! Clears the document by deleting all nodes and clearing the memory pool.
1427
- //! All nodes owned by document pool are destroyed.
1428
- void clear()
1429
- {
1430
- this->remove_all_nodes();
1431
- this->remove_all_attributes();
1432
- memory_pool<Ch>::clear();
1433
- }
1434
-
1435
- private:
1436
-
1437
- ///////////////////////////////////////////////////////////////////////
1438
- // Internal character utility functions
1439
-
1440
- // Detect whitespace character
1441
- struct whitespace_pred
1442
- {
1443
- static unsigned char test(Ch ch)
1444
- {
1445
- return internal::lookup_tables<0>::lookup_whitespace[static_cast<unsigned char>(ch)];
1446
- }
1447
- };
1448
-
1449
- // Detect node name character
1450
- struct node_name_pred
1451
- {
1452
- static unsigned char test(Ch ch)
1453
- {
1454
- return internal::lookup_tables<0>::lookup_node_name[static_cast<unsigned char>(ch)];
1455
- }
1456
- };
1457
-
1458
- // Detect attribute name character
1459
- struct attribute_name_pred
1460
- {
1461
- static unsigned char test(Ch ch)
1462
- {
1463
- return internal::lookup_tables<0>::lookup_attribute_name[static_cast<unsigned char>(ch)];
1464
- }
1465
- };
1466
-
1467
- // Detect text character (PCDATA)
1468
- struct text_pred
1469
- {
1470
- static unsigned char test(Ch ch)
1471
- {
1472
- return internal::lookup_tables<0>::lookup_text[static_cast<unsigned char>(ch)];
1473
- }
1474
- };
1475
-
1476
- // Detect text character (PCDATA) that does not require processing
1477
- struct text_pure_no_ws_pred
1478
- {
1479
- static unsigned char test(Ch ch)
1480
- {
1481
- return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast<unsigned char>(ch)];
1482
- }
1483
- };
1484
-
1485
- // Detect text character (PCDATA) that does not require processing
1486
- struct text_pure_with_ws_pred
1487
- {
1488
- static unsigned char test(Ch ch)
1489
- {
1490
- return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast<unsigned char>(ch)];
1491
- }
1492
- };
1493
-
1494
- // Detect attribute value character
1495
- template<Ch Quote>
1496
- struct attribute_value_pred
1497
- {
1498
- static unsigned char test(Ch ch)
1499
- {
1500
- if (Quote == Ch('\''))
1501
- return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast<unsigned char>(ch)];
1502
- if (Quote == Ch('\"'))
1503
- return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast<unsigned char>(ch)];
1504
- return 0; // Should never be executed, to avoid warnings on Comeau
1505
- }
1506
- };
1507
-
1508
- // Detect attribute value character
1509
- template<Ch Quote>
1510
- struct attribute_value_pure_pred
1511
- {
1512
- static unsigned char test(Ch ch)
1513
- {
1514
- if (Quote == Ch('\''))
1515
- return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast<unsigned char>(ch)];
1516
- if (Quote == Ch('\"'))
1517
- return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast<unsigned char>(ch)];
1518
- return 0; // Should never be executed, to avoid warnings on Comeau
1519
- }
1520
- };
1521
-
1522
- // Insert coded character, using UTF8 or 8-bit ASCII
1523
- template<int Flags>
1524
- static void insert_coded_character(Ch *&text, unsigned long code)
1525
- {
1526
- if (Flags & parse_no_utf8)
1527
- {
1528
- // Insert 8-bit ASCII character
1529
- // Todo: possibly verify that code is less than 256 and use replacement char otherwise?
1530
- text[0] = static_cast<Ch>(code);
1531
- text += 1;
1532
- }
1533
- else
1534
- {
1535
- // Insert UTF8 sequence
1536
- if (code < 0x80) // 1 byte sequence
1537
- {
1538
- text[0] = static_cast<Ch>(code);
1539
- text += 1;
1540
- }
1541
- else if (code < 0x800) // 2 byte sequence
1542
- {
1543
- text[1] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6;
1544
- text[0] = static_cast<Ch>(code | 0xC0);
1545
- text += 2;
1546
- }
1547
- else if (code < 0x10000) // 3 byte sequence
1548
- {
1549
- text[2] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6;
1550
- text[1] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6;
1551
- text[0] = static_cast<Ch>(code | 0xE0);
1552
- text += 3;
1553
- }
1554
- else if (code < 0x110000) // 4 byte sequence
1555
- {
1556
- text[3] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6;
1557
- text[2] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6;
1558
- text[1] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6;
1559
- text[0] = static_cast<Ch>(code | 0xF0);
1560
- text += 4;
1561
- }
1562
- else // Invalid, only codes up to 0x10FFFF are allowed in Unicode
1563
- {
1564
- CEREAL_RAPIDXML_PARSE_ERROR("invalid numeric character entity", text);
1565
- }
1566
- }
1567
- }
1568
-
1569
- // Skip characters until predicate evaluates to true
1570
- template<class StopPred, int Flags>
1571
- static void skip(Ch *&text)
1572
- {
1573
- Ch *tmp = text;
1574
- while (StopPred::test(*tmp))
1575
- ++tmp;
1576
- text = tmp;
1577
- }
1578
-
1579
- // Skip characters until predicate evaluates to true while doing the following:
1580
- // - replacing XML character entity references with proper characters (&apos; &amp; &quot; &lt; &gt; &#...;)
1581
- // - condensing whitespace sequences to single space character
1582
- template<class StopPred, class StopPredPure, int Flags>
1583
- static Ch *skip_and_expand_character_refs(Ch *&text, bool preserve_space)
1584
- {
1585
- // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip
1586
- if (Flags & parse_no_entity_translation &&
1587
- !(Flags & parse_normalize_whitespace) &&
1588
- !(Flags & parse_trim_whitespace))
1589
- {
1590
- skip<StopPred, Flags>(text);
1591
- return text;
1592
- }
1593
-
1594
- // Use simple skip until first modification is detected
1595
- skip<StopPredPure, Flags>(text);
1596
-
1597
- // Use translation skip
1598
- Ch *src = text;
1599
- Ch *dest = src;
1600
- while (StopPred::test(*src))
1601
- {
1602
- // If entity translation is enabled
1603
- if (!(Flags & parse_no_entity_translation))
1604
- {
1605
- // Test if replacement is needed
1606
- if (src[0] == Ch('&'))
1607
- {
1608
- switch (src[1])
1609
- {
1610
-
1611
- // &amp; &apos;
1612
- case Ch('a'):
1613
- if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';'))
1614
- {
1615
- *dest = Ch('&');
1616
- ++dest;
1617
- src += 5;
1618
- continue;
1619
- }
1620
- if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';'))
1621
- {
1622
- *dest = Ch('\'');
1623
- ++dest;
1624
- src += 6;
1625
- continue;
1626
- }
1627
- break;
1628
-
1629
- // &quot;
1630
- case Ch('q'):
1631
- if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';'))
1632
- {
1633
- *dest = Ch('"');
1634
- ++dest;
1635
- src += 6;
1636
- continue;
1637
- }
1638
- break;
1639
-
1640
- // &gt;
1641
- case Ch('g'):
1642
- if (src[2] == Ch('t') && src[3] == Ch(';'))
1643
- {
1644
- *dest = Ch('>');
1645
- ++dest;
1646
- src += 4;
1647
- continue;
1648
- }
1649
- break;
1650
-
1651
- // &lt;
1652
- case Ch('l'):
1653
- if (src[2] == Ch('t') && src[3] == Ch(';'))
1654
- {
1655
- *dest = Ch('<');
1656
- ++dest;
1657
- src += 4;
1658
- continue;
1659
- }
1660
- break;
1661
-
1662
- // &#...; - assumes ASCII
1663
- case Ch('#'):
1664
- if (src[2] == Ch('x'))
1665
- {
1666
- unsigned long code = 0;
1667
- src += 3; // Skip &#x
1668
- while (1)
1669
- {
1670
- unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
1671
- if (digit == 0xFF)
1672
- break;
1673
- code = code * 16 + digit;
1674
- ++src;
1675
- }
1676
- insert_coded_character<Flags>(dest, code); // Put character in output
1677
- }
1678
- else
1679
- {
1680
- unsigned long code = 0;
1681
- src += 2; // Skip &#
1682
- while (1)
1683
- {
1684
- unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
1685
- if (digit == 0xFF)
1686
- break;
1687
- code = code * 10 + digit;
1688
- ++src;
1689
- }
1690
- insert_coded_character<Flags>(dest, code); // Put character in output
1691
- }
1692
- if (*src == Ch(';'))
1693
- ++src;
1694
- else
1695
- CEREAL_RAPIDXML_PARSE_ERROR("expected ;", src);
1696
- continue;
1697
-
1698
- // Something else
1699
- default:
1700
- // Ignore, just copy '&' verbatim
1701
- break;
1702
-
1703
- }
1704
- }
1705
- }
1706
-
1707
- // If whitespace condensing is enabled
1708
- if ((Flags & parse_normalize_whitespace) && !preserve_space)
1709
- {
1710
- // Test if condensing is needed
1711
- if (whitespace_pred::test(*src))
1712
- {
1713
- *dest = Ch(' '); ++dest; // Put single space in dest
1714
- ++src; // Skip first whitespace char
1715
- // Skip remaining whitespace chars
1716
- while (whitespace_pred::test(*src))
1717
- ++src;
1718
- continue;
1719
- }
1720
- }
1721
-
1722
- // No replacement, only copy character
1723
- *dest++ = *src++;
1724
-
1725
- }
1726
-
1727
- // Return new end
1728
- text = src;
1729
- return dest;
1730
-
1731
- }
1732
-
1733
- ///////////////////////////////////////////////////////////////////////
1734
- // Internal parsing functions
1735
-
1736
- // Parse BOM, if any
1737
- template<int Flags>
1738
- void parse_bom(Ch *&text)
1739
- {
1740
- // UTF-8?
1741
- if (static_cast<unsigned char>(text[0]) == 0xEF &&
1742
- static_cast<unsigned char>(text[1]) == 0xBB &&
1743
- static_cast<unsigned char>(text[2]) == 0xBF)
1744
- {
1745
- text += 3; // Skup utf-8 bom
1746
- }
1747
- }
1748
-
1749
- // Parse XML declaration (<?xml...)
1750
- template<int Flags>
1751
- xml_node<Ch> *parse_xml_declaration(Ch *&text)
1752
- {
1753
- // If parsing of declaration is disabled
1754
- if (!(Flags & parse_declaration_node))
1755
- {
1756
- // Skip until end of declaration
1757
- while (text[0] != Ch('?') || text[1] != Ch('>'))
1758
- {
1759
- if (!text[0])
1760
- CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
1761
- ++text;
1762
- }
1763
- text += 2; // Skip '?>'
1764
- return 0;
1765
- }
1766
-
1767
- // Create declaration
1768
- xml_node<Ch> *declaration = this->allocate_node(node_declaration);
1769
-
1770
- // Skip whitespace before attributes or ?>
1771
- skip<whitespace_pred, Flags>(text);
1772
-
1773
- // Parse declaration attributes
1774
- parse_node_attributes<Flags>(text, declaration);
1775
-
1776
- // Skip ?>
1777
- if (text[0] != Ch('?') || text[1] != Ch('>'))
1778
- CEREAL_RAPIDXML_PARSE_ERROR("expected ?>", text);
1779
- text += 2;
1780
-
1781
- return declaration;
1782
- }
1783
-
1784
- // Parse XML comment (<!--...)
1785
- template<int Flags>
1786
- xml_node<Ch> *parse_comment(Ch *&text)
1787
- {
1788
- // If parsing of comments is disabled
1789
- if (!(Flags & parse_comment_nodes))
1790
- {
1791
- // Skip until end of comment
1792
- while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
1793
- {
1794
- if (!text[0])
1795
- CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
1796
- ++text;
1797
- }
1798
- text += 3; // Skip '-->'
1799
- return 0; // Do not produce comment node
1800
- }
1801
-
1802
- // Remember value start
1803
- Ch *value_ = text;
1804
-
1805
- // Skip until end of comment
1806
- while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
1807
- {
1808
- if (!text[0])
1809
- CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
1810
- ++text;
1811
- }
1812
-
1813
- // Create comment node
1814
- xml_node<Ch> *comment = this->allocate_node(node_comment);
1815
- comment->value(value_, static_cast<std::size_t>(text - value_));
1816
-
1817
- // Place zero terminator after comment value
1818
- if (!(Flags & parse_no_string_terminators))
1819
- *text = Ch('\0');
1820
-
1821
- text += 3; // Skip '-->'
1822
- return comment;
1823
- }
1824
-
1825
- // Parse DOCTYPE
1826
- template<int Flags>
1827
- xml_node<Ch> *parse_doctype(Ch *&text)
1828
- {
1829
- // Remember value start
1830
- Ch *value_ = text;
1831
-
1832
- // Skip to >
1833
- while (*text != Ch('>'))
1834
- {
1835
- // Determine character type
1836
- switch (*text)
1837
- {
1838
-
1839
- // If '[' encountered, scan for matching ending ']' using naive algorithm with depth
1840
- // This works for all W3C test files except for 2 most wicked
1841
- case Ch('['):
1842
- {
1843
- ++text; // Skip '['
1844
- int depth = 1;
1845
- while (depth > 0)
1846
- {
1847
- switch (*text)
1848
- {
1849
- case Ch('['): ++depth; break;
1850
- case Ch(']'): --depth; break;
1851
- case 0: CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
1852
- }
1853
- ++text;
1854
- }
1855
- break;
1856
- }
1857
-
1858
- // Error on end of text
1859
- case Ch('\0'):
1860
- CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
1861
-
1862
- // Other character, skip it
1863
- default:
1864
- ++text;
1865
-
1866
- }
1867
- }
1868
-
1869
- // If DOCTYPE nodes enabled
1870
- if (Flags & parse_doctype_node)
1871
- {
1872
- // Create a new doctype node
1873
- xml_node<Ch> *doctype = this->allocate_node(node_doctype);
1874
- doctype->value(value_, static_cast<std::size_t>(text - value_));
1875
-
1876
- // Place zero terminator after value
1877
- if (!(Flags & parse_no_string_terminators))
1878
- *text = Ch('\0');
1879
-
1880
- text += 1; // skip '>'
1881
- return doctype;
1882
- }
1883
- else
1884
- {
1885
- text += 1; // skip '>'
1886
- return 0;
1887
- }
1888
-
1889
- }
1890
-
1891
- // Parse PI
1892
- template<int Flags>
1893
- xml_node<Ch> *parse_pi(Ch *&text)
1894
- {
1895
- // If creation of PI nodes is enabled
1896
- if (Flags & parse_pi_nodes)
1897
- {
1898
- // Create pi node
1899
- xml_node<Ch> *pi = this->allocate_node(node_pi);
1900
-
1901
- // Extract PI target name
1902
- Ch *name_ = text;
1903
- skip<node_name_pred, Flags>(text);
1904
- if (text == name_)
1905
- CEREAL_RAPIDXML_PARSE_ERROR("expected PI target", text);
1906
- pi->name(name_, static_cast<std::size_t>(text - name_));
1907
-
1908
- // Skip whitespace between pi target and pi
1909
- skip<whitespace_pred, Flags>(text);
1910
-
1911
- // Remember start of pi
1912
- Ch *value_ = text;
1913
-
1914
- // Skip to '?>'
1915
- while (text[0] != Ch('?') || text[1] != Ch('>'))
1916
- {
1917
- if (*text == Ch('\0'))
1918
- CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
1919
- ++text;
1920
- }
1921
-
1922
- // Set pi value (verbatim, no entity expansion or whitespace normalization)
1923
- pi->value(value_, static_cast<std::size_t>(text - value_));
1924
-
1925
- // Place zero terminator after name and value
1926
- if (!(Flags & parse_no_string_terminators))
1927
- {
1928
- pi->name()[pi->name_size()] = Ch('\0');
1929
- pi->value()[pi->value_size()] = Ch('\0');
1930
- }
1931
-
1932
- text += 2; // Skip '?>'
1933
- return pi;
1934
- }
1935
- else
1936
- {
1937
- // Skip to '?>'
1938
- while (text[0] != Ch('?') || text[1] != Ch('>'))
1939
- {
1940
- if (*text == Ch('\0'))
1941
- CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
1942
- ++text;
1943
- }
1944
- text += 2; // Skip '?>'
1945
- return 0;
1946
- }
1947
- }
1948
-
1949
- // Parse and append data
1950
- // Return character that ends data.
1951
- // This is necessary because this character might have been overwritten by a terminating 0
1952
- template<int Flags>
1953
- Ch parse_and_append_data(xml_node<Ch> *node, Ch *&text, Ch *contents_start)
1954
- {
1955
- // Backup to contents start if whitespace trimming is disabled
1956
- if (!(Flags & parse_trim_whitespace))
1957
- text = contents_start;
1958
-
1959
- const bool preserve_space = internal::preserve_space(node);
1960
-
1961
- // Skip until end of data
1962
- Ch *value_ = text, *end;
1963
- if ((Flags & parse_normalize_whitespace) && !preserve_space)
1964
- end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text, false);
1965
- else
1966
- end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text, preserve_space);
1967
-
1968
- // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after >
1969
- if ((Flags & parse_trim_whitespace) && !preserve_space)
1970
- {
1971
- if (Flags & parse_normalize_whitespace)
1972
- {
1973
- // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end
1974
- if (*(end - 1) == Ch(' '))
1975
- --end;
1976
- }
1977
- else
1978
- {
1979
- // Backup until non-whitespace character is found
1980
- while (whitespace_pred::test(*(end - 1)))
1981
- --end;
1982
- }
1983
- }
1984
-
1985
- // If characters are still left between end and value (this test is only necessary if normalization is enabled)
1986
- // Create new data node
1987
- if (!(Flags & parse_no_data_nodes))
1988
- {
1989
- xml_node<Ch> *data = this->allocate_node(node_data);
1990
- data->value(value_, static_cast<std::size_t>(end - value_));
1991
- node->append_node(data);
1992
- }
1993
-
1994
- // Add data to parent node if no data exists yet
1995
- if (!(Flags & parse_no_element_values))
1996
- if (*node->value() == Ch('\0'))
1997
- node->value(value_, static_cast<std::size_t>(end - value_));
1998
-
1999
- // Place zero terminator after value
2000
- if (!(Flags & parse_no_string_terminators))
2001
- {
2002
- Ch ch = *text;
2003
- *end = Ch('\0');
2004
- return ch; // Return character that ends data; this is required because zero terminator overwritten it
2005
- }
2006
-
2007
- // Return character that ends data
2008
- return *text;
2009
- }
2010
-
2011
- // Parse CDATA
2012
- template<int Flags>
2013
- xml_node<Ch> *parse_cdata(Ch *&text)
2014
- {
2015
- // If CDATA is disabled
2016
- if (Flags & parse_no_data_nodes)
2017
- {
2018
- // Skip until end of cdata
2019
- while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
2020
- {
2021
- if (!text[0])
2022
- CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
2023
- ++text;
2024
- }
2025
- text += 3; // Skip ]]>
2026
- return 0; // Do not produce CDATA node
2027
- }
2028
-
2029
- // Skip until end of cdata
2030
- Ch *value_ = text;
2031
- while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
2032
- {
2033
- if (!text[0])
2034
- CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
2035
- ++text;
2036
- }
2037
-
2038
- // Create new cdata node
2039
- xml_node<Ch> *cdata = this->allocate_node(node_cdata);
2040
- cdata->value(value_, static_cast<std::size_t>(text - value_));
2041
-
2042
- // Place zero terminator after value
2043
- if (!(Flags & parse_no_string_terminators))
2044
- *text = Ch('\0');
2045
-
2046
- text += 3; // Skip ]]>
2047
- return cdata;
2048
- }
2049
-
2050
- // Parse element node
2051
- template<int Flags>
2052
- xml_node<Ch> *parse_element(Ch *&text)
2053
- {
2054
- // Create element node
2055
- xml_node<Ch> *element = this->allocate_node(node_element);
2056
-
2057
- // Extract element name
2058
- Ch *name_ = text;
2059
- skip<node_name_pred, Flags>(text);
2060
- if (text == name_)
2061
- CEREAL_RAPIDXML_PARSE_ERROR("expected element name", text);
2062
- element->name(name_, static_cast<std::size_t>(text - name_));
2063
-
2064
- // Skip whitespace between element name and attributes or >
2065
- skip<whitespace_pred, Flags>(text);
2066
-
2067
- // Parse attributes, if any
2068
- parse_node_attributes<Flags>(text, element);
2069
-
2070
- // Determine ending type
2071
- if (*text == Ch('>'))
2072
- {
2073
- ++text;
2074
- parse_node_contents<Flags>(text, element);
2075
- }
2076
- else if (*text == Ch('/'))
2077
- {
2078
- ++text;
2079
- if (*text != Ch('>'))
2080
- CEREAL_RAPIDXML_PARSE_ERROR("expected >", text);
2081
- ++text;
2082
- }
2083
- else
2084
- CEREAL_RAPIDXML_PARSE_ERROR("expected >", text);
2085
-
2086
- // Place zero terminator after name
2087
- if (!(Flags & parse_no_string_terminators))
2088
- element->name()[element->name_size()] = Ch('\0');
2089
-
2090
- // Return parsed element
2091
- return element;
2092
- }
2093
-
2094
- // Determine node type, and parse it
2095
- template<int Flags>
2096
- xml_node<Ch> *parse_node(Ch *&text)
2097
- {
2098
- // Parse proper node type
2099
- switch (text[0])
2100
- {
2101
-
2102
- // <...
2103
- default:
2104
- // Parse and append element node
2105
- return parse_element<Flags>(text);
2106
-
2107
- // <?...
2108
- case Ch('?'):
2109
- ++text; // Skip ?
2110
- if ((text[0] == Ch('x') || text[0] == Ch('X')) &&
2111
- (text[1] == Ch('m') || text[1] == Ch('M')) &&
2112
- (text[2] == Ch('l') || text[2] == Ch('L')) &&
2113
- whitespace_pred::test(text[3]))
2114
- {
2115
- // '<?xml ' - xml declaration
2116
- text += 4; // Skip 'xml '
2117
- return parse_xml_declaration<Flags>(text);
2118
- }
2119
- else
2120
- {
2121
- // Parse PI
2122
- return parse_pi<Flags>(text);
2123
- }
2124
-
2125
- // <!...
2126
- case Ch('!'):
2127
-
2128
- // Parse proper subset of <! node
2129
- switch (text[1])
2130
- {
2131
-
2132
- // <!-
2133
- case Ch('-'):
2134
- if (text[2] == Ch('-'))
2135
- {
2136
- // '<!--' - xml comment
2137
- text += 3; // Skip '!--'
2138
- return parse_comment<Flags>(text);
2139
- }
2140
- break;
2141
-
2142
- // <![
2143
- case Ch('['):
2144
- if (text[2] == Ch('C') && text[3] == Ch('D') && text[4] == Ch('A') &&
2145
- text[5] == Ch('T') && text[6] == Ch('A') && text[7] == Ch('['))
2146
- {
2147
- // '<![CDATA[' - cdata
2148
- text += 8; // Skip '![CDATA['
2149
- return parse_cdata<Flags>(text);
2150
- }
2151
- break;
2152
-
2153
- // <!D
2154
- case Ch('D'):
2155
- if (text[2] == Ch('O') && text[3] == Ch('C') && text[4] == Ch('T') &&
2156
- text[5] == Ch('Y') && text[6] == Ch('P') && text[7] == Ch('E') &&
2157
- whitespace_pred::test(text[8]))
2158
- {
2159
- // '<!DOCTYPE ' - doctype
2160
- text += 9; // skip '!DOCTYPE '
2161
- return parse_doctype<Flags>(text);
2162
- }
2163
-
2164
- } // switch
2165
-
2166
- // Attempt to skip other, unrecognized node types starting with <!
2167
- ++text; // Skip !
2168
- while (*text != Ch('>'))
2169
- {
2170
- if (*text == 0)
2171
- CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
2172
- ++text;
2173
- }
2174
- ++text; // Skip '>'
2175
- return 0; // No node recognized
2176
-
2177
- }
2178
- }
2179
-
2180
- // Parse contents of the node - children, data etc.
2181
- template<int Flags>
2182
- void parse_node_contents(Ch *&text, xml_node<Ch> *node)
2183
- {
2184
- // For all children and text
2185
- while (1)
2186
- {
2187
- // Skip whitespace between > and node contents
2188
- Ch *contents_start = text; // Store start of node contents before whitespace is skipped
2189
- skip<whitespace_pred, Flags>(text);
2190
- Ch next_char = *text;
2191
-
2192
- // After data nodes, instead of continuing the loop, control jumps here.
2193
- // This is because zero termination inside parse_and_append_data() function
2194
- // would wreak havoc with the above code.
2195
- // Also, skipping whitespace after data nodes is unnecessary.
2196
- after_data_node:
2197
-
2198
- // Determine what comes next: node closing, child node, data node, or 0?
2199
- switch (next_char)
2200
- {
2201
-
2202
- // Node closing or child node
2203
- case Ch('<'):
2204
- if (text[1] == Ch('/'))
2205
- {
2206
- Ch *contents_end = 0;
2207
- if (internal::preserve_space(node))
2208
- {
2209
- contents_end = text;
2210
- }
2211
-
2212
- // Node closing
2213
- text += 2; // Skip '</'
2214
- if (Flags & parse_validate_closing_tags)
2215
- {
2216
- // Skip and validate closing tag name
2217
- Ch *closing_name = text;
2218
- skip<node_name_pred, Flags>(text);
2219
- if (!internal::compare(node->name(), node->name_size(), closing_name, static_cast<std::size_t>(text - closing_name), true))
2220
- CEREAL_RAPIDXML_PARSE_ERROR("invalid closing tag name", text);
2221
- }
2222
- else
2223
- {
2224
- // No validation, just skip name
2225
- skip<node_name_pred, Flags>(text);
2226
- }
2227
- // Skip remaining whitespace after node name
2228
- skip<whitespace_pred, Flags>(text);
2229
- if (*text != Ch('>'))
2230
- CEREAL_RAPIDXML_PARSE_ERROR("expected >", text);
2231
- ++text; // Skip '>'
2232
-
2233
- if (contents_end && contents_end != contents_start)
2234
- {
2235
- node->value(contents_start, static_cast<std::size_t>(contents_end - contents_start));
2236
- node->value()[node->value_size()] = Ch('\0');
2237
- }
2238
- return; // Node closed, finished parsing contents
2239
- }
2240
- else
2241
- {
2242
- // Child node
2243
- ++text; // Skip '<'
2244
- if (xml_node<Ch> *child = parse_node<Flags>(text))
2245
- node->append_node(child);
2246
- }
2247
- break;
2248
-
2249
- // End of data - error
2250
- case Ch('\0'):
2251
- CEREAL_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
2252
-
2253
- // Data node
2254
- default:
2255
- next_char = parse_and_append_data<Flags>(node, text, contents_start);
2256
- goto after_data_node; // Bypass regular processing after data nodes
2257
-
2258
- }
2259
- }
2260
- }
2261
-
2262
- // Parse XML attributes of the node
2263
- template<int Flags>
2264
- void parse_node_attributes(Ch *&text, xml_node<Ch> *node)
2265
- {
2266
- // For all attributes
2267
- while (attribute_name_pred::test(*text))
2268
- {
2269
- // Extract attribute name
2270
- Ch *name_ = text;
2271
- ++text; // Skip first character of attribute name
2272
- skip<attribute_name_pred, Flags>(text);
2273
- if (text == name_)
2274
- CEREAL_RAPIDXML_PARSE_ERROR("expected attribute name", name_);
2275
-
2276
- // Create new attribute
2277
- xml_attribute<Ch> *attribute = this->allocate_attribute();
2278
- attribute->name(name_, static_cast<std::size_t>(text - name_));
2279
- node->append_attribute(attribute);
2280
-
2281
- // Skip whitespace after attribute name
2282
- skip<whitespace_pred, Flags>(text);
2283
-
2284
- // Skip =
2285
- if (*text != Ch('='))
2286
- CEREAL_RAPIDXML_PARSE_ERROR("expected =", text);
2287
- ++text;
2288
-
2289
- // Add terminating zero after name
2290
- if (!(Flags & parse_no_string_terminators))
2291
- attribute->name()[attribute->name_size()] = 0;
2292
-
2293
- // Skip whitespace after =
2294
- skip<whitespace_pred, Flags>(text);
2295
-
2296
- // Skip quote and remember if it was ' or "
2297
- Ch quote = *text;
2298
- if (quote != Ch('\'') && quote != Ch('"'))
2299
- CEREAL_RAPIDXML_PARSE_ERROR("expected ' or \"", text);
2300
- ++text;
2301
-
2302
- // Extract attribute value and expand char refs in it
2303
- Ch *value_ = text, *end;
2304
- const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes
2305
- if (quote == Ch('\''))
2306
- end = skip_and_expand_character_refs<attribute_value_pred<Ch('\'')>, attribute_value_pure_pred<Ch('\'')>, AttFlags>(text, false);
2307
- else
2308
- end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text, false);
2309
-
2310
- // Set attribute value
2311
- attribute->value(value_, static_cast<std::size_t>(end - value_));
2312
-
2313
- // Make sure that end quote is present
2314
- if (*text != quote)
2315
- CEREAL_RAPIDXML_PARSE_ERROR("expected ' or \"", text);
2316
- ++text; // Skip quote
2317
-
2318
- // Add terminating zero after value
2319
- if (!(Flags & parse_no_string_terminators))
2320
- attribute->value()[attribute->value_size()] = 0;
2321
-
2322
- // Skip whitespace after attribute value
2323
- skip<whitespace_pred, Flags>(text);
2324
- }
2325
- }
2326
-
2327
- };
2328
-
2329
- //! \cond internal
2330
- namespace internal
2331
- {
2332
-
2333
- // Whitespace (space \n \r \t)
2334
- template<int Dummy>
2335
- const unsigned char lookup_tables<Dummy>::lookup_whitespace[256] =
2336
- {
2337
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
2338
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0
2339
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
2340
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
2341
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
2342
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
2343
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
2344
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
2345
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
2346
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
2347
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
2348
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
2349
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
2350
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
2351
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
2352
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
2353
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
2354
- };
2355
-
2356
- // Node name (anything but space \n \r \t / > ? \0)
2357
- template<int Dummy>
2358
- const unsigned char lookup_tables<Dummy>::lookup_node_name[256] =
2359
- {
2360
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
2361
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
2362
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
2363
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2
2364
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3
2365
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
2366
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
2367
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
2368
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
2369
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
2370
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
2371
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
2372
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
2373
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
2374
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
2375
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
2376
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
2377
- };
2378
-
2379
- // Text (i.e. PCDATA) (anything but < \0)
2380
- template<int Dummy>
2381
- const unsigned char lookup_tables<Dummy>::lookup_text[256] =
2382
- {
2383
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
2384
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
2385
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
2386
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
2387
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
2388
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
2389
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
2390
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
2391
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
2392
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
2393
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
2394
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
2395
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
2396
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
2397
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
2398
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
2399
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
2400
- };
2401
-
2402
- // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled
2403
- // (anything but < \0 &)
2404
- template<int Dummy>
2405
- const unsigned char lookup_tables<Dummy>::lookup_text_pure_no_ws[256] =
2406
- {
2407
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
2408
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
2409
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
2410
- 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
2411
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
2412
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
2413
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
2414
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
2415
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
2416
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
2417
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
2418
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
2419
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
2420
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
2421
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
2422
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
2423
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
2424
- };
2425
-
2426
- // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled
2427
- // (anything but < \0 & space \n \r \t)
2428
- template<int Dummy>
2429
- const unsigned char lookup_tables<Dummy>::lookup_text_pure_with_ws[256] =
2430
- {
2431
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
2432
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
2433
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
2434
- 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
2435
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
2436
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
2437
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
2438
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
2439
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
2440
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
2441
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
2442
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
2443
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
2444
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
2445
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
2446
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
2447
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
2448
- };
2449
-
2450
- // Attribute name (anything but space \n \r \t / < > = ? ! \0)
2451
- template<int Dummy>
2452
- const unsigned char lookup_tables<Dummy>::lookup_attribute_name[256] =
2453
- {
2454
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
2455
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
2456
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
2457
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2
2458
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3
2459
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
2460
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
2461
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
2462
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
2463
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
2464
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
2465
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
2466
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
2467
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
2468
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
2469
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
2470
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
2471
- };
2472
-
2473
- // Attribute data with single quote (anything but ' \0)
2474
- template<int Dummy>
2475
- const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1[256] =
2476
- {
2477
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
2478
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
2479
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
2480
- 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2
2481
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
2482
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
2483
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
2484
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
2485
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
2486
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
2487
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
2488
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
2489
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
2490
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
2491
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
2492
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
2493
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
2494
- };
2495
-
2496
- // Attribute data with single quote that does not require processing (anything but ' \0 &)
2497
- template<int Dummy>
2498
- const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1_pure[256] =
2499
- {
2500
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
2501
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
2502
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
2503
- 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2
2504
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
2505
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
2506
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
2507
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
2508
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
2509
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
2510
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
2511
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
2512
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
2513
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
2514
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
2515
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
2516
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
2517
- };
2518
-
2519
- // Attribute data with double quote (anything but " \0)
2520
- template<int Dummy>
2521
- const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2[256] =
2522
- {
2523
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
2524
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
2525
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
2526
- 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
2527
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
2528
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
2529
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
2530
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
2531
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
2532
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
2533
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
2534
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
2535
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
2536
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
2537
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
2538
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
2539
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
2540
- };
2541
-
2542
- // Attribute data with double quote that does not require processing (anything but " \0 &)
2543
- template<int Dummy>
2544
- const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2_pure[256] =
2545
- {
2546
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
2547
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
2548
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
2549
- 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
2550
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
2551
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
2552
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
2553
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
2554
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
2555
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
2556
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
2557
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
2558
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
2559
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
2560
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
2561
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
2562
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
2563
- };
2564
-
2565
- // Digits (dec and hex, 255 denotes end of numeric character reference)
2566
- template<int Dummy>
2567
- const unsigned char lookup_tables<Dummy>::lookup_digits[256] =
2568
- {
2569
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
2570
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 0
2571
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 1
2572
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 2
2573
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255, // 3
2574
- 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 4
2575
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 5
2576
- 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 6
2577
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 7
2578
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 8
2579
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 9
2580
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // A
2581
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // B
2582
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // C
2583
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // D
2584
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // E
2585
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 // F
2586
- };
2587
-
2588
- // Upper case conversion
2589
- template<int Dummy>
2590
- const unsigned char lookup_tables<Dummy>::lookup_upcase[256] =
2591
- {
2592
- // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F
2593
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0
2594
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1
2595
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2
2596
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3
2597
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4
2598
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5
2599
- 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 6
2600
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127, // 7
2601
- 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 8
2602
- 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, // 9
2603
- 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // A
2604
- 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // B
2605
- 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // C
2606
- 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // D
2607
- 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // E
2608
- 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // F
2609
- };
2610
- }
2611
- //! \endcond
2612
-
2613
- }
2614
- } // end namespace cereal
2615
-
2616
- // Undefine internal macros
2617
- #undef CEREAL_RAPIDXML_PARSE_ERROR
2618
-
2619
- // On MSVC, restore warnings state
2620
- #ifdef _MSC_VER
2621
- #pragma warning(pop)
2622
- #endif
2623
-
2624
- #endif