15 #ifndef SOURCE_PUGIXML_CPP
16 #define SOURCE_PUGIXML_CPP
26 #ifdef PUGIXML_WCHAR_MODE
30 #ifndef PUGIXML_NO_XPATH
33 # ifdef PUGIXML_NO_EXCEPTIONS
38 #ifndef PUGIXML_NO_STL
48 # pragma warning(push)
49 # pragma warning(disable: 4127) // conditional expression is constant
50 # pragma warning(disable: 4324) // structure was padded due to __declspec(align())
51 # pragma warning(disable: 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
52 # pragma warning(disable: 4702) // unreachable code
53 # pragma warning(disable: 4996) // this function or variable may be unsafe
54 # pragma warning(disable: 4793) // function compiled as native: presence of '_setjmp' makes a function unmanaged
57 #ifdef __INTEL_COMPILER
58 # pragma warning(disable: 177) // function was declared but never referenced
59 # pragma warning(disable: 279) // controlling expression is constant
60 # pragma warning(disable: 1478 1786) // function was declared "deprecated"
61 # pragma warning(disable: 1684) // conversion from pointer to same-sized integral type
64 #if defined(__BORLANDC__) && defined(PUGIXML_HEADER_ONLY)
65 # pragma warn -8080 // symbol is declared but never used; disabling this inside push/pop bracket does not make the warning go away
70 # pragma warn -8008 // condition is always false
71 # pragma warn -8066 // unreachable code
76 # pragma diag_suppress=178 // function was declared but never referenced
77 # pragma diag_suppress=237 // controlling expression is constant
81 #if defined(_MSC_VER) && _MSC_VER >= 1300
82 # define PUGI__NO_INLINE __declspec(noinline)
83 #elif defined(__GNUC__)
84 # define PUGI__NO_INLINE __attribute__((noinline))
86 # define PUGI__NO_INLINE
91 # define PUGI__UNLIKELY(cond) __builtin_expect(cond, 0)
93 # define PUGI__UNLIKELY(cond) (cond)
97 #define PUGI__STATIC_ASSERT(cond) { static const char condition_failed[(cond) ? 1 : -1] = {0}; (void)condition_failed[0]; }
101 # define PUGI__DMC_VOLATILE volatile
103 # define PUGI__DMC_VOLATILE
107 #if defined(__BORLANDC__) && !defined(__MEM_H_USING_LIST)
114 #if defined(PUGIXML_HAS_LONG_LONG) && defined(__MINGW32__) && defined(__STRICT_ANSI__) && !defined(LLONG_MAX) && !defined(LLONG_MIN) && !defined(ULLONG_MAX)
115 # define LLONG_MAX 9223372036854775807LL
116 # define LLONG_MIN (-LLONG_MAX-1)
117 # define ULLONG_MAX (2ULL*LLONG_MAX+1)
121 #if defined(_MSC_VER) && !defined(__S3E__)
122 # define PUGI__MSVC_CRT_VERSION _MSC_VER
125 #ifdef PUGIXML_HEADER_ONLY
126 # define PUGI__NS_BEGIN OIIO_NAMESPACE_BEGIN namespace pugi { namespace impl {
127 # define PUGI__NS_END } } OIIO_NAMESPACE_END
128 # define PUGI__FN inline
129 # define PUGI__FN_NO_INLINE inline
131 # if defined(_MSC_VER) && _MSC_VER < 1300 // MSVC6 seems to have an amusing bug with anonymous namespaces inside namespaces
132 # define PUGI__NS_BEGIN OIIO_NAMESPACE_BEGIN namespace pugi { namespace impl {
133 # define PUGI__NS_END } } OIIO_NAMESPACE_END
135 # define PUGI__NS_BEGIN OIIO_NAMESPACE_BEGIN namespace pugi { namespace impl { namespace {
136 # define PUGI__NS_END } } } OIIO_NAMESPACE_END
139 # define PUGI__FN_NO_INLINE PUGI__NO_INLINE
143 #if (defined(_MSC_VER) && _MSC_VER < 1600) || (defined(__BORLANDC__) && __BORLANDC__ < 0x561)
146 # ifndef _UINTPTR_T_DEFINED
150 typedef unsigned __int8 uint8_t;
151 typedef unsigned __int16 uint16_t;
152 typedef unsigned __int32 uint32_t;
170 template <
typename T>
192 #ifdef PUGIXML_WCHAR_MODE
204 #ifdef PUGIXML_WCHAR_MODE
205 return wcscmp(src, dst) == 0;
207 return strcmp(src, dst) == 0;
214 for (
size_t i = 0; i <
count; ++i)
215 if (lhs[i] != rhs[i])
218 return lhs[
count] == 0;
226 #ifdef PUGIXML_WCHAR_MODE
229 const wchar_t*
end =
s;
231 return static_cast<size_t>(end -
s);
263 #ifdef PUGIXML_COMPACT
265 class compact_hash_table
268 compact_hash_table(): _items(0), _capacity(0), _count(0)
283 void**
find(
const void* key)
287 if (_capacity == 0)
return 0;
289 size_t hashmod = _capacity - 1;
290 size_t bucket = hash(key) & hashmod;
292 for (
size_t probe = 0; probe <= hashmod; ++probe)
294 item_t& probe_item = _items[bucket];
296 if (probe_item.key == key)
297 return &probe_item.value;
299 if (probe_item.key == 0)
303 bucket = (bucket + probe + 1) & hashmod;
306 assert(
false &&
"Hash table is full");
310 void**
insert(
const void* key)
313 assert(_capacity != 0 && _count < _capacity - _capacity / 4);
315 size_t hashmod = _capacity - 1;
316 size_t bucket = hash(key) & hashmod;
318 for (
size_t probe = 0; probe <= hashmod; ++probe)
320 item_t& probe_item = _items[bucket];
322 if (probe_item.key == 0)
324 probe_item.key = key;
326 return &probe_item.value;
329 if (probe_item.key == key)
330 return &probe_item.value;
333 bucket = (bucket + probe + 1) & hashmod;
336 assert(
false &&
"Hash table is full");
342 if (_count + 16 >= _capacity - _capacity / 4)
362 static unsigned int hash(
const void* key)
364 unsigned int h =
static_cast<unsigned int>(
reinterpret_cast<uintptr_t>(key));
379 compact_hash_table rt;
380 rt._capacity = (_capacity == 0) ? 32 : _capacity * 2;
386 memset(rt._items, 0,
sizeof(item_t) * rt._capacity);
388 for (
size_t i = 0; i < _capacity; ++i)
390 *rt.insert(_items[i].key) = _items[i].value;
395 _capacity = rt._capacity;
398 assert(_count == rt._count);
407 #ifdef PUGIXML_COMPACT
408 static const uintptr_t xml_memory_block_alignment = 4;
410 static const uintptr_t xml_memory_block_alignment =
sizeof(
void*);
414 static const uintptr_t xml_memory_page_contents_shared_mask = 64;
415 static const uintptr_t xml_memory_page_name_allocated_mask = 32;
416 static const uintptr_t xml_memory_page_value_allocated_mask = 16;
417 static const uintptr_t xml_memory_page_type_mask = 15;
420 static const uintptr_t xml_memory_page_name_allocated_or_shared_mask = xml_memory_page_name_allocated_mask | xml_memory_page_contents_shared_mask;
421 static const uintptr_t xml_memory_page_value_allocated_or_shared_mask = xml_memory_page_value_allocated_mask | xml_memory_page_contents_shared_mask;
423 #ifdef PUGIXML_COMPACT
424 #define PUGI__GETHEADER_IMPL(object, page, flags) // unused
425 #define PUGI__GETPAGE_IMPL(header) (header).get_page()
427 #define PUGI__GETHEADER_IMPL(object, page, flags) (((reinterpret_cast<char*>(object) - reinterpret_cast<char*>(page)) << 8) | (flags))
429 #define PUGI__GETPAGE_IMPL(header) static_cast<impl::xml_memory_page*>(const_cast<void*>(static_cast<const void*>(reinterpret_cast<const char*>(&header) - (header >> 8))))
432 #define PUGI__GETPAGE(n) PUGI__GETPAGE_IMPL((n)->header)
433 #define PUGI__NODETYPE(n) static_cast<xml_node_type>((n)->header & impl::xml_memory_page_type_mask)
449 #ifdef PUGIXML_COMPACT
450 result->compact_string_base = 0;
451 result->compact_shared_parent = 0;
452 result->compact_page_marker = 0;
466 #ifdef PUGIXML_COMPACT
467 char_t* compact_string_base;
468 void* compact_shared_parent;
469 uint32_t* compact_page_marker;
473 static const size_t xml_memory_page_size =
474 #ifdef PUGIXML_MEMORY_PAGE_SIZE
475 (PUGIXML_MEMORY_PAGE_SIZE)
491 #ifdef PUGIXML_COMPACT
502 if (!memory)
return 0;
534 #ifdef PUGIXML_COMPACT
538 if (!result)
return 0;
541 ptrdiff_t
offset =
static_cast<char*
>(
result) - reinterpret_cast<char*>(out_page->compact_page_marker);
543 if (
PUGI__UNLIKELY(static_cast<uintptr_t>(offset) >= 256 * xml_memory_block_alignment))
548 *marker =
static_cast<uint32_t
>(
reinterpret_cast<char*
>(
marker) - reinterpret_cast<char*>(out_page));
549 out_page->compact_page_marker =
marker;
586 assert(
_root == page);
592 #ifdef PUGIXML_COMPACT
594 page->compact_string_base = 0;
595 page->compact_shared_parent = 0;
596 page->compact_page_marker = 0;
603 assert(
_root != page);
618 static const size_t max_encoded_offset = (1 << 16) * xml_memory_block_alignment;
626 size_t full_size = (size + (xml_memory_block_alignment - 1)) & ~(xml_memory_block_alignment - 1);
631 if (!header)
return 0;
634 ptrdiff_t page_offset =
reinterpret_cast<char*
>(header) - reinterpret_cast<char*>(page) -
sizeof(
xml_memory_page);
636 assert(page_offset % xml_memory_block_alignment == 0);
637 assert(page_offset >= 0 && static_cast<size_t>(page_offset) < max_encoded_offset);
638 header->
page_offset =
static_cast<uint16_t
>(
static_cast<size_t>(page_offset) / xml_memory_block_alignment);
641 assert(full_size % xml_memory_block_alignment == 0);
642 assert(full_size < max_encoded_offset || (page->
busy_size == full_size && page_offset == 0));
643 header->
full_size =
static_cast<uint16_t
>(full_size < max_encoded_offset ? full_size / xml_memory_block_alignment : 0);
647 return static_cast<char_t*
>(
static_cast<void*
>(header + 1));
661 xml_memory_page* page = reinterpret_cast<xml_memory_page*>(static_cast<void*>(reinterpret_cast<char*>(header) - page_offset));
664 size_t full_size = header->
full_size == 0 ? page->busy_size : header->
full_size * xml_memory_block_alignment;
671 #ifdef PUGIXML_COMPACT
672 return _hash->reserve();
681 #ifdef PUGIXML_COMPACT
682 compact_hash_table* _hash;
688 const size_t large_allocation_threshold = xml_memory_page_size / 4;
695 if (size <= large_allocation_threshold)
725 #ifdef PUGIXML_COMPACT
727 static const uintptr_t compact_alignment_log2 = 2;
728 static const uintptr_t compact_alignment = 1 << compact_alignment_log2;
737 ptrdiff_t offset = (
reinterpret_cast<char*
>(
this) - reinterpret_cast<char*>(page->compact_page_marker));
738 assert(offset % compact_alignment == 0 && static_cast<uintptr_t>(offset) < 256 * compact_alignment);
740 _page =
static_cast<unsigned char>(offset >> compact_alignment_log2);
741 _flags =
static_cast<unsigned char>(
flags);
746 _flags &=
static_cast<unsigned char>(mod);
751 _flags |=
static_cast<unsigned char>(mod);
762 const char* page_marker =
reinterpret_cast<const char*
>(
this) - (_page << compact_alignment_log2);
763 const char* page = page_marker - *
reinterpret_cast<const uint32_t*
>(
static_cast<const void*
>(page_marker));
770 unsigned char _flags;
775 const compact_header* header =
reinterpret_cast<const compact_header*
>(
static_cast<const char*
>(
object) - header_offset);
777 return header->get_page();
780 template <
int header_offset,
typename T>
PUGI__FN_NO_INLINE T* compact_get_value(
const void*
object)
782 return static_cast<T*
>(*compact_get_page(
object, header_offset)->allocator->_hash->find(
object));
785 template <
int header_offset,
typename T>
PUGI__FN_NO_INLINE void compact_set_value(
const void*
object, T*
value)
787 *compact_get_page(
object, header_offset)->allocator->_hash->insert(
object) =
value;
790 template <
typename T,
int header_offset,
int start = -126>
class compact_pointer
793 compact_pointer(): _data(0)
797 void operator=(
const compact_pointer& rhs)
802 void operator=(
T* value)
810 ptrdiff_t diff =
reinterpret_cast<char*
>(
value) - reinterpret_cast<char*>(
this);
811 ptrdiff_t offset = ((diff +
int(compact_alignment - 1)) >> compact_alignment_log2) -
start;
813 if (static_cast<uintptr_t>(offset) <= 253)
814 _data = static_cast<unsigned char>(offset + 1);
817 compact_set_value<header_offset>(
this,
value);
834 return reinterpret_cast<T*
>(base + ((_data - 1 +
start) << compact_alignment_log2));
837 return compact_get_value<header_offset, T>(
this);
843 T* operator->()
const
852 template <
typename T,
int header_offset>
class compact_pointer_parent
855 compact_pointer_parent(): _data(0)
859 void operator=(
const compact_pointer_parent& rhs)
864 void operator=(
T* value)
872 ptrdiff_t diff =
reinterpret_cast<char*
>(
value) - reinterpret_cast<char*>(
this);
873 ptrdiff_t offset = ((diff +
int(compact_alignment - 1)) >> compact_alignment_log2) + 65533;
875 if (static_cast<uintptr_t>(offset) <= 65533)
877 _data =
static_cast<unsigned short>(offset + 1);
884 page->compact_shared_parent =
value;
886 if (page->compact_shared_parent == value)
892 compact_set_value<header_offset>(
this,
value);
912 return reinterpret_cast<T*
>(base + ((_data - 1 - 65533) << compact_alignment_log2));
914 else if (_data == 65534)
915 return static_cast<T*
>(compact_get_page(
this, header_offset)->compact_shared_parent);
917 return compact_get_value<header_offset, T>(
this);
923 T* operator->()
const
932 template <
int header_offset,
int base_offset>
class compact_string
935 compact_string(): _data(0)
939 void operator=(
const compact_string& rhs)
944 void operator=(
char_t* value)
951 page->compact_string_base =
value;
953 ptrdiff_t offset = value - page->compact_string_base;
955 if (static_cast<uintptr_t>(offset) < (65535 << 7))
958 uint16_t* base =
reinterpret_cast<uint16_t*
>(
static_cast<void*
>(
reinterpret_cast<char*
>(
this) - base_offset));
962 *base =
static_cast<uint16_t
>((offset >> 7) + 1);
963 _data =
static_cast<unsigned char>((offset & 127) + 1);
967 ptrdiff_t
remainder = offset - ((*base - 1) << 7);
969 if (static_cast<uintptr_t>(
remainder) <= 253)
971 _data =
static_cast<unsigned char>(
remainder + 1);
975 compact_set_value<header_offset>(
this,
value);
983 compact_set_value<header_offset>(
this,
value);
1003 const uint16_t* base =
reinterpret_cast<const uint16_t*
>(
static_cast<const void*
>(
reinterpret_cast<const char*
>(
this) - base_offset));
1006 ptrdiff_t offset = ((*base - 1) << 7) + (_data - 1);
1008 return page->compact_string_base +
offset;
1012 return compact_get_value<header_offset, char_t>(
this);
1020 unsigned char _data;
1025 #ifdef PUGIXML_COMPACT
1028 struct xml_attribute_struct
1035 impl::compact_header
header;
1037 uint16_t namevalue_base;
1039 impl::compact_string<4, 2>
name;
1040 impl::compact_string<5, 3>
value;
1043 impl::compact_pointer<xml_attribute_struct, 7, 0>
next_attribute;
1046 struct xml_node_struct
1053 impl::compact_header
header;
1055 uint16_t namevalue_base;
1057 impl::compact_string<4, 2>
name;
1058 impl::compact_string<5, 3>
value;
1060 impl::compact_pointer_parent<xml_node_struct, 6>
parent;
1062 impl::compact_pointer<xml_node_struct, 8, 0>
first_child;
1065 impl::compact_pointer<xml_node_struct, 10, 0>
next_sibling;
1130 #ifdef PUGIXML_COMPACT
1131 compact_hash_table hash;
1155 void* memory = alloc.
allocate_object(
sizeof(xml_attribute_struct), page);
1156 if (!memory)
return 0;
1158 return new (memory) xml_attribute_struct(page);
1165 if (!memory)
return 0;
1167 return new (memory) xml_node_struct(page, type);
1172 if (a->header & impl::xml_memory_page_name_allocated_mask)
1175 if (a->header & impl::xml_memory_page_value_allocated_mask)
1183 if (n->header & impl::xml_memory_page_name_allocated_mask)
1186 if (n->header & impl::xml_memory_page_value_allocated_mask)
1189 for (xml_attribute_struct* attr = n->first_attribute; attr; )
1191 xml_attribute_struct* next = attr->next_attribute;
1198 for (xml_node_struct* child = n->first_child; child; )
1200 xml_node_struct* next = child->next_sibling;
1210 inline void append_node(xml_node_struct* child, xml_node_struct* node)
1212 child->parent = node;
1214 xml_node_struct* head = node->first_child;
1218 xml_node_struct* tail = head->prev_sibling_c;
1220 tail->next_sibling = child;
1221 child->prev_sibling_c = tail;
1222 head->prev_sibling_c = child;
1226 node->first_child = child;
1227 child->prev_sibling_c = child;
1233 child->parent = node;
1235 xml_node_struct* head = node->first_child;
1239 child->prev_sibling_c = head->prev_sibling_c;
1240 head->prev_sibling_c = child;
1243 child->prev_sibling_c = child;
1245 child->next_sibling = head;
1246 node->first_child = child;
1251 xml_node_struct* parent = node->parent;
1253 child->parent = parent;
1255 if (node->next_sibling)
1256 node->next_sibling->prev_sibling_c = child;
1258 parent->first_child->prev_sibling_c = child;
1260 child->next_sibling = node->next_sibling;
1261 child->prev_sibling_c = node;
1263 node->next_sibling = child;
1268 xml_node_struct* parent = node->parent;
1270 child->parent = parent;
1272 if (node->prev_sibling_c->next_sibling)
1273 node->prev_sibling_c->next_sibling = child;
1275 parent->first_child = child;
1277 child->prev_sibling_c = node->prev_sibling_c;
1278 child->next_sibling = node;
1280 node->prev_sibling_c = child;
1285 xml_node_struct* parent = node->parent;
1287 if (node->next_sibling)
1288 node->next_sibling->prev_sibling_c = node->prev_sibling_c;
1290 parent->first_child->prev_sibling_c = node->prev_sibling_c;
1292 if (node->prev_sibling_c->next_sibling)
1293 node->prev_sibling_c->next_sibling = node->next_sibling;
1295 parent->first_child = node->next_sibling;
1298 node->prev_sibling_c = 0;
1299 node->next_sibling = 0;
1304 xml_attribute_struct* head = node->first_attribute;
1308 xml_attribute_struct* tail = head->prev_attribute_c;
1310 tail->next_attribute = attr;
1311 attr->prev_attribute_c = tail;
1312 head->prev_attribute_c = attr;
1316 node->first_attribute = attr;
1317 attr->prev_attribute_c = attr;
1323 xml_attribute_struct* head = node->first_attribute;
1327 attr->prev_attribute_c = head->prev_attribute_c;
1328 head->prev_attribute_c = attr;
1331 attr->prev_attribute_c = attr;
1333 attr->next_attribute = head;
1334 node->first_attribute = attr;
1339 if (place->next_attribute)
1340 place->next_attribute->prev_attribute_c = attr;
1342 node->first_attribute->prev_attribute_c = attr;
1344 attr->next_attribute = place->next_attribute;
1345 attr->prev_attribute_c = place;
1346 place->next_attribute = attr;
1351 if (place->prev_attribute_c->next_attribute)
1352 place->prev_attribute_c->next_attribute = attr;
1354 node->first_attribute = attr;
1356 attr->prev_attribute_c = place->prev_attribute_c;
1357 attr->next_attribute = place;
1358 place->prev_attribute_c = attr;
1363 if (attr->next_attribute)
1364 attr->next_attribute->prev_attribute_c = attr->prev_attribute_c;
1366 node->first_attribute->prev_attribute_c = attr->prev_attribute_c;
1368 if (attr->prev_attribute_c->next_attribute)
1369 attr->prev_attribute_c->next_attribute = attr->next_attribute;
1371 node->first_attribute = attr->next_attribute;
1373 attr->prev_attribute_c = 0;
1374 attr->next_attribute = 0;
1379 if (!alloc.
reserve())
return 0;
1382 if (!child)
return 0;
1391 if (!alloc.
reserve())
return 0;
1394 if (!attr)
return 0;
1419 return static_cast<uint16_t
>(((value & 0xff) << 8) | (value >> 8));
1424 return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value & 0xff0000) >> 8) | (value >> 24);
1434 if (ch < 0x80)
return result + 1;
1436 else if (ch < 0x800)
return result + 2;
1438 else return result + 3;
1457 *result =
static_cast<uint8_t
>(ch);
1461 else if (ch < 0x800)
1463 result[0] =
static_cast<uint8_t
>(0xC0 | (ch >> 6));
1464 result[1] =
static_cast<uint8_t
>(0x80 | (ch & 0x3F));
1470 result[0] =
static_cast<uint8_t
>(0xE0 | (ch >> 12));
1471 result[1] =
static_cast<uint8_t
>(0x80 | ((ch >> 6) & 0x3F));
1472 result[2] =
static_cast<uint8_t
>(0x80 | (ch & 0x3F));
1480 result[0] =
static_cast<uint8_t
>(0xF0 | (ch >> 18));
1481 result[1] =
static_cast<uint8_t
>(0x80 | ((ch >> 12) & 0x3F));
1482 result[2] =
static_cast<uint8_t
>(0x80 | ((ch >> 6) & 0x3F));
1483 result[3] =
static_cast<uint8_t
>(0x80 | (ch & 0x3F));
1489 return (ch < 0x10000) ?
low(result, ch) :
high(result, ch);
1514 *result =
static_cast<uint16_t
>(ch);
1521 uint32_t msh =
static_cast<uint32_t
>(ch - 0x10000) >> 10;
1522 uint32_t lsh =
static_cast<uint32_t
>(ch - 0x10000) & 0x3ff;
1524 result[0] =
static_cast<uint16_t
>(0xD800 + msh);
1525 result[1] =
static_cast<uint16_t
>(0xDC00 + lsh);
1532 return (ch < 0x10000) ?
low(result, ch) :
high(result, ch);
1583 *result =
static_cast<uint8_t
>(ch > 255 ?
'?' : ch);
1604 const uint8_t utf8_byte_mask = 0x3f;
1608 uint8_t lead = *
data;
1613 result = Traits::low(result, lead);
1618 if ((reinterpret_cast<uintptr_t>(data) & 3) == 0)
1621 while (size >= 4 && (*static_cast<const uint32_t*>(static_cast<const void*>(data)) & 0x80808080) == 0)
1623 result = Traits::low(result, data[0]);
1624 result = Traits::low(result, data[1]);
1625 result = Traits::low(result, data[2]);
1626 result = Traits::low(result, data[3]);
1633 else if (static_cast<unsigned int>(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80)
1635 result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask));
1640 else if (static_cast<unsigned int>(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80)
1642 result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask));
1647 else if (static_cast<unsigned int>(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80)
1649 result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask));
1678 result = Traits::low(result, lead);
1683 else if (static_cast<unsigned int>(lead - 0xE000) < 0x2000)
1685 result = Traits::low(result, lead);
1690 else if (static_cast<unsigned int>(lead - 0xD800) < 0x400 && size >= 2)
1694 if (static_cast<unsigned int>(next - 0xDC00) < 0x400)
1696 result = Traits::high(result, 0x10000 + ((lead & 0x3ff) << 10) + (next & 0x3ff));
1730 result = Traits::low(result, lead);
1737 result = Traits::high(result, lead);
1755 result = Traits::low(result, *data);
1793 return decoder::process(reinterpret_cast<const typename decoder::type*>(data), size, result, traits);
1797 #ifdef PUGIXML_WCHAR_MODE
1798 PUGI__FN void convert_wchar_endian_swap(
wchar_t* result,
const wchar_t*
data,
size_t length)
1800 for (
size_t i = 0; i <
length; ++i)
1819 static const unsigned char chartype_table[256] =
1821 55, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 63, 0, 0,
1822 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1823 8, 0, 6, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 96, 64, 0,
1824 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 0, 1, 0, 48, 0,
1825 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1826 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 16, 0, 192,
1827 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1828 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 0, 0, 0,
1830 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1831 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1832 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1833 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1834 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1835 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1836 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1837 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192
1849 static const unsigned char chartypex_table[256] =
1851 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 2, 3, 3,
1852 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1853 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 16, 16, 0,
1854 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 3, 0, 3, 0,
1856 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1857 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 20,
1858 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1859 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0,
1861 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1862 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1863 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1864 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1865 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1866 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1867 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1868 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20
1871 #ifdef PUGIXML_WCHAR_MODE
1872 #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) ((static_cast<unsigned int>(c) < 128 ? table[static_cast<unsigned int>(c)] : table[128]) & (ct))
1874 #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast<unsigned char>(c)] & (ct))
1877 #define PUGI__IS_CHARTYPE(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartype_table)
1878 #define PUGI__IS_CHARTYPEX(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartypex_table)
1882 unsigned int ui = 1;
1884 return *
reinterpret_cast<unsigned char*
>(&ui) == 1;
1891 if (
sizeof(
wchar_t) == 2)
1899 #define PUGI__SCANCHAR(ch) { if (offset >= size || data[offset] != ch) return false; offset++; }
1900 #define PUGI__SCANCHARTYPE(ct) { while (offset < size && PUGI__IS_CHARTYPE(data[offset], ct)) offset++; }
1903 if (size < 6 || !((data[0] ==
'<') & (data[1] ==
'?') & (data[2] ==
'x') & (data[3] ==
'm') & (data[4] ==
'l') &&
PUGI__IS_CHARTYPE(data[5],
ct_space)))
1907 for (
size_t i = 6; i + 1 <
size; ++i)
1913 if (data[i] ==
'e' && data[i + 1] ==
'n')
1927 uint8_t delimiter = (offset < size && data[
offset] ==
'"') ?
'"' :
'\'';
1933 out_encoding = data +
offset;
1937 out_length = offset -
start;
1947 #undef PUGI__SCANCHAR
1948 #undef PUGI__SCANCHARTYPE
1956 uint8_t d0 = data[0], d1 = data[1], d2 = data[2], d3 = data[3];
1963 if (d0 == 0xef && d1 == 0xbb && d2 == 0xbf)
return encoding_utf8;
1976 const uint8_t* enc = 0;
1977 size_t enc_length = 0;
1982 if (enc_length == 10
1983 && (enc[0] |
' ') ==
'i' && (enc[1] |
' ') ==
's' && (enc[2] |
' ') ==
'o'
1984 && enc[3] ==
'-' && enc[4] ==
'8' && enc[5] ==
'8' && enc[6] ==
'5' && enc[7] ==
'9'
1985 && enc[8] ==
'-' && enc[9] ==
'1')
1990 && (enc[0] |
' ') ==
'l' && (enc[1] |
' ') ==
'a' && (enc[2] |
' ') ==
't'
1991 && (enc[3] |
' ') ==
'i' && (enc[4] |
' ') ==
'n'
2014 const uint8_t* data =
static_cast<const uint8_t*
>(contents);
2021 size_t length = size /
sizeof(
char_t);
2025 out_buffer =
static_cast<char_t*
>(
const_cast<void*
>(contents));
2031 if (!buffer)
return false;
2034 memcpy(buffer, contents, length *
sizeof(
char_t));
2036 assert(length == 0);
2041 out_length = length + 1;
2047 #ifdef PUGIXML_WCHAR_MODE
2054 PUGI__FN bool convert_buffer_endian_swap(
char_t*& out_buffer,
size_t& out_length,
const void* contents,
size_t size,
bool is_mutable)
2056 const char_t* data =
static_cast<const char_t*
>(contents);
2057 size_t length = size /
sizeof(
char_t);
2063 convert_wchar_endian_swap(buffer, data, length);
2071 if (!buffer)
return false;
2073 convert_wchar_endian_swap(buffer, data, length);
2077 out_length = length + 1;
2085 const typename D::type* data =
static_cast<const typename
D::type*
>(contents);
2086 size_t data_length = size /
sizeof(
typename D::type);
2089 size_t length = D::process(data, data_length, 0,
wchar_counter());
2093 if (!buffer)
return false;
2099 assert(oend == obegin + length);
2103 out_length = length + 1;
2114 if (encoding == wchar_encoding)
2118 if (need_endian_swap_utf(encoding, wchar_encoding))
2119 return convert_buffer_endian_swap(out_buffer, out_length, contents, size, is_mutable);
2130 return (native_encoding == encoding) ?
2140 return (native_encoding == encoding) ?
2149 assert(
false &&
"Invalid encoding");
2155 const typename D::type* data =
static_cast<const typename
D::type*
>(contents);
2156 size_t data_length = size /
sizeof(
typename D::type);
2159 size_t length = D::process(data, data_length, 0,
utf8_counter());
2163 if (!buffer)
return false;
2166 uint8_t* obegin =
reinterpret_cast<uint8_t*
>(
buffer);
2167 uint8_t* oend = D::process(data, data_length, obegin,
utf8_writer());
2169 assert(oend == obegin + length);
2173 out_length = length + 1;
2180 for (
size_t i = 0; i <
size; ++i)
2189 const uint8_t* data =
static_cast<const uint8_t*
>(contents);
2190 size_t data_length =
size;
2194 assert(prefix_length <= data_length);
2196 const uint8_t* postfix = data + prefix_length;
2197 size_t postfix_length = data_length - prefix_length;
2200 if (postfix_length == 0)
return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable);
2207 if (!buffer)
return false;
2210 memcpy(buffer, data, prefix_length);
2212 uint8_t* obegin =
reinterpret_cast<uint8_t*
>(
buffer);
2215 assert(oend == obegin + length);
2219 out_length = length + 1;
2235 return (native_encoding == encoding) ?
2245 return (native_encoding == encoding) ?
2254 assert(
false &&
"Invalid encoding");
2268 uint8_t* begin =
reinterpret_cast<uint8_t*
>(
buffer);
2271 assert(begin + size == end);
2276 #ifndef PUGIXML_NO_STL
2284 result.resize(size);
2287 if (size > 0)
as_utf8_end(&result[0], size, str, length);
2294 const uint8_t* data =
reinterpret_cast<const uint8_t*
>(str);
2300 std::basic_string<wchar_t>
result;
2301 result.resize(length);
2309 assert(begin + length == end);
2317 template <
typename Header>
2321 if (header & xml_memory_page_contents_shared_mask)
return false;
2323 size_t target_length =
strlength(target);
2326 if ((header & header_mask) == 0)
return target_length >=
length;
2329 const size_t reuse_threshold = 32;
2331 return target_length >= length && (target_length < reuse_threshold || target_length - length < target_length / 2);
2334 template <
typename String,
typename Header>
2337 if (source_length == 0)
2346 header &= ~header_mask;
2353 memcpy(dest, source, source_length *
sizeof(
char_t));
2354 dest[source_length] = 0;
2362 if (!alloc->
reserve())
return false;
2366 if (!buf)
return false;
2369 memcpy(buf, source, source_length *
sizeof(
char_t));
2370 buf[source_length] = 0;
2377 header |= header_mask;
2400 memmove(
end - size,
end, reinterpret_cast<char*>(s) - reinterpret_cast<char*>(
end));
2417 memmove(
end - size,
end, reinterpret_cast<char*>(s) - reinterpret_cast<char*>(
end));
2433 unsigned int ucsc = 0;
2441 if (ch ==
';')
return stre;
2445 if (static_cast<unsigned int>(ch -
'0') <= 9)
2446 ucsc = 16 * ucsc + (ch -
'0');
2447 else if (static_cast<unsigned int>((ch |
' ') -
'a') <= 5)
2448 ucsc = 16 * ucsc + ((ch |
' ') -
'a' + 10);
2463 if (ch ==
';')
return stre;
2467 if (static_cast<unsigned int>(static_cast<unsigned int>(ch) -
'0') <= 9)
2468 ucsc = 10 * ucsc + (ch -
'0');
2480 #ifdef PUGIXML_WCHAR_MODE
2486 g.
push(s, stre - s);
2496 if (*++stre ==
'p' && *++stre ==
';')
2501 g.
push(s, stre - s);
2505 else if (*stre ==
'p')
2507 if (*++stre ==
'o' && *++stre ==
's' && *++stre ==
';')
2512 g.
push(s, stre - s);
2521 if (*++stre ==
't' && *++stre ==
';')
2526 g.
push(s, stre - s);
2534 if (*++stre ==
't' && *++stre ==
';')
2539 g.
push(s, stre - s);
2547 if (*++stre ==
'u' && *++stre ==
'o' && *++stre ==
't' && *++stre ==
';')
2552 g.
push(s, stre - s);
2566 #define PUGI__ENDSWITH(c, e) ((c) == (e) || ((c) == 0 && endch == (e)))
2567 #define PUGI__SKIPWS() { while (PUGI__IS_CHARTYPE(*s, ct_space)) ++s; }
2568 #define PUGI__OPTSET(OPT) ( optmsk & (OPT) )
2569 #define PUGI__PUSHNODE(TYPE) { cursor = append_new_node(cursor, *alloc, TYPE); if (!cursor) PUGI__THROW_ERROR(status_out_of_memory, s); }
2570 #define PUGI__POPNODE() { cursor = cursor->parent; }
2571 #define PUGI__SCANFOR(X) { while (*s != 0 && !(X)) ++s; }
2572 #define PUGI__SCANWHILE(X) { while (X) ++s; }
2573 #define PUGI__SCANWHILE_UNROLL(X) { for (;;) { char_t ss = s[0]; if (PUGI__UNLIKELY(!(X))) { break; } ss = s[1]; if (PUGI__UNLIKELY(!(X))) { s += 1; break; } ss = s[2]; if (PUGI__UNLIKELY(!(X))) { s += 2; break; } ss = s[3]; if (PUGI__UNLIKELY(!(X))) { s += 3; break; } s += 4; } }
2574 #define PUGI__ENDSEG() { ch = *s; *s = 0; ++s; }
2575 #define PUGI__THROW_ERROR(err, m) return error_offset = m, error_status = err, static_cast<char_t*>(0)
2576 #define PUGI__CHECK_ERROR(err, m) { if (*s == 0) PUGI__THROW_ERROR(err, m); }
2590 if (*s ==
'\n') g.
push(s, 1);
2592 else if (s[0] ==
'-' && s[1] ==
'-' &&
PUGI__ENDSWITH(s[2],
'>'))
2596 return s + (s[2] ==
'>' ? 3 : 2);
2618 if (*s ==
'\n') g.
push(s, 1);
2620 else if (s[0] ==
']' && s[1] ==
']' &&
PUGI__ENDSWITH(s[2],
'>'))
2664 if (*s ==
'\n') g.
push(s, 1);
2691 switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4))
2701 default: assert(
false);
return 0;
2728 if (*s == end_quote)
2730 char_t* str = g.
flush(s);
2743 char_t* str = s + 1;
2769 if (*s == end_quote)
2781 if (*s ==
'\n') g.
push(s, 1);
2805 if (*s == end_quote)
2811 else if (*s ==
'\r')
2815 if (*s ==
'\n') g.
push(s, 1);
2837 if (*s == end_quote)
2860 switch ((optmask >> 4) & 15)
2878 default: assert(
false);
return 0;
2885 result.status = status;
2910 if (*s ==
'"' || *s ==
'\'')
2919 else if (s[0] ==
'<' && s[1] ==
'?')
2928 else if (s[0] ==
'<' && s[1] ==
'!' && s[2] ==
'-' && s[3] ==
'-')
2945 assert(s[0] ==
'<' && s[1] ==
'!' && s[2] ==
'[');
2950 if (s[0] ==
'<' && s[1] ==
'!' && s[2] ==
'[')
2956 else if (s[0] ==
']' && s[1] ==
']' && s[2] ==
'>')
2976 assert((s[0] ==
'<' || s[0] == 0) && s[1] ==
'!');
2981 if (s[0] ==
'<' && s[1] ==
'!' && s[2] !=
'-')
2996 else if (s[0] ==
'<' || s[0] ==
'"' || s[0] ==
'\'')
3052 s += (s[2] ==
'>' ? 3 : 2);
3060 if (*++s==
'C' && *++s==
'D' && *++s==
'A' && *++s==
'T' && *++s==
'A' && *++s ==
'[')
3093 s += (s[1] ==
'>' ? 2 : 1);
3097 else if (s[0] ==
'D' && s[1] ==
'O' && s[2] ==
'C' && s[3] ==
'T' && s[4] ==
'Y' && s[5] ==
'P' &&
PUGI__ENDSWITH(s[6],
'E'))
3103 char_t* mark = s + 9;
3108 assert((*s == 0 && endch ==
'>') || *s ==
'>');
3117 cursor->value = mark;
3127 char_t*
parse_question(char_t*
s, xml_node_struct*& ref_cursor,
unsigned int optmsk, char_t endch)
3130 xml_node_struct* cursor = ref_cursor;
3145 bool declaration = (target[0] |
' ') ==
'x' && (target[1] |
' ') ==
'm' && (target[2] |
' ') ==
'l' && target + 3 == s;
3195 cursor->value =
value;
3212 s += (s[1] ==
'>' ? 2 : 1);
3216 ref_cursor = cursor;
3221 char_t*
parse_tree(char_t*
s, xml_node_struct* root,
unsigned int optmsk, char_t endch)
3227 xml_node_struct* cursor = root;
3279 if (*s ==
'"' || *s ==
'\'')
3285 s = strconv_attribute(s, ch);
3308 else if (*s == 0 && endch ==
'>')
3321 else if (*s == 0 && endch ==
'>')
3353 char_t*
name = cursor->name;
3403 if (*s ==
'<' || !*s)
3414 if (s[0] !=
'<' || s[1] !=
'/' || cursor->first_child)
continue;
3436 s = strconv_pcdata(s);
3459 #ifdef PUGIXML_WCHAR_MODE
3462 unsigned int bom = 0xfeff;
3463 return (s[0] == static_cast<wchar_t>(bom)) ? s + 1 :
s;
3468 return (s[0] ==
'\xef' && s[1] ==
'\xbb' && s[2] ==
'\xbf') ? s + 3 :
s;
3478 node = node->next_sibling;
3491 xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c + 0 : 0;
3494 xml_parser parser(static_cast<xml_allocator*>(xmldoc));
3497 char_t endch = buffer[length - 1];
3498 buffer[length - 1] = 0;
3504 parser.
parse_tree(buffer_data, root, optmsk, endch);
3507 assert(result.offset >= 0 && static_cast<size_t>(result.offset) <= length);
3516 xml_node_struct* first_root_child_parsed = last_root_child ? last_root_child->next_sibling + 0 : root->first_child+ 0;
3524 if (result.offset > 0 && static_cast<size_t>(result.offset) == length - 1 && endch == 0)
3535 #ifdef PUGIXML_WCHAR_MODE
3564 typename T::value_type end = D::process(reinterpret_cast<const typename D::type*>(data), length, dest,
T());
3566 return static_cast<size_t>(end - dest) *
sizeof(*dest);
3573 typename T::value_type end = D::process(reinterpret_cast<const typename D::type*>(data), length, dest,
T());
3581 return static_cast<size_t>(end - dest) *
sizeof(*dest);
3584 #ifdef PUGIXML_WCHAR_MODE
3587 if (length < 1)
return 0;
3590 return (
sizeof(
wchar_t) == 2 && static_cast<unsigned int>(static_cast<uint16_t>(data[length - 1]) - 0xD800) < 0x400) ? length - 1 :
length;
3598 convert_wchar_endian_swap(r_char, data, length);
3600 return length *
sizeof(
char_t);
3627 assert(
false &&
"Invalid encoding");
3633 if (length < 5)
return 0;
3635 for (
size_t i = 1; i <= 4; ++i)
3637 uint8_t ch =
static_cast<uint8_t
>(data[length - i]);
3640 if ((ch & 0xc0) != 0x80)
return length - i;
3666 assert(
false &&
"Invalid encoding");
3689 void flush(
const char_t* data,
size_t size)
3691 if (size == 0)
return;
3695 writer.write(data, size *
sizeof(char_t));
3700 assert(result <=
sizeof(
scratch));
3718 writer.write(data, length *
sizeof(char_t));
3731 flush(data, chunk_size);
3735 length -= chunk_size;
3742 memcpy(buffer +
bufsize, data, length *
sizeof(char_t));
3752 memcpy(buffer + offset, data, length *
sizeof(char_t));
3767 buffer[offset++] = *data++;
3777 size_t length = offset -
bufsize;
3780 bufsize = offset - extra;
3791 buffer[offset + 0] = d0;
3800 buffer[offset + 0] = d0;
3801 buffer[offset + 1] = d1;
3805 void write(char_t d0, char_t d1, char_t d2)
3810 buffer[offset + 0] = d0;
3811 buffer[offset + 1] = d1;
3812 buffer[offset + 2] = d2;
3816 void write(char_t d0, char_t d1, char_t d2, char_t d3)
3821 buffer[offset + 0] = d0;
3822 buffer[offset + 1] = d1;
3823 buffer[offset + 2] = d2;
3824 buffer[offset + 3] = d3;
3828 void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4)
3833 buffer[offset + 0] = d0;
3834 buffer[offset + 1] = d1;
3835 buffer[offset + 2] = d2;
3836 buffer[offset + 3] = d3;
3837 buffer[offset + 4] = d4;
3841 void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4, char_t d5)
3846 buffer[offset + 0] = d0;
3847 buffer[offset + 1] = d1;
3848 buffer[offset + 2] = d2;
3849 buffer[offset + 3] = d3;
3850 buffer[offset + 4] = d4;
3851 buffer[offset + 5] = d5;
3861 #ifdef PUGIXML_MEMORY_OUTPUT_STACK
3862 PUGIXML_MEMORY_OUTPUT_STACK
3889 const char_t* prev =
s;
3894 writer.
write_buffer(prev, static_cast<size_t>(s - prev));
3900 writer.
write(
'&',
'a',
'm',
'p',
';');
3904 writer.
write(
'&',
'l',
't',
';');
3908 writer.
write(
'&',
'g',
't',
';');
3912 writer.
write(
'&',
'q',
'u',
'o',
't',
';');
3917 unsigned int ch =
static_cast<unsigned int>(*s++);
3920 writer.
write(
'&',
'#', static_cast<char_t>((ch / 10) +
'0'), static_cast<char_t>((ch % 10) +
'0'),
';');
3938 writer.
write(
'<',
'!',
'[',
'C',
'D');
3939 writer.
write(
'A',
'T',
'A',
'[');
3941 const char_t* prev =
s;
3944 while (*s && !(s[0] ==
']' && s[1] ==
']' && s[2] ==
'>')) ++
s;
3949 writer.
write_buffer(prev, static_cast<size_t>(s - prev));
3951 writer.
write(
']',
']',
'>');
3958 switch (indent_length)
3962 for (
unsigned int i = 0; i <
depth; ++i)
3963 writer.
write(indent[0]);
3969 for (
unsigned int i = 0; i <
depth; ++i)
3970 writer.
write(indent[0], indent[1]);
3976 for (
unsigned int i = 0; i <
depth; ++i)
3977 writer.
write(indent[0], indent[1], indent[2]);
3983 for (
unsigned int i = 0; i <
depth; ++i)
3984 writer.
write(indent[0], indent[1], indent[2], indent[3]);
3990 for (
unsigned int i = 0; i <
depth; ++i)
3998 writer.
write(
'<',
'!',
'-',
'-');
4002 const char_t* prev =
s;
4005 while (*s && !(s[0] ==
'-' && (s[1] ==
'-' || s[1] == 0))) ++
s;
4007 writer.
write_buffer(prev, static_cast<size_t>(s - prev));
4013 writer.
write(
'-',
' ');
4018 writer.
write(
'-',
'-',
'>');
4025 const char_t* prev =
s;
4028 while (*s && !(s[0] ==
'?' && s[1] ==
'>')) ++
s;
4030 writer.
write_buffer(prev, static_cast<size_t>(s - prev));
4034 assert(s[0] ==
'?' && s[1] ==
'>');
4036 writer.
write(
'?',
' ',
'>');
4044 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4046 for (xml_attribute_struct*
a = node->first_attribute;
a;
a =
a->next_attribute)
4060 writer.
write(
'=',
'"');
4071 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4072 const char_t*
name = node->name ? node->name + 0 : default_name;
4077 if (node->first_attribute)
4083 if (!node->first_child)
4087 writer.
write(
'>',
'<',
'/');
4098 writer.
write(
'/',
'>');
4116 if (!node->first_child)
4118 writer.
write(
'<',
'/');
4133 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4134 const char_t*
name = node->name ? node->name + 0 : default_name;
4136 writer.
write(
'<',
'/');
4143 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4160 writer.
write(
'<',
'?');
4161 writer.
write_string(node->name ? node->name + 0 : default_name);
4169 writer.
write(
'?',
'>');
4173 writer.
write(
'<',
'?');
4174 writer.
write_string(node->name ? node->name + 0 : default_name);
4176 writer.
write(
'?',
'>');
4180 writer.
write(
'<',
'!',
'D',
'O',
'C');
4181 writer.
write(
'T',
'Y',
'P',
'E');
4193 assert(
false &&
"Invalid node type");
4208 xml_node_struct* node = root;
4239 node = node->first_child;
4248 if (node->first_child)
4250 node = node->first_child;
4263 while (node != root)
4265 if (node->next_sibling)
4267 node = node->next_sibling;
4271 node = node->parent;
4290 while (node != root);
4298 for (xml_node_struct* child = node->first_child; child; child = child->next_sibling)
4311 for (xml_attribute_struct*
a = node->first_attribute;
a;
a =
a->next_attribute)
4339 if (parent.root() != child.root())
4343 xml_node cur = parent;
4356 template <
typename String,
typename Header>
4359 assert(!dest && (header & header_mask) == 0);
4363 if (alloc && (source_header & header_mask) == 0)
4368 header |= xml_memory_page_contents_shared_mask;
4369 source_header |= xml_memory_page_contents_shared_mask;
4378 node_copy_string(dn->name, dn->header, xml_memory_page_name_allocated_mask, sn->name, sn->header, shared_alloc);
4379 node_copy_string(dn->value, dn->header, xml_memory_page_value_allocated_mask, sn->value, sn->header, shared_alloc);
4381 for (xml_attribute_struct* sa = sn->first_attribute; sa; sa = sa->next_attribute)
4387 node_copy_string(da->name, da->header, xml_memory_page_name_allocated_mask, sa->name, sa->header, shared_alloc);
4388 node_copy_string(da->value, da->header, xml_memory_page_value_allocated_mask, sa->value, sa->header, shared_alloc);
4400 xml_node_struct* dit = dn;
4401 xml_node_struct* sit = sn->first_child;
4403 while (sit && sit != sn)
4413 if (sit->first_child)
4416 sit = sit->first_child;
4425 if (sit->next_sibling)
4427 sit = sit->next_sibling;
4443 node_copy_string(da->name, da->header, xml_memory_page_name_allocated_mask, sa->name, sa->header, shared_alloc);
4444 node_copy_string(da->value, da->header, xml_memory_page_value_allocated_mask, sa->value, sa->header, shared_alloc);
4458 const char_t* s =
value;
4465 s += (*s ==
'+' || *s ==
'-');
4467 bool overflow =
false;
4469 if (s[0] ==
'0' && (s[1] |
' ') ==
'x')
4477 const char_t* start =
s;
4481 if (static_cast<unsigned>(*s -
'0') < 10)
4482 result = result * 16 + (*s -
'0');
4483 else if (static_cast<unsigned>((*s |
' ') -
'a') < 6)
4484 result = result * 16 + ((*s |
' ') -
'a' + 10);
4491 size_t digits =
static_cast<size_t>(s -
start);
4493 overflow = digits >
sizeof(U) * 2;
4501 const char_t* start =
s;
4505 if (static_cast<unsigned>(*s -
'0') < 10)
4506 result = result * 10 + (*s -
'0');
4513 size_t digits =
static_cast<size_t>(s -
start);
4517 const size_t max_digits10 =
sizeof(U) == 8 ? 20 :
sizeof(U) == 4 ? 10 : 5;
4518 const char_t max_lead =
sizeof(U) == 8 ?
'1' :
sizeof(U) == 4 ?
'4' :
'6';
4519 const size_t high_bit =
sizeof(U) * 8 - 1;
4525 return (overflow || result > minneg) ? 0 - minneg : 0 -
result;
4527 return (overflow || result > maxpos) ? maxpos :
result;
4532 return string_to_integer<unsigned int>(
value, 0 -
static_cast<unsigned int>(INT_MIN), INT_MAX);
4537 return string_to_integer<unsigned int>(
value, 0, UINT_MAX);
4542 #ifdef PUGIXML_WCHAR_MODE
4543 return wcstod(value, 0);
4551 #ifdef PUGIXML_WCHAR_MODE
4552 return static_cast<float>(wcstod(value, 0));
4554 return static_cast<float>(
strtod(value, 0));
4564 return (first ==
'1' || first ==
't' || first ==
'T' || first ==
'y' || first ==
'Y');
4567 #ifdef PUGIXML_HAS_LONG_LONG
4568 PUGI__FN long long get_value_llong(
const char_t* value)
4570 return string_to_integer<unsigned long long>(
value, 0 -
static_cast<unsigned long long>(LLONG_MIN), LLONG_MAX);
4573 PUGI__FN unsigned long long get_value_ullong(
const char_t* value)
4575 return string_to_integer<unsigned long long>(
value, 0, ULLONG_MAX);
4581 char_t* result = end - 1;
4586 *result-- =
static_cast<char_t
>(
'0' + (rest % 10));
4591 assert(result >= begin);
4600 template <
typename String,
typename Header>
4603 #ifdef PUGIXML_WCHAR_MODE
4605 assert(strlen(buf) <
sizeof(wbuf) /
sizeof(wbuf[0]));
4608 for (; buf[
offset]; ++
offset) wbuf[offset] = buf[offset];
4610 return strcpy_insitu(dest, header, header_mask, wbuf, offset);
4612 return strcpy_insitu(dest, header, header_mask, buf, strlen(buf));
4616 template <
typename U,
typename String,
typename Header>
4620 char_t*
end = buf +
sizeof(
buf) /
sizeof(buf[0]);
4623 return strcpy_insitu(dest, header, header_mask, begin, end - begin);
4626 template <
typename String,
typename Header>
4635 template <
typename String,
typename Header>
4644 template <
typename String,
typename Header>
4665 if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents);
4668 if (own || buffer != contents) *out_buffer =
buffer;
4674 xml_parse_result
res = impl::xml_parser::parse(buffer, length, doc, root, options);
4677 res.encoding = buffer_encoding;
4685 #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE)
4687 typedef __int64 length_type;
4690 length_type length = _ftelli64(file);
4692 #elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))
4694 typedef off64_t length_type;
4697 length_type length = ftello64(file);
4701 typedef long length_type;
4704 length_type length =
ftell(file);
4712 size_t result =
static_cast<size_t>(
length);
4726 #ifdef PUGIXML_WCHAR_MODE
4729 if (encoding == wchar_encoding || need_endian_swap_utf(encoding, wchar_encoding))
4731 size_t length = size /
sizeof(
char_t);
4733 static_cast<char_t*
>(
buffer)[length] = 0;
4734 return (length + 1) *
sizeof(
char_t);
4739 static_cast<char*
>(
buffer)[size] = 0;
4756 size_t max_suffix_size =
sizeof(
char_t);
4763 size_t read_size = fread(contents, 1, size, file);
4765 if (read_size != size)
4773 return load_buffer_impl(doc, doc, contents,
zero_terminate_buffer(contents, size, real_encoding), options, real_encoding,
true,
true, out_buffer);
4781 #ifndef PUGIXML_NO_STL
4787 if (!memory)
return 0;
4812 T data[xml_memory_page_size /
sizeof(
T)];
4823 while (!stream.eof())
4830 if (last) last = last->
next = chunk;
4831 else chunks.
data = last = chunk;
4834 stream.read(chunk->
data, static_cast<std::streamsize>(
sizeof(chunk->
data) /
sizeof(
T)));
4835 chunk->
size =
static_cast<size_t>(stream.gcount()) *
sizeof(
T);
4838 if (stream.bad() || (!stream.eof() && stream.fail()))
return status_io_error;
4842 total += chunk->
size;
4845 size_t max_suffix_size =
sizeof(
char_t);
4855 assert(write + chunk->size <= buffer + total);
4856 memcpy(write, chunk->data, chunk->size);
4857 write += chunk->size;
4860 assert(write == buffer + total);
4872 typename std::basic_istream<T>::pos_type pos = stream.tellg();
4874 std::streamoff length = stream.tellg() - pos;
4880 size_t read_length =
static_cast<size_t>(
length);
4882 if (static_cast<std::streamsize>(read_length) != length || length < 0)
return status_out_of_memory;
4884 size_t max_suffix_size =
sizeof(
char_t);
4890 stream.read(static_cast<T*>(buffer.
data), static_cast<std::streamsize>(read_length));
4893 if (stream.bad() || (!stream.eof() && stream.fail()))
return status_io_error;
4896 size_t actual_length =
static_cast<size_t>(stream.gcount());
4897 assert(actual_length <= read_length);
4899 *out_buffer = buffer.
release();
4900 *out_size = actual_length *
sizeof(
T);
4915 if (stream.tellg() < 0)
4927 return load_buffer_impl(doc, doc, buffer,
zero_terminate_buffer(buffer, size, real_encoding), options, real_encoding,
true,
true, out_buffer);
4931 #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR)))
4934 return _wfopen(path, mode);
4947 if (!result)
return 0;
4962 if (!path_utf8)
return 0;
4965 char mode_ascii[4] = {0};
4966 for (
size_t i = 0; mode[i]; ++i) mode_ascii[i] = static_cast<char>(mode[i]);
4969 FILE* result =
fopen(path_utf8, mode_ascii);
4980 if (!file)
return false;
4982 xml_writer_file writer(file);
4983 doc.save(writer, indent, flags, encoding);
4985 return ferror(file) == 0;
5013 size_t result = fwrite(data, 1, size, static_cast<FILE*>(file));
5017 #ifndef PUGIXML_NO_STL
5030 assert(!wide_stream);
5031 narrow_stream->write(reinterpret_cast<const char*>(data), static_cast<std::streamsize>(size));
5035 assert(wide_stream);
5036 assert(size %
sizeof(
wchar_t) == 0);
5038 wide_stream->write(reinterpret_cast<const wchar_t*>(data), static_cast<std::streamsize>(size /
sizeof(
wchar_t)));
5078 PUGI__FN xml_attribute::operator xml_attribute::unspecified_bool_type()
const
5080 return _attr ? unspecified_bool_xml_attribute : 0;
5090 return (_attr == r._attr);
5095 return (_attr != r._attr);
5100 return (_attr < r._attr);
5105 return (_attr > r._attr);
5110 return (_attr <= r._attr);
5115 return (_attr >= r._attr);
5130 return (_attr && _attr->
value) ? _attr->
value + 0 : def;
5158 #ifdef PUGIXML_HAS_LONG_LONG
5159 PUGI__FN long long xml_attribute::as_llong(
long long def)
const
5161 return (_attr && _attr->
value) ? impl::get_value_llong(_attr->
value) : def;
5164 PUGI__FN unsigned long long xml_attribute::as_ullong(
unsigned long long def)
const
5166 return (_attr && _attr->
value) ? impl::get_value_ullong(_attr->
value) : def;
5243 #ifdef PUGIXML_HAS_LONG_LONG
5259 if (!_attr)
return false;
5266 if (!_attr)
return false;
5273 if (!_attr)
return false;
5275 return impl::set_value_integer<unsigned int>(_attr->
value, _attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5280 if (!_attr)
return false;