14#ifndef SOURCE_PUGIXML_CPP
15#define SOURCE_PUGIXML_CPP
25#ifdef PUGIXML_WCHAR_MODE
29#ifndef PUGIXML_NO_XPATH
44# pragma clang diagnostic push
45# pragma clang diagnostic ignored "-Wconversion"
46# pragma clang diagnostic ignored "-Wdouble-promotion"
51# pragma warning(disable: 4127)
52# pragma warning(disable: 4324)
53# pragma warning(disable: 4702)
54# pragma warning(disable: 4996)
57#if defined(_MSC_VER) && defined(__c2__)
58# pragma clang diagnostic push
59# pragma clang diagnostic ignored "-Wdeprecated"
62#ifdef __INTEL_COMPILER
63# pragma warning(disable: 177)
64# pragma warning(disable: 279)
65# pragma warning(disable: 1478 1786)
66# pragma warning(disable: 1684)
69#if defined(__BORLANDC__) && defined(PUGIXML_HEADER_ONLY)
81# pragma diag_suppress=178
82# pragma diag_suppress=237
85#ifdef __TI_COMPILER_VERSION__
86# pragma diag_suppress 179
90#if defined(_MSC_VER) && _MSC_VER >= 1300
91# define PUGI__NO_INLINE __declspec(noinline)
92#elif defined(__GNUC__)
93# define PUGI__NO_INLINE __attribute__((noinline))
95# define PUGI__NO_INLINE
99#if defined(__GNUC__) && !defined(__c2__)
100# define PUGI__UNLIKELY(cond) __builtin_expect(cond, 0)
102# define PUGI__UNLIKELY(cond) (cond)
106#define PUGI__STATIC_ASSERT(cond) { static const char condition_failed[(cond) ? 1 : -1] = {0}; (void)condition_failed[0]; }
110# define PUGI__DMC_VOLATILE volatile
112# define PUGI__DMC_VOLATILE
116#if defined(__clang__) && defined(__has_attribute)
117# if __has_attribute(no_sanitize)
118# define PUGI__UNSIGNED_OVERFLOW __attribute__((no_sanitize("unsigned-integer-overflow")))
120# define PUGI__UNSIGNED_OVERFLOW
123# define PUGI__UNSIGNED_OVERFLOW
127#if defined(__BORLANDC__) && !defined(__MEM_H_USING_LIST)
134#if defined(PUGIXML_HAS_LONG_LONG) && defined(__GNUC__) && !defined(LLONG_MAX) && !defined(LLONG_MIN) && !defined(ULLONG_MAX)
135# define LLONG_MIN (-LLONG_MAX - 1LL)
136# define LLONG_MAX __LONG_LONG_MAX__
137# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
141#if defined(_MSC_VER) && !defined(__S3E__)
142# define PUGI__MSVC_CRT_VERSION _MSC_VER
146#if __cplusplus >= 201103
147# define PUGI__SNPRINTF(buf, ...) snprintf(buf, sizeof(buf), __VA_ARGS__)
148#elif defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400
149# define PUGI__SNPRINTF(buf, ...) _snprintf_s(buf, _countof(buf), _TRUNCATE, __VA_ARGS__)
151# define PUGI__SNPRINTF sprintf
155#ifdef PUGIXML_HEADER_ONLY
156# define PUGI__NS_BEGIN namespace pugi { namespace impl {
157# define PUGI__NS_END } }
158# define PUGI__FN inline
159# define PUGI__FN_NO_INLINE inline
161# if defined(_MSC_VER) && _MSC_VER < 1300
162# define PUGI__NS_BEGIN namespace pugi { namespace impl {
163# define PUGI__NS_END } }
165# define PUGI__NS_BEGIN namespace pugi { namespace impl { namespace {
166# define PUGI__NS_END } } }
169# define PUGI__FN_NO_INLINE PUGI__NO_INLINE
173#if (defined(_MSC_VER) && _MSC_VER < 1600) || (defined(__BORLANDC__) && __BORLANDC__ < 0x561)
176# ifndef _UINTPTR_T_DEFINED
177 typedef size_t uintptr_t;
180 typedef unsigned __int8 uint8_t;
181 typedef unsigned __int16 uint16_t;
182 typedef unsigned __int32 uint32_t;
200 template <
typename T>
222 #ifdef PUGIXML_WCHAR_MODE
234 #ifdef PUGIXML_WCHAR_MODE
235 return wcscmp(src, dst) == 0;
237 return strcmp(src, dst) == 0;
244 for (
size_t i = 0; i < count; ++i)
245 if (lhs[i] != rhs[i])
248 return lhs[count] == 0;
256 #ifdef PUGIXML_WCHAR_MODE
259 const wchar_t* end = s;
261 return static_cast<size_t>(end - s);
270 typedef void (*
D)(T*);
293#ifdef PUGIXML_COMPACT
295 class compact_hash_table
298 compact_hash_table(): _items(0), _capacity(0), _count(0)
313 void* find(
const void* key)
315 if (_capacity == 0)
return 0;
317 item_t* item = get_item(key);
319 assert(item->key == key || (item->key == 0 && item->value == 0));
324 void insert(
const void* key,
void* value)
326 assert(_capacity != 0 && _count < _capacity - _capacity / 4);
328 item_t* item = get_item(key);
340 bool reserve(
size_t extra = 16)
342 if (_count + extra >= _capacity - _capacity / 4)
343 return rehash(_count + extra);
360 bool rehash(
size_t count);
362 item_t* get_item(
const void* key)
365 assert(_capacity > 0);
367 size_t hashmod = _capacity - 1;
368 size_t bucket = hash(key) & hashmod;
370 for (
size_t probe = 0; probe <= hashmod; ++probe)
372 item_t& probe_item = _items[bucket];
374 if (probe_item.key == key || probe_item.key == 0)
378 bucket = (bucket + probe + 1) & hashmod;
381 assert(
false &&
"Hash table is full");
387 unsigned int h =
static_cast<unsigned int>(
reinterpret_cast<uintptr_t
>(key));
402 size_t capacity = 32;
403 while (count >= capacity - capacity / 4)
406 compact_hash_table rt;
407 rt._capacity = capacity;
413 memset(rt._items, 0,
sizeof(item_t) * capacity);
415 for (
size_t i = 0; i < _capacity; ++i)
417 rt.insert(_items[i].key, _items[i].value);
422 _capacity = capacity;
425 assert(_count == rt._count);
434#ifdef PUGIXML_COMPACT
450#ifdef PUGIXML_COMPACT
451 #define PUGI__GETHEADER_IMPL(object, page, flags)
452 #define PUGI__GETPAGE_IMPL(header) (header).get_page()
454 #define PUGI__GETHEADER_IMPL(object, page, flags) (((reinterpret_cast<char*>(object) - reinterpret_cast<char*>(page)) << 8) | (flags))
456 #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))))
459 #define PUGI__GETPAGE(n) PUGI__GETPAGE_IMPL((n)->header)
460 #define PUGI__NODETYPE(n) static_cast<xml_node_type>((n)->header & impl::xml_memory_page_type_mask)
476 #ifdef PUGIXML_COMPACT
477 result->compact_string_base = 0;
478 result->compact_shared_parent = 0;
479 result->compact_page_marker = 0;
493 #ifdef PUGIXML_COMPACT
494 char_t* compact_string_base;
495 void* compact_shared_parent;
496 uint32_t* compact_page_marker;
501 #ifdef PUGIXML_MEMORY_PAGE_SIZE
502 (PUGIXML_MEMORY_PAGE_SIZE)
518 #ifdef PUGIXML_COMPACT
529 if (!memory)
return 0;
561 #ifdef PUGIXML_COMPACT
565 if (!result)
return 0;
568 ptrdiff_t offset =
static_cast<char*
>(result) -
reinterpret_cast<char*
>(out_page->compact_page_marker);
573 uint32_t* marker =
static_cast<uint32_t*
>(result);
575 *marker =
static_cast<uint32_t
>(
reinterpret_cast<char*
>(marker) -
reinterpret_cast<char*
>(out_page));
576 out_page->compact_page_marker = marker;
613 assert(
_root == page);
619 #ifdef PUGIXML_COMPACT
621 page->compact_string_base = 0;
622 page->compact_shared_parent = 0;
623 page->compact_page_marker = 0;
630 assert(
_root != page);
658 if (!header)
return 0;
661 ptrdiff_t page_offset =
reinterpret_cast<char*
>(header) -
reinterpret_cast<char*
>(page) -
sizeof(
xml_memory_page);
664 assert(page_offset >= 0 &&
static_cast<size_t>(page_offset) < max_encoded_offset);
669 assert(full_size < max_encoded_offset || (page->
busy_size == full_size && page_offset == 0));
674 return static_cast<char_t*
>(
static_cast<void*
>(header + 1));
698 #ifdef PUGIXML_COMPACT
699 return _hash->reserve();
708 #ifdef PUGIXML_COMPACT
709 compact_hash_table* _hash;
722 if (size <= large_allocation_threshold)
752#ifdef PUGIXML_COMPACT
754 static const uintptr_t compact_alignment_log2 = 2;
755 static const uintptr_t compact_alignment = 1 << compact_alignment_log2;
764 ptrdiff_t offset = (
reinterpret_cast<char*
>(
this) -
reinterpret_cast<char*
>(page->compact_page_marker));
765 assert(offset % compact_alignment == 0 &&
static_cast<uintptr_t
>(offset) < 256 * compact_alignment);
767 _page =
static_cast<unsigned char>(offset >> compact_alignment_log2);
768 _flags =
static_cast<unsigned char>(flags);
771 void operator&=(uintptr_t mod)
773 _flags &=
static_cast<unsigned char>(mod);
776 void operator|=(uintptr_t mod)
778 _flags |=
static_cast<unsigned char>(mod);
781 uintptr_t operator&(uintptr_t mod)
const
789 const char* page_marker =
reinterpret_cast<const char*
>(
this) - (_page << compact_alignment_log2);
790 const char* page = page_marker - *
reinterpret_cast<const uint32_t*
>(
static_cast<const void*
>(page_marker));
797 unsigned char _flags;
802 const compact_header* header =
reinterpret_cast<const compact_header*
>(
static_cast<const char*
>(object) - header_offset);
804 return header->get_page();
807 template <
int header_offset,
typename T>
PUGI__FN_NO_INLINE T* compact_get_value(
const void*
object)
809 return static_cast<T*
>(compact_get_page(
object, header_offset)->allocator->_hash->find(
object));
812 template <
int header_offset,
typename T>
PUGI__FN_NO_INLINE void compact_set_value(
const void*
object, T* value)
814 compact_get_page(
object, header_offset)->allocator->_hash->insert(
object, value);
817 template <
typename T,
int header_offset,
int start = -126>
class compact_pointer
820 compact_pointer(): _data(0)
824 void operator=(
const compact_pointer& rhs)
829 void operator=(T* value)
837 ptrdiff_t diff =
reinterpret_cast<char*
>(value) -
reinterpret_cast<char*
>(
this);
838 ptrdiff_t offset = ((diff + int(compact_alignment - 1)) >> compact_alignment_log2) - start;
840 if (
static_cast<uintptr_t
>(offset) <= 253)
841 _data =
static_cast<unsigned char>(offset + 1);
844 compact_set_value<header_offset>(
this, value);
859 uintptr_t base =
reinterpret_cast<uintptr_t
>(
this) & ~(compact_alignment - 1);
861 return reinterpret_cast<T*
>(base + (_data - 1 + start) * compact_alignment);
864 return compact_get_value<header_offset, T>(
this);
870 T* operator->()
const
879 template <
typename T,
int header_offset>
class compact_pointer_parent
882 compact_pointer_parent(): _data(0)
886 void operator=(
const compact_pointer_parent& rhs)
891 void operator=(T* value)
899 ptrdiff_t diff =
reinterpret_cast<char*
>(value) -
reinterpret_cast<char*
>(
this);
900 ptrdiff_t offset = ((diff + int(compact_alignment - 1)) >> compact_alignment_log2) + 65533;
902 if (
static_cast<uintptr_t
>(offset) <= 65533)
904 _data =
static_cast<unsigned short>(offset + 1);
911 page->compact_shared_parent = value;
913 if (page->compact_shared_parent == value)
919 compact_set_value<header_offset>(
this, value);
937 uintptr_t base =
reinterpret_cast<uintptr_t
>(
this) & ~(compact_alignment - 1);
939 return reinterpret_cast<T*
>(base + (_data - 1 - 65533) * compact_alignment);
941 else if (_data == 65534)
942 return static_cast<T*
>(compact_get_page(
this, header_offset)->compact_shared_parent);
944 return compact_get_value<header_offset, T>(
this);
950 T* operator->()
const
959 template <
int header_offset,
int base_offset>
class compact_string
962 compact_string(): _data(0)
966 void operator=(
const compact_string& rhs)
971 void operator=(char_t* value)
978 page->compact_string_base = value;
980 ptrdiff_t offset = value - page->compact_string_base;
982 if (
static_cast<uintptr_t
>(offset) < (65535 << 7))
985 uint16_t* base =
reinterpret_cast<uint16_t*
>(
static_cast<void*
>(
reinterpret_cast<char*
>(
this) - base_offset));
989 *base =
static_cast<uint16_t
>((offset >> 7) + 1);
990 _data =
static_cast<unsigned char>((offset & 127) + 1);
994 ptrdiff_t remainder = offset - ((*base - 1) << 7);
996 if (
static_cast<uintptr_t
>(remainder) <= 253)
998 _data =
static_cast<unsigned char>(remainder + 1);
1002 compact_set_value<header_offset>(
this, value);
1010 compact_set_value<header_offset>(
this, value);
1021 operator char_t*()
const
1030 const uint16_t* base =
reinterpret_cast<const uint16_t*
>(
static_cast<const void*
>(
reinterpret_cast<const char*
>(
this) - base_offset));
1033 ptrdiff_t offset = ((*base - 1) << 7) + (_data - 1);
1035 return page->compact_string_base + offset;
1039 return compact_get_value<header_offset, char_t>(
this);
1047 unsigned char _data;
1052#ifdef PUGIXML_COMPACT
1055 struct xml_attribute_struct
1062 impl::compact_header
header;
1064 uint16_t namevalue_base;
1066 impl::compact_string<4, 2>
name;
1067 impl::compact_string<5, 3>
value;
1070 impl::compact_pointer<xml_attribute_struct, 7, 0>
next_attribute;
1080 impl::compact_header
header;
1082 uint16_t namevalue_base;
1084 impl::compact_string<4, 2>
name;
1085 impl::compact_string<5, 3>
value;
1087 impl::compact_pointer_parent<xml_node_struct, 6>
parent;
1089 impl::compact_pointer<xml_node_struct, 8, 0>
first_child;
1092 impl::compact_pointer<xml_node_struct, 10, 0>
next_sibling;
1157 #ifdef PUGIXML_COMPACT
1158 compact_hash_table hash;
1182 void* memory = alloc.
allocate_object(
sizeof(xml_attribute_struct), page);
1183 if (!memory)
return 0;
1185 return new (memory) xml_attribute_struct(page);
1192 if (!memory)
return 0;
1199 if (a->header & impl::xml_memory_page_name_allocated_mask)
1202 if (a->header & impl::xml_memory_page_value_allocated_mask)
1210 if (n->header & impl::xml_memory_page_name_allocated_mask)
1213 if (n->header & impl::xml_memory_page_value_allocated_mask)
1216 for (xml_attribute_struct* attr = n->first_attribute; attr; )
1218 xml_attribute_struct* next = attr->next_attribute;
1239 child->parent = node;
1247 tail->next_sibling = child;
1248 child->prev_sibling_c = tail;
1249 head->prev_sibling_c = child;
1253 node->first_child = child;
1254 child->prev_sibling_c = child;
1260 child->parent = node;
1266 child->prev_sibling_c = head->prev_sibling_c;
1267 head->prev_sibling_c = child;
1270 child->prev_sibling_c = child;
1272 child->next_sibling = head;
1273 node->first_child = child;
1280 child->parent = parent;
1282 if (node->next_sibling)
1283 node->next_sibling->prev_sibling_c = child;
1285 parent->first_child->prev_sibling_c = child;
1287 child->next_sibling = node->next_sibling;
1288 child->prev_sibling_c = node;
1290 node->next_sibling = child;
1297 child->parent = parent;
1299 if (node->prev_sibling_c->next_sibling)
1300 node->prev_sibling_c->next_sibling = child;
1302 parent->first_child = child;
1304 child->prev_sibling_c = node->prev_sibling_c;
1305 child->next_sibling = node;
1307 node->prev_sibling_c = child;
1314 if (node->next_sibling)
1315 node->next_sibling->prev_sibling_c = node->prev_sibling_c;
1317 parent->first_child->prev_sibling_c = node->prev_sibling_c;
1319 if (node->prev_sibling_c->next_sibling)
1320 node->prev_sibling_c->next_sibling = node->next_sibling;
1322 parent->first_child = node->next_sibling;
1325 node->prev_sibling_c = 0;
1326 node->next_sibling = 0;
1331 xml_attribute_struct* head = node->first_attribute;
1335 xml_attribute_struct* tail = head->prev_attribute_c;
1337 tail->next_attribute = attr;
1338 attr->prev_attribute_c = tail;
1339 head->prev_attribute_c = attr;
1343 node->first_attribute = attr;
1344 attr->prev_attribute_c = attr;
1350 xml_attribute_struct* head = node->first_attribute;
1354 attr->prev_attribute_c = head->prev_attribute_c;
1355 head->prev_attribute_c = attr;
1358 attr->prev_attribute_c = attr;
1360 attr->next_attribute = head;
1361 node->first_attribute = attr;
1366 if (place->next_attribute)
1367 place->next_attribute->prev_attribute_c = attr;
1369 node->first_attribute->prev_attribute_c = attr;
1371 attr->next_attribute = place->next_attribute;
1372 attr->prev_attribute_c = place;
1373 place->next_attribute = attr;
1378 if (place->prev_attribute_c->next_attribute)
1379 place->prev_attribute_c->next_attribute = attr;
1381 node->first_attribute = attr;
1383 attr->prev_attribute_c = place->prev_attribute_c;
1384 attr->next_attribute = place;
1385 place->prev_attribute_c = attr;
1390 if (attr->next_attribute)
1391 attr->next_attribute->prev_attribute_c = attr->prev_attribute_c;
1393 node->first_attribute->prev_attribute_c = attr->prev_attribute_c;
1395 if (attr->prev_attribute_c->next_attribute)
1396 attr->prev_attribute_c->next_attribute = attr->next_attribute;
1398 node->first_attribute = attr->next_attribute;
1400 attr->prev_attribute_c = 0;
1401 attr->next_attribute = 0;
1406 if (!alloc.
reserve())
return 0;
1409 if (!child)
return 0;
1418 if (!alloc.
reserve())
return 0;
1421 if (!attr)
return 0;
1446 return static_cast<uint16_t
>(((value & 0xff) << 8) | (value >> 8));
1451 return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value & 0xff0000) >> 8) | (value >> 24);
1461 if (ch < 0x80)
return result + 1;
1463 else if (ch < 0x800)
return result + 2;
1465 else return result + 3;
1484 *result =
static_cast<uint8_t
>(ch);
1488 else if (ch < 0x800)
1490 result[0] =
static_cast<uint8_t
>(0xC0 | (ch >> 6));
1491 result[1] =
static_cast<uint8_t
>(0x80 | (ch & 0x3F));
1497 result[0] =
static_cast<uint8_t
>(0xE0 | (ch >> 12));
1498 result[1] =
static_cast<uint8_t
>(0x80 | ((ch >> 6) & 0x3F));
1499 result[2] =
static_cast<uint8_t
>(0x80 | (ch & 0x3F));
1507 result[0] =
static_cast<uint8_t
>(0xF0 | (ch >> 18));
1508 result[1] =
static_cast<uint8_t
>(0x80 | ((ch >> 12) & 0x3F));
1509 result[2] =
static_cast<uint8_t
>(0x80 | ((ch >> 6) & 0x3F));
1510 result[3] =
static_cast<uint8_t
>(0x80 | (ch & 0x3F));
1516 return (ch < 0x10000) ?
low(result, ch) :
high(result, ch);
1541 *result =
static_cast<uint16_t
>(ch);
1548 uint32_t msh =
static_cast<uint32_t
>(ch - 0x10000) >> 10;
1549 uint32_t lsh =
static_cast<uint32_t
>(ch - 0x10000) & 0x3ff;
1551 result[0] =
static_cast<uint16_t
>(0xD800 + msh);
1552 result[1] =
static_cast<uint16_t
>(0xDC00 + lsh);
1559 return (ch < 0x10000) ?
low(result, ch) :
high(result, ch);
1610 *result =
static_cast<uint8_t
>(ch > 255 ?
'?' : ch);
1629 template <
typename Traits>
static inline typename Traits::value_type
process(
const uint8_t* data,
size_t size,
typename Traits::value_type result, Traits)
1631 const uint8_t utf8_byte_mask = 0x3f;
1635 uint8_t lead = *data;
1640 result = Traits::low(result, lead);
1645 if ((
reinterpret_cast<uintptr_t
>(data) & 3) == 0)
1648 while (size >= 4 && (*
static_cast<const uint32_t*
>(
static_cast<const void*
>(data)) & 0x80808080) == 0)
1650 result = Traits::low(result, data[0]);
1651 result = Traits::low(result, data[1]);
1652 result = Traits::low(result, data[2]);
1653 result = Traits::low(result, data[3]);
1660 else if (
static_cast<unsigned int>(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80)
1662 result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask));
1667 else if (
static_cast<unsigned int>(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80)
1669 result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask));
1674 else if (
static_cast<unsigned int>(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80)
1676 result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask));
1696 template <
typename Traits>
static inline typename Traits::value_type
process(
const uint16_t* data,
size_t size,
typename Traits::value_type result, Traits)
1700 uint16_t lead = opt_swap::value ?
endian_swap(*data) : *data;
1705 result = Traits::low(result, lead);
1710 else if (
static_cast<unsigned int>(lead - 0xE000) < 0x2000)
1712 result = Traits::low(result, lead);
1717 else if (
static_cast<unsigned int>(lead - 0xD800) < 0x400 && size >= 2)
1719 uint16_t next = opt_swap::value ?
endian_swap(data[1]) : data[1];
1721 if (
static_cast<unsigned int>(next - 0xDC00) < 0x400)
1723 result = Traits::high(result, 0x10000 + ((lead & 0x3ff) << 10) + (next & 0x3ff));
1748 template <
typename Traits>
static inline typename Traits::value_type
process(
const uint32_t* data,
size_t size,
typename Traits::value_type result, Traits)
1752 uint32_t lead = opt_swap::value ?
endian_swap(*data) : *data;
1757 result = Traits::low(result, lead);
1764 result = Traits::high(result, lead);
1778 template <
typename Traits>
static inline typename Traits::value_type
process(
const uint8_t* data,
size_t size,
typename Traits::value_type result, Traits)
1782 result = Traits::low(result, *data);
1816 template <
typename Traits>
static inline typename Traits::value_type
process(
const wchar_t* data,
size_t size,
typename Traits::value_type result, Traits traits)
1820 return decoder::process(
reinterpret_cast<const typename decoder::type*
>(data), size, result, traits);
1824#ifdef PUGIXML_WCHAR_MODE
1825 PUGI__FN void convert_wchar_endian_swap(
wchar_t* result,
const wchar_t* data,
size_t length)
1827 for (
size_t i = 0; i < length; ++i)
1848 55, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 63, 0, 0,
1849 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1850 8, 0, 6, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 96, 64, 0,
1851 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 0, 1, 0, 48, 0,
1852 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1853 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 16, 0, 192,
1854 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1855 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 0, 0, 0,
1857 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1858 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1859 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1860 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1861 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1862 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1863 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1864 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192
1878 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 2, 3, 3,
1879 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1880 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 16, 16, 0,
1881 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 3, 0, 3, 0,
1883 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1884 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 20,
1885 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1886 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0,
1888 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1889 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1890 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1891 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1892 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1893 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1894 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1895 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20
1898#ifdef PUGIXML_WCHAR_MODE
1899 #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) ((static_cast<unsigned int>(c) < 128 ? table[static_cast<unsigned int>(c)] : table[128]) & (ct))
1901 #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast<unsigned char>(c)] & (ct))
1904 #define PUGI__IS_CHARTYPE(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartype_table)
1905 #define PUGI__IS_CHARTYPEX(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartypex_table)
1909 unsigned int ui = 1;
1911 return *
reinterpret_cast<unsigned char*
>(&ui) == 1;
1918 if (
sizeof(
wchar_t) == 2)
1926 #define PUGI__SCANCHAR(ch) { if (offset >= size || data[offset] != ch) return false; offset++; }
1927 #define PUGI__SCANCHARTYPE(ct) { while (offset < size && PUGI__IS_CHARTYPE(data[offset], ct)) offset++; }
1930 if (size < 6 || !((data[0] ==
'<') & (data[1] ==
'?') & (data[2] ==
'x') & (data[3] ==
'm') & (data[4] ==
'l') &&
PUGI__IS_CHARTYPE(data[5],
ct_space)))
1934 for (
size_t i = 6; i + 1 < size; ++i)
1940 if (data[i] ==
'e' && data[i + 1] ==
'n')
1954 uint8_t delimiter = (offset < size && data[offset] ==
'"') ?
'"' :
'\'';
1958 size_t start = offset;
1960 out_encoding = data + offset;
1964 out_length = offset - start;
1974 #undef PUGI__SCANCHAR
1975 #undef PUGI__SCANCHARTYPE
1981 if (size < 4)
return encoding_utf8;
1983 uint8_t d0 = data[0], d1 = data[1], d2 = data[2], d3 = data[3];
1986 if (d0 == 0 && d1 == 0 && d2 == 0xfe && d3 == 0xff)
return encoding_utf32_be;
1987 if (d0 == 0xff && d1 == 0xfe && d2 == 0 && d3 == 0)
return encoding_utf32_le;
1988 if (d0 == 0xfe && d1 == 0xff)
return encoding_utf16_be;
1989 if (d0 == 0xff && d1 == 0xfe)
return encoding_utf16_le;
1990 if (d0 == 0xef && d1 == 0xbb && d2 == 0xbf)
return encoding_utf8;
1993 if (d0 == 0 && d1 == 0 && d2 == 0 && d3 == 0x3c)
return encoding_utf32_be;
1994 if (d0 == 0x3c && d1 == 0 && d2 == 0 && d3 == 0)
return encoding_utf32_le;
1995 if (d0 == 0 && d1 == 0x3c && d2 == 0 && d3 == 0x3f)
return encoding_utf16_be;
1996 if (d0 == 0x3c && d1 == 0 && d2 == 0x3f && d3 == 0)
return encoding_utf16_le;
1999 if (d0 == 0 && d1 == 0x3c)
return encoding_utf16_be;
2000 if (d0 == 0x3c && d1 == 0)
return encoding_utf16_le;
2003 const uint8_t* enc = 0;
2004 size_t enc_length = 0;
2009 if (enc_length == 10
2010 && (enc[0] |
' ') ==
'i' && (enc[1] |
' ') ==
's' && (enc[2] |
' ') ==
'o'
2011 && enc[3] ==
'-' && enc[4] ==
'8' && enc[5] ==
'8' && enc[6] ==
'5' && enc[7] ==
'9'
2012 && enc[8] ==
'-' && enc[9] ==
'1')
2013 return encoding_latin1;
2017 && (enc[0] |
' ') ==
'l' && (enc[1] |
' ') ==
'a' && (enc[2] |
' ') ==
't'
2018 && (enc[3] |
' ') ==
'i' && (enc[4] |
' ') ==
'n'
2020 return encoding_latin1;
2023 return encoding_utf8;
2032 if (encoding == encoding_utf16)
return is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
2035 if (encoding == encoding_utf32)
return is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
2038 if (encoding != encoding_auto)
return encoding;
2041 const uint8_t* data =
static_cast<const uint8_t*
>(contents);
2048 size_t length = size /
sizeof(char_t);
2052 out_buffer =
static_cast<char_t*
>(
const_cast<void*
>(contents));
2053 out_length = length;
2058 if (!buffer)
return false;
2061 memcpy(buffer, contents, length *
sizeof(char_t));
2063 assert(length == 0);
2067 out_buffer = buffer;
2068 out_length = length + 1;
2074#ifdef PUGIXML_WCHAR_MODE
2075 PUGI__FN bool need_endian_swap_utf(xml_encoding le, xml_encoding re)
2081 PUGI__FN bool convert_buffer_endian_swap(char_t*& out_buffer,
size_t& out_length,
const void* contents,
size_t size,
bool is_mutable)
2083 const char_t* data =
static_cast<const char_t*
>(contents);
2084 size_t length = size /
sizeof(char_t);
2088 char_t* buffer =
const_cast<char_t*
>(data);
2090 convert_wchar_endian_swap(buffer, data, length);
2092 out_buffer = buffer;
2093 out_length = length;
2098 if (!buffer)
return false;
2100 convert_wchar_endian_swap(buffer, data, length);
2103 out_buffer = buffer;
2104 out_length = length + 1;
2112 const typename D::type* data =
static_cast<const typename D::type*
>(contents);
2113 size_t data_length = size /
sizeof(
typename D::type);
2116 size_t length = D::process(data, data_length, 0,
wchar_counter());
2120 if (!buffer)
return false;
2123 wchar_writer::value_type obegin =
reinterpret_cast<wchar_writer::value_type
>(buffer);
2124 wchar_writer::value_type oend = D::process(data, data_length, obegin,
wchar_writer());
2126 assert(oend == obegin + length);
2129 out_buffer = buffer;
2130 out_length = length + 1;
2135 PUGI__FN bool convert_buffer(char_t*& out_buffer,
size_t& out_length, xml_encoding encoding,
const void* contents,
size_t size,
bool is_mutable)
2141 if (encoding == wchar_encoding)
2145 if (need_endian_swap_utf(encoding, wchar_encoding))
2146 return convert_buffer_endian_swap(out_buffer, out_length, contents, size, is_mutable);
2149 if (encoding == encoding_utf8)
2153 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
2157 return (native_encoding == encoding) ?
2163 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
2167 return (native_encoding == encoding) ?
2173 if (encoding == encoding_latin1)
2176 assert(
false &&
"Invalid encoding");
2182 const typename D::type* data =
static_cast<const typename D::type*
>(contents);
2183 size_t data_length = size /
sizeof(
typename D::type);
2186 size_t length = D::process(data, data_length, 0,
utf8_counter());
2190 if (!buffer)
return false;
2193 uint8_t* obegin =
reinterpret_cast<uint8_t*
>(buffer);
2194 uint8_t* oend = D::process(data, data_length, obegin,
utf8_writer());
2196 assert(oend == obegin + length);
2199 out_buffer = buffer;
2200 out_length = length + 1;
2207 for (
size_t i = 0; i < size; ++i)
2216 const uint8_t* data =
static_cast<const uint8_t*
>(contents);
2217 size_t data_length = size;
2221 assert(prefix_length <= data_length);
2223 const uint8_t* postfix = data + prefix_length;
2224 size_t postfix_length = data_length - prefix_length;
2227 if (postfix_length == 0)
return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable);
2234 if (!buffer)
return false;
2237 memcpy(buffer, data, prefix_length);
2239 uint8_t* obegin =
reinterpret_cast<uint8_t*
>(buffer);
2242 assert(oend == obegin + length);
2245 out_buffer = buffer;
2246 out_length = length + 1;
2251 PUGI__FN bool convert_buffer(char_t*& out_buffer,
size_t& out_length, xml_encoding encoding,
const void* contents,
size_t size,
bool is_mutable)
2254 if (encoding == encoding_utf8)
2258 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
2260 xml_encoding native_encoding =
is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
2262 return (native_encoding == encoding) ?
2268 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
2270 xml_encoding native_encoding =
is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
2272 return (native_encoding == encoding) ?
2278 if (encoding == encoding_latin1)
2281 assert(
false &&
"Invalid encoding");
2295 uint8_t* begin =
reinterpret_cast<uint8_t*
>(buffer);
2298 assert(begin + size == end);
2303#ifndef PUGIXML_NO_STL
2311 result.resize(size);
2314 if (size > 0)
as_utf8_end(&result[0], size, str, length);
2321 const uint8_t* data =
reinterpret_cast<const uint8_t*
>(str);
2327 std::basic_string<wchar_t> result;
2328 result.resize(length);
2333 wchar_writer::value_type begin =
reinterpret_cast<wchar_writer::value_type
>(&result[0]);
2336 assert(begin + length == end);
2344 template <
typename Header>
2350 size_t target_length =
strlength(target);
2353 if ((header & header_mask) == 0)
return target_length >= length;
2356 const size_t reuse_threshold = 32;
2358 return target_length >= length && (target_length < reuse_threshold || target_length - length < target_length / 2);
2361 template <
typename String,
typename Header>
2364 if (source_length == 0)
2373 header &= ~header_mask;
2380 memcpy(dest, source, source_length *
sizeof(char_t));
2381 dest[source_length] = 0;
2389 if (!alloc->
reserve())
return false;
2393 if (!buf)
return false;
2396 memcpy(buf, source, source_length *
sizeof(char_t));
2397 buf[source_length] = 0;
2404 header |= header_mask;
2421 void push(char_t*& s,
size_t count)
2427 memmove(
end -
size,
end,
reinterpret_cast<char*
>(s) -
reinterpret_cast<char*
>(
end));
2444 memmove(
end -
size,
end,
reinterpret_cast<char*
>(s) -
reinterpret_cast<char*
>(
end));
2454 char_t* stre = s + 1;
2460 unsigned int ucsc = 0;
2468 if (ch ==
';')
return stre;
2472 if (
static_cast<unsigned int>(ch -
'0') <= 9)
2473 ucsc = 16 * ucsc + (ch -
'0');
2474 else if (
static_cast<unsigned int>((ch |
' ') -
'a') <= 5)
2475 ucsc = 16 * ucsc + ((ch |
' ') -
'a' + 10);
2488 char_t ch = *++stre;
2490 if (ch ==
';')
return stre;
2494 if (
static_cast<unsigned int>(ch -
'0') <= 9)
2495 ucsc = 10 * ucsc + (ch -
'0');
2507 #ifdef PUGIXML_WCHAR_MODE
2508 s =
reinterpret_cast<char_t*
>(wchar_writer::any(
reinterpret_cast<wchar_writer::value_type
>(s), ucsc));
2510 s =
reinterpret_cast<char_t*
>(
utf8_writer::any(
reinterpret_cast<uint8_t*
>(s), ucsc));
2513 g.
push(s, stre - s);
2523 if (*++stre ==
'p' && *++stre ==
';')
2528 g.
push(s, stre - s);
2532 else if (*stre ==
'p')
2534 if (*++stre ==
'o' && *++stre ==
's' && *++stre ==
';')
2539 g.
push(s, stre - s);
2548 if (*++stre ==
't' && *++stre ==
';')
2553 g.
push(s, stre - s);
2561 if (*++stre ==
't' && *++stre ==
';')
2566 g.
push(s, stre - s);
2574 if (*++stre ==
'u' && *++stre ==
'o' && *++stre ==
't' && *++stre ==
';')
2579 g.
push(s, stre - s);
2593 #define PUGI__ENDSWITH(c, e) ((c) == (e) || ((c) == 0 && endch == (e)))
2594 #define PUGI__SKIPWS() { while (PUGI__IS_CHARTYPE(*s, ct_space)) ++s; }
2595 #define PUGI__OPTSET(OPT) ( optmsk & (OPT) )
2596 #define PUGI__PUSHNODE(TYPE) { cursor = append_new_node(cursor, *alloc, TYPE); if (!cursor) PUGI__THROW_ERROR(status_out_of_memory, s); }
2597 #define PUGI__POPNODE() { cursor = cursor->parent; }
2598 #define PUGI__SCANFOR(X) { while (*s != 0 && !(X)) ++s; }
2599 #define PUGI__SCANWHILE(X) { while (X) ++s; }
2600 #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; } }
2601 #define PUGI__ENDSEG() { ch = *s; *s = 0; ++s; }
2602 #define PUGI__THROW_ERROR(err, m) return error_offset = m, error_status = err, static_cast<char_t*>(0)
2603 #define PUGI__CHECK_ERROR(err, m) { if (*s == 0) PUGI__THROW_ERROR(err, m); }
2617 if (*s ==
'\n') g.
push(s, 1);
2619 else if (s[0] ==
'-' && s[1] ==
'-' &&
PUGI__ENDSWITH(s[2],
'>'))
2623 return s + (s[2] ==
'>' ? 3 : 2);
2645 if (*s ==
'\n') g.
push(s, 1);
2647 else if (s[0] ==
']' && s[1] ==
']' &&
PUGI__ENDSWITH(s[2],
'>'))
2661 typedef char_t* (*strconv_pcdata_t)(char_t*);
2677 char_t* end = g.
flush(s);
2679 if (opt_trim::value)
2687 else if (opt_eol::value && *s ==
'\r')
2691 if (*s ==
'\n') g.
push(s, 1);
2693 else if (opt_escape::value && *s ==
'&')
2699 char_t* end = g.
flush(s);
2701 if (opt_trim::value)
2716 PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_trim_pcdata == 0x0800);
2718 switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4))
2728 default: assert(
false);
return 0;
2732 typedef char_t* (*strconv_attribute_t)(char_t*, char_t);
2755 if (*s == end_quote)
2757 char_t* str = g.
flush(s);
2770 char_t* str = s + 1;
2776 else if (opt_escape::value && *s ==
'&')
2796 if (*s == end_quote)
2808 if (*s ==
'\n') g.
push(s, 1);
2812 else if (opt_escape::value && *s ==
'&')
2832 if (*s == end_quote)
2838 else if (*s ==
'\r')
2842 if (*s ==
'\n') g.
push(s, 1);
2844 else if (opt_escape::value && *s ==
'&')
2864 if (*s == end_quote)
2870 else if (opt_escape::value && *s ==
'&')
2885 PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80);
2887 switch ((optmask >> 4) & 15)
2905 default: assert(
false);
return 0;
2911 xml_parse_result result;
2912 result.status = status;
2913 result.offset = offset;
2937 if (*s ==
'"' || *s ==
'\'')
2946 else if (s[0] ==
'<' && s[1] ==
'?')
2955 else if (s[0] ==
'<' && s[1] ==
'!' && s[2] ==
'-' && s[3] ==
'-')
2972 assert(s[0] ==
'<' && s[1] ==
'!' && s[2] ==
'[');
2977 if (s[0] ==
'<' && s[1] ==
'!' && s[2] ==
'[')
2983 else if (s[0] ==
']' && s[1] ==
']' && s[2] ==
'>')
3003 assert((s[0] ==
'<' || s[0] == 0) && s[1] ==
'!');
3008 if (s[0] ==
'<' && s[1] ==
'!' && s[2] !=
'-')
3023 else if (s[0] ==
'<' || s[0] ==
'"' || s[0] ==
'\'')
3079 s += (s[2] ==
'>' ? 3 : 2);
3087 if (*++s==
'C' && *++s==
'D' && *++s==
'A' && *++s==
'T' && *++s==
'A' && *++s ==
'[')
3120 s += (s[1] ==
'>' ? 2 : 1);
3124 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'))
3130 char_t* mark = s + 9;
3135 assert((*s == 0 && endch ==
'>') || *s ==
'>');
3144 cursor->value = mark;
3172 bool declaration = (target[0] |
' ') ==
'x' && (target[1] |
' ') ==
'm' && (target[2] |
' ') ==
'l' && target + 3 == s;
3188 cursor->name = target;
3222 cursor->value = value;
3239 s += (s[1] ==
'>' ? 2 : 1);
3243 ref_cursor = cursor;
3306 if (*s ==
'"' || *s ==
'\'')
3312 s = strconv_attribute(s, ch);
3335 else if (*s == 0 && endch ==
'>')
3348 else if (*s == 0 && endch ==
'>')
3380 char_t* name = cursor->name;
3390 if (*s == 0 && name[0] == endch && name[1] == 0)
PUGI__THROW_ERROR(status_bad_end_element, s);
3414 if (
PUGI__NODETYPE(cursor) == node_declaration)
goto LOC_ATTRIBUTES;
3430 if (*s ==
'<' || !*s)
3441 if (s[0] !=
'<' || s[1] !=
'/' || cursor->first_child)
continue;
3450 if (
PUGI__OPTSET(parse_embed_pcdata) && cursor->parent && !cursor->first_child && !cursor->value)
3463 s = strconv_pcdata(s);
3486 #ifdef PUGIXML_WCHAR_MODE
3489 unsigned int bom = 0xfeff;
3490 return (s[0] ==
static_cast<wchar_t>(bom)) ? s + 1 : s;
3495 return (s[0] ==
'\xef' && s[1] ==
'\xbb' && s[2] ==
'\xbf') ? s + 3 : s;
3505 node = node->next_sibling;
3518 xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c + 0 : 0;
3524 char_t endch = buffer[length - 1];
3525 buffer[length - 1] = 0;
3531 parser.
parse_tree(buffer_data, root, optmsk, endch);
3534 assert(result.offset >= 0 &&
static_cast<size_t>(result.offset) <= length);
3543 xml_node_struct* first_root_child_parsed = last_root_child ? last_root_child->next_sibling + 0 : root->first_child+ 0;
3551 if (result.offset > 0 &&
static_cast<size_t>(result.offset) == length - 1 && endch == 0)
3562 #ifdef PUGIXML_WCHAR_MODE
3565 return encoding_utf8;
3575 if (encoding == encoding_utf16)
return is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
3578 if (encoding == encoding_utf32)
return is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
3581 if (encoding != encoding_auto)
return encoding;
3584 return encoding_utf8;
3591 typename T::value_type end = D::process(
reinterpret_cast<const typename D::type*
>(data), length, dest, T());
3593 return static_cast<size_t>(end - dest) *
sizeof(*dest);
3600 typename T::value_type end = D::process(
reinterpret_cast<const typename D::type*
>(data), length, dest, T());
3604 for (
typename T::value_type i = dest; i != end; ++i)
3608 return static_cast<size_t>(end - dest) *
sizeof(*dest);
3611#ifdef PUGIXML_WCHAR_MODE
3614 if (length < 1)
return 0;
3617 return (
sizeof(
wchar_t) == 2 &&
static_cast<unsigned int>(
static_cast<uint16_t
>(data[length - 1]) - 0xD800) < 0x400) ? length - 1 : length;
3620 PUGI__FN size_t convert_buffer_output(char_t* r_char, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32,
const char_t* data,
size_t length, xml_encoding encoding)
3625 convert_wchar_endian_swap(r_char, data, length);
3627 return length *
sizeof(char_t);
3631 if (encoding == encoding_utf8)
3635 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
3643 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
3651 if (encoding == encoding_latin1)
3654 assert(
false &&
"Invalid encoding");
3660 if (length < 5)
return 0;
3662 for (
size_t i = 1; i <= 4; ++i)
3664 uint8_t ch =
static_cast<uint8_t
>(data[length - i]);
3667 if ((ch & 0xc0) != 0x80)
return length - i;
3676 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
3678 xml_encoding native_encoding =
is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
3683 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
3685 xml_encoding native_encoding =
is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
3690 if (encoding == encoding_latin1)
3693 assert(
false &&
"Invalid encoding");
3716 void flush(
const char_t* data,
size_t size)
3718 if (size == 0)
return;
3722 writer.write(data, size *
sizeof(char_t));
3727 assert(result <=
sizeof(
scratch));
3745 writer.write(data, length *
sizeof(char_t));
3758 flush(data, chunk_size);
3762 length -= chunk_size;
3779 memcpy(
buffer + offset, data, length *
sizeof(char_t));
3794 buffer[offset++] = *data++;
3804 size_t length = offset -
bufsize;
3832 void write(char_t d0, char_t d1, char_t d2)
3843 void write(char_t d0, char_t d1, char_t d2, char_t d3)
3855 void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4)
3868 void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4, char_t d5)
3888 #ifdef PUGIXML_MEMORY_OUTPUT_STACK
3889 PUGIXML_MEMORY_OUTPUT_STACK
3916 const char_t* prev = s;
3921 writer.
write_buffer(prev,
static_cast<size_t>(s - prev));
3927 writer.
write(
'&',
'a',
'm',
'p',
';');
3931 writer.
write(
'&',
'l',
't',
';');
3935 writer.
write(
'&',
'g',
't',
';');
3939 writer.
write(
'&',
'q',
'u',
'o',
't',
';');
3944 unsigned int ch =
static_cast<unsigned int>(*s++);
3947 writer.
write(
'&',
'#',
static_cast<char_t
>((ch / 10) +
'0'),
static_cast<char_t
>((ch % 10) +
'0'),
';');
3955 if (flags & format_no_escapes)
3965 writer.
write(
'<',
'!',
'[',
'C',
'D');
3966 writer.
write(
'A',
'T',
'A',
'[');
3968 const char_t* prev = s;
3971 while (*s && !(s[0] ==
']' && s[1] ==
']' && s[2] ==
'>')) ++s;
3976 writer.
write_buffer(prev,
static_cast<size_t>(s - prev));
3978 writer.
write(
']',
']',
'>');
3985 switch (indent_length)
3989 for (
unsigned int i = 0; i < depth; ++i)
3990 writer.
write(indent[0]);
3996 for (
unsigned int i = 0; i < depth; ++i)
3997 writer.
write(indent[0], indent[1]);
4003 for (
unsigned int i = 0; i < depth; ++i)
4004 writer.
write(indent[0], indent[1], indent[2]);
4010 for (
unsigned int i = 0; i < depth; ++i)
4011 writer.
write(indent[0], indent[1], indent[2], indent[3]);
4017 for (
unsigned int i = 0; i < depth; ++i)
4025 writer.
write(
'<',
'!',
'-',
'-');
4029 const char_t* prev = s;
4032 while (*s && !(s[0] ==
'-' && (s[1] ==
'-' || s[1] == 0))) ++s;
4034 writer.
write_buffer(prev,
static_cast<size_t>(s - prev));
4040 writer.
write(
'-',
' ');
4045 writer.
write(
'-',
'-',
'>');
4052 const char_t* prev = s;
4055 while (*s && !(s[0] ==
'?' && s[1] ==
'>')) ++s;
4057 writer.
write_buffer(prev,
static_cast<size_t>(s - prev));
4061 assert(s[0] ==
'?' && s[1] ==
'>');
4063 writer.
write(
'?',
' ',
'>');
4071 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4073 for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute)
4075 if ((flags & (format_indent_attributes | format_raw)) == format_indent_attributes)
4086 writer.
write_string(a->name ? a->name + 0 : default_name);
4087 writer.
write(
'=',
'"');
4098 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4099 const char_t* name = node->name ? node->name + 0 : default_name;
4104 if (node->first_attribute)
4110 if (!node->first_child)
4112 if (flags & format_no_empty_element_tags)
4114 writer.
write(
'>',
'<',
'/');
4122 if ((flags & format_raw) == 0)
4125 writer.
write(
'/',
'>');
4143 if (!node->first_child)
4145 writer.
write(
'<',
'/');
4160 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4161 const char_t* name = node->name ? node->name + 0 : default_name;
4163 writer.
write(
'<',
'/');
4170 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4187 writer.
write(
'<',
'?');
4188 writer.
write_string(node->name ? node->name + 0 : default_name);
4196 writer.
write(
'?',
'>');
4199 case node_declaration:
4200 writer.
write(
'<',
'?');
4201 writer.
write_string(node->name ? node->name + 0 : default_name);
4203 writer.
write(
'?',
'>');
4207 writer.
write(
'<',
'!',
'D',
'O',
'C');
4208 writer.
write(
'T',
'Y',
'P',
'E');
4220 assert(
false &&
"Invalid node type");
4232 size_t indent_length = ((flags & (format_indent | format_indent_attributes)) && (flags & format_raw) == 0) ?
strlength(indent) : 0;
4250 if ((indent_flags &
indent_newline) && (flags & format_raw) == 0)
4266 node = node->first_child;
4275 if (node->first_child)
4277 node = node->first_child;
4290 while (node != root)
4292 if (node->next_sibling)
4294 node = node->next_sibling;
4298 node = node->parent;
4305 if ((indent_flags &
indent_newline) && (flags & format_raw) == 0)
4317 while (node != root);
4319 if ((indent_flags &
indent_newline) && (flags & format_raw) == 0)
4325 for (
xml_node_struct* child = node->first_child; child; child = child->next_sibling)
4329 if (type == node_declaration)
return true;
4330 if (type == node_element)
return false;
4338 for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute)
4347 return parent == node_element || parent == node_declaration;
4352 if (parent != node_document && parent != node_element)
return false;
4353 if (child == node_document || child == node_null)
return false;
4354 if (parent != node_document && (child == node_declaration || child == node_doctype))
return false;
4366 if (parent.root() != child.root())
4370 xml_node cur = parent;
4383 template <
typename String,
typename Header>
4386 assert(!dest && (header & header_mask) == 0);
4390 if (alloc && (source_header & header_mask) == 0)
4408 for (xml_attribute_struct* sa =
sn->first_attribute; sa; sa = sa->next_attribute)
4430 while (sit && sit !=
sn)
4441 if (sit->first_child)
4444 sit = sit->first_child;
4453 if (sit->next_sibling)
4455 sit = sit->next_sibling;
4479 return type == node_pcdata || type == node_cdata;
4486 const char_t* s = value;
4491 bool negative = (*s ==
'-');
4493 s += (*s ==
'+' || *s ==
'-');
4495 bool overflow =
false;
4497 if (s[0] ==
'0' && (s[1] |
' ') ==
'x')
4505 const char_t* start = s;
4509 if (
static_cast<unsigned>(*s -
'0') < 10)
4510 result = result * 16 + (*s -
'0');
4511 else if (
static_cast<unsigned>((*s |
' ') -
'a') < 6)
4512 result = result * 16 + ((*s |
' ') -
'a' + 10);
4519 size_t digits =
static_cast<size_t>(s - start);
4521 overflow = digits >
sizeof(U) * 2;
4529 const char_t* start = s;
4533 if (
static_cast<unsigned>(*s -
'0') < 10)
4534 result = result * 10 + (*s -
'0');
4541 size_t digits =
static_cast<size_t>(s - start);
4545 const size_t max_digits10 =
sizeof(U) == 8 ? 20 :
sizeof(U) == 4 ? 10 : 5;
4546 const char_t max_lead =
sizeof(U) == 8 ?
'1' :
sizeof(U) == 4 ?
'4' :
'6';
4547 const size_t high_bit =
sizeof(U) * 8 - 1;
4549 overflow = digits >= max_digits10 && !(digits == max_digits10 && (*start < max_lead || (*start == max_lead && result >> high_bit)));
4556 return (overflow || result > ~minv + 1) ? minv : ~result + 1;
4558 return (overflow || result > 0 - minv) ? minv : 0 - result;
4562 return (overflow || result > maxv) ? maxv : result;
4567 return string_to_integer<unsigned int>(value,
static_cast<unsigned int>(INT_MIN), INT_MAX);
4572 return string_to_integer<unsigned int>(value, 0, UINT_MAX);
4577 #ifdef PUGIXML_WCHAR_MODE
4578 return wcstod(value, 0);
4580 return strtod(value, 0);
4586 #ifdef PUGIXML_WCHAR_MODE
4587 return static_cast<float>(wcstod(value, 0));
4589 return static_cast<float>(strtod(value, 0));
4596 char_t first = *value;
4599 return (first ==
'1' || first ==
't' || first ==
'T' || first ==
'y' || first ==
'Y');
4602#ifdef PUGIXML_HAS_LONG_LONG
4603 PUGI__FN long long get_value_llong(
const char_t* value)
4605 return string_to_integer<unsigned long long>(value,
static_cast<unsigned long long>(LLONG_MIN), LLONG_MAX);
4608 PUGI__FN unsigned long long get_value_ullong(
const char_t* value)
4610 return string_to_integer<unsigned long long>(value, 0, ULLONG_MAX);
4616 char_t* result = end - 1;
4617 U rest = negative ? 0 - value : value;
4621 *result-- =
static_cast<char_t
>(
'0' + (rest % 10));
4626 assert(result >= begin);
4631 return result + !negative;
4635 template <
typename String,
typename Header>
4638 #ifdef PUGIXML_WCHAR_MODE
4640 assert(strlen(buf) <
sizeof(wbuf) /
sizeof(wbuf[0]));
4643 for (; buf[offset]; ++offset) wbuf[offset] = buf[offset];
4645 return strcpy_insitu(dest, header, header_mask, wbuf, offset);
4647 return strcpy_insitu(dest, header, header_mask, buf, strlen(buf));
4651 template <
typename U,
typename String,
typename Header>
4655 char_t* end = buf +
sizeof(buf) /
sizeof(buf[0]);
4658 return strcpy_insitu(dest, header, header_mask, begin, end - begin);
4661 template <
typename String,
typename Header>
4670 template <
typename String,
typename Header>
4679 template <
typename String,
typename Header>
4691 xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size);
4697 if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable))
return impl::make_parse_result(status_out_of_memory);
4700 if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents);
4703 if (own || buffer != contents) *out_buffer = buffer;
4709 xml_parse_result res = impl::xml_parser::parse(buffer, length, doc, root, options);
4712 res.encoding = buffer_encoding;
4720 #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE)
4722 typedef __int64 length_type;
4724 _fseeki64(file, 0, SEEK_END);
4725 length_type length = _ftelli64(file);
4726 _fseeki64(file, 0, SEEK_SET);
4727 #elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))
4729 typedef off64_t length_type;
4731 fseeko64(file, 0, SEEK_END);
4732 length_type length = ftello64(file);
4733 fseeko64(file, 0, SEEK_SET);
4736 typedef long length_type;
4738 fseek(file, 0, SEEK_END);
4739 length_type length = ftell(file);
4740 fseek(file, 0, SEEK_SET);
4744 if (length < 0)
return status_io_error;
4747 size_t result =
static_cast<size_t>(length);
4749 if (
static_cast<length_type
>(result) != length)
return status_out_of_memory;
4752 out_result = result;
4761 #ifdef PUGIXML_WCHAR_MODE
4764 if (encoding == wchar_encoding || need_endian_swap_utf(encoding, wchar_encoding))
4766 size_t length = size /
sizeof(char_t);
4768 static_cast<char_t*
>(buffer)[length] = 0;
4769 return (length + 1) *
sizeof(char_t);
4772 if (encoding == encoding_utf8)
4774 static_cast<char*
>(buffer)[size] = 0;
4791 size_t max_suffix_size =
sizeof(char_t);
4798 size_t read_size = fread(contents, 1, size, file);
4800 if (read_size != size)
4808 return load_buffer_impl(doc, doc, contents,
zero_terminate_buffer(contents, size, real_encoding), options, real_encoding,
true,
true, out_buffer);
4816#ifndef PUGIXML_NO_STL
4822 if (!memory)
return 0;
4858 while (!stream.eof())
4862 if (!chunk)
return status_out_of_memory;
4865 if (last) last = last->
next = chunk;
4866 else chunks.
data = last = chunk;
4869 stream.read(chunk->
data,
static_cast<std::streamsize
>(
sizeof(chunk->
data) /
sizeof(T)));
4870 chunk->
size =
static_cast<size_t>(stream.gcount()) *
sizeof(T);
4873 if (stream.bad() || (!stream.eof() && stream.fail()))
return status_io_error;
4876 if (total + chunk->
size < total)
return status_out_of_memory;
4877 total += chunk->
size;
4880 size_t max_suffix_size =
sizeof(char_t);
4884 if (!buffer)
return status_out_of_memory;
4886 char* write = buffer;
4890 assert(write + chunk->size <= buffer + total);
4891 memcpy(write, chunk->data, chunk->size);
4892 write += chunk->size;
4895 assert(write == buffer + total);
4898 *out_buffer = buffer;
4907 typename std::basic_istream<T>::pos_type pos = stream.tellg();
4908 stream.seekg(0, std::ios::end);
4909 std::streamoff length = stream.tellg() - pos;
4912 if (stream.fail() || pos < 0)
return status_io_error;
4915 size_t read_length =
static_cast<size_t>(length);
4917 if (
static_cast<std::streamsize
>(read_length) != length || length < 0)
return status_out_of_memory;
4919 size_t max_suffix_size =
sizeof(char_t);
4923 if (!buffer.
data)
return status_out_of_memory;
4925 stream.read(
static_cast<T*
>(buffer.
data),
static_cast<std::streamsize
>(read_length));
4928 if (stream.bad() || (!stream.eof() && stream.fail()))
return status_io_error;
4931 size_t actual_length =
static_cast<size_t>(stream.gcount());
4932 assert(actual_length <= read_length);
4934 *out_buffer = buffer.
release();
4935 *out_size = actual_length *
sizeof(T);
4944 xml_parse_status status = status_ok;
4950 if (stream.tellg() < 0)
4962 return load_buffer_impl(doc, doc, buffer,
zero_terminate_buffer(buffer, size, real_encoding), options, real_encoding,
true,
true, out_buffer);
4966#if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR)))
4969 return _wfopen(path, mode);
4982 if (!result)
return 0;
4997 if (!path_utf8)
return 0;
5000 char mode_ascii[4] = {0};
5001 for (
size_t i = 0; mode[i]; ++i) mode_ascii[i] =
static_cast<char>(mode[i]);
5004 FILE* result = fopen(path_utf8, mode_ascii);
5013 PUGI__FN bool save_file_impl(
const xml_document& doc, FILE* file,
const char_t* indent,
unsigned int flags, xml_encoding encoding)
5015 if (!file)
return false;
5017 xml_writer_file writer(file);
5018 doc.save(writer, indent, flags, encoding);
5020 return ferror(file) == 0;
5048 size_t result = fwrite(data, 1, size,
static_cast<FILE*
>(
file));
5052#ifndef PUGIXML_NO_STL
5066 narrow_stream->write(
reinterpret_cast<const char*
>(data),
static_cast<std::streamsize
>(size));
5071 assert(size %
sizeof(
wchar_t) == 0);
5073 wide_stream->write(
reinterpret_cast<const wchar_t*
>(data),
static_cast<std::streamsize
>(size /
sizeof(
wchar_t)));
5193#ifdef PUGIXML_HAS_LONG_LONG
5194 PUGI__FN long long xml_attribute::as_llong(
long long def)
const
5199 PUGI__FN unsigned long long xml_attribute::as_ullong(
unsigned long long def)
const
5278#ifdef PUGIXML_HAS_LONG_LONG
5294 if (!
_attr)
return false;
5296 return impl::strcpy_insitu(
_attr->
name,
_attr->
header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
5301 if (!
_attr)
return false;
5303 return impl::strcpy_insitu(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs));
5308 if (!
_attr)
return false;
5310 return impl::set_value_integer<unsigned int>(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5315 if (!
_attr)
return false;
5317 return impl::set_value_integer<unsigned int>(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs,
false);
5322 if (!
_attr)
return false;
5324 return impl::set_value_integer<unsigned long>(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5329 if (!
_attr)
return false;
5331 return impl::set_value_integer<unsigned long>(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs,
false);
5336 if (!
_attr)
return false;
5338 return impl::set_value_convert(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs);
5343 if (!
_attr)
return false;
5345 return impl::set_value_convert(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs);
5350 if (!
_attr)
return false;
5352 return impl::set_value_bool(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs);
5355#ifdef PUGIXML_HAS_LONG_LONG
5358 if (!
_attr)
return false;
5360 return impl::set_value_integer<unsigned long long>(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5365 if (!
_attr)
return false;
5367 return impl::set_value_integer<unsigned long long>(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs,
false);
5372 PUGI__FN bool operator&&(
const xml_attribute& lhs,
bool rhs)
5374 return (
bool)lhs && rhs;
5377 PUGI__FN bool operator||(
const xml_attribute& lhs,
bool rhs)
5379 return (
bool)lhs || rhs;
5495 if (i->name && impl::strequal(name_, i->name))
return xml_node(i);
5505 if (i->name && impl::strequal(name_, i->name))
5516 if (i->name && impl::strequal(name_, i->name))
return xml_node(i);
5531 if (i->name && impl::strequal(name_, i->name))
return xml_node(i);
5541 assert(!hint || (
_root && impl::is_attribute_of(hint,
_root)));
5547 if (i->name && impl::strequal(name_, i->name))
5558 if (j->name && impl::strequal(name_, j->name))
5601 if (impl::is_text_node(i) && i->value)
5639 return impl::strcpy_insitu(
_root->
name,
_root->
header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
5649 return impl::strcpy_insitu(
_root->
value,
_root->
header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs));
5656 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5673 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5691 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5709 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5727 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5734 impl::node_copy_attribute(a.
_attr, proto.
_attr);
5744 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5751 impl::node_copy_attribute(a.
_attr, proto.
_attr);
5762 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5769 impl::node_copy_attribute(a.
_attr, proto.
_attr);
5780 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5787 impl::node_copy_attribute(a.
_attr, proto.
_attr);
5794 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5796 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5797 if (!alloc.reserve())
return xml_node();
5799 xml_node n(impl::allocate_node(alloc, type_));
5811 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5813 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5814 if (!alloc.reserve())
return xml_node();
5816 xml_node n(impl::allocate_node(alloc, type_));
5828 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5831 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5832 if (!alloc.reserve())
return xml_node();
5834 xml_node n(impl::allocate_node(alloc, type_));
5837 impl::insert_node_before(n.
_root, node.
_root);
5846 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5849 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5850 if (!alloc.reserve())
return xml_node();
5852 xml_node n(impl::allocate_node(alloc, type_));
5855 impl::insert_node_after(n.
_root, node.
_root);
5901 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5903 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5904 if (!alloc.reserve())
return xml_node();
5906 xml_node n(impl::allocate_node(alloc, type_));
5918 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5920 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5921 if (!alloc.reserve())
return xml_node();
5923 xml_node n(impl::allocate_node(alloc, type_));
5935 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5938 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5939 if (!alloc.reserve())
return xml_node();
5941 xml_node n(impl::allocate_node(alloc, type_));
5944 impl::insert_node_after(n.
_root, node.
_root);
5953 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5956 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5957 if (!alloc.reserve())
return xml_node();
5959 xml_node n(impl::allocate_node(alloc, type_));
5962 impl::insert_node_before(n.
_root, node.
_root);
5970 if (!impl::allow_move(*
this, moved))
return xml_node();
5972 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5973 if (!alloc.reserve())
return xml_node();
5976 impl::get_document(
_root).header |= impl::xml_memory_page_contents_shared_mask;
5978 impl::remove_node(moved.
_root);
5986 if (!impl::allow_move(*
this, moved))
return xml_node();
5988 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5989 if (!alloc.reserve())
return xml_node();
5992 impl::get_document(
_root).header |= impl::xml_memory_page_contents_shared_mask;
5994 impl::remove_node(moved.
_root);
6002 if (!impl::allow_move(*
this, moved))
return xml_node();
6006 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6007 if (!alloc.reserve())
return xml_node();
6010 impl::get_document(
_root).header |= impl::xml_memory_page_contents_shared_mask;
6012 impl::remove_node(moved.
_root);
6013 impl::insert_node_after(moved.
_root, node.
_root);
6020 if (!impl::allow_move(*
this, moved))
return xml_node();
6024 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6025 if (!alloc.reserve())
return xml_node();
6028 impl::get_document(
_root).header |= impl::xml_memory_page_contents_shared_mask;
6030 impl::remove_node(moved.
_root);
6031 impl::insert_node_before(moved.
_root, node.
_root);
6044 if (!impl::is_attribute_of(a.
_attr,
_root))
return false;
6046 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6047 if (!alloc.reserve())
return false;
6050 impl::destroy_attribute(a.
_attr, alloc);
6064 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6065 if (!alloc.reserve())
return false;
6067 impl::remove_node(n.
_root);
6068 impl::destroy_node(n.
_root, alloc);
6079 impl::xml_document_struct* doc = &impl::get_document(
_root);
6082 doc->header |= impl::xml_memory_page_contents_shared_mask;
6085 impl::xml_memory_page* page = 0;
6086 impl::xml_extra_buffer* extra =
static_cast<impl::xml_extra_buffer*
>(doc->allocate_memory(
sizeof(impl::xml_extra_buffer) +
sizeof(
void*), page));
6091 #ifdef PUGIXML_COMPACT
6094 extra =
reinterpret_cast<impl::xml_extra_buffer*
>((
reinterpret_cast<uintptr_t
>(extra) + (
sizeof(
void*) - 1)) & ~(
sizeof(
void*) - 1));
6099 extra->next = doc->extra_buffers;
6100 doc->extra_buffers = extra;
6103 impl::name_null_sentry sentry(
_root);
6105 return impl::load_buffer_impl(doc,
_root,
const_cast<void*
>(contents), size, options, encoding,
false,
false, &extra->buffer);
6113 if (i->name && impl::strequal(name_, i->name))
6116 if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 :
PUGIXML_TEXT(
"")))
6129 if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 :
PUGIXML_TEXT(
"")))
6135#ifndef PUGIXML_NO_STL
6144 offset += (i !=
_root);
6145 offset += i->name ? impl::strlength(i->name) : 0;
6149 result.resize(offset);
6154 result[--offset] = delimiter;
6158 size_t length = impl::strlength(j->name);
6161 memcpy(&result[offset], j->name, length *
sizeof(
char_t));
6165 assert(offset == 0);
6175 if (!
_root || !path_[0])
return found;
6177 if (path_[0] == delimiter)
6180 found = found.
root();
6184 const char_t* path_segment = path_;
6186 while (*path_segment == delimiter) ++path_segment;
6188 const char_t* path_segment_end = path_segment;
6190 while (*path_segment_end && *path_segment_end != delimiter) ++path_segment_end;
6192 if (path_segment == path_segment_end)
return found;
6194 const char_t* next_segment = path_segment_end;
6196 while (*next_segment == delimiter) ++next_segment;
6198 if (*path_segment ==
'.' && path_segment + 1 == path_segment_end)
6200 else if (*path_segment ==
'.' && *(path_segment+1) ==
'.' && path_segment + 2 == path_segment_end)
6206 if (j->name && impl::strequalrange(j->name, path_segment,
static_cast<size_t>(path_segment_end - path_segment)))
6210 if (subsearch)
return subsearch;
6223 if (!walker.
begin(arg_begin))
return false;
6234 if (!walker.
for_each(arg_for_each))
6256 while (cur && cur !=
_root);
6259 assert(walker.
_depth == -1);
6262 return walker.
end(arg_end);
6279 impl::xml_buffered_writer buffered_writer(writer, encoding);
6281 impl::node_output(buffered_writer,
_root, indent, flags, depth);
6283 buffered_writer.flush();
6286#ifndef PUGIXML_NO_STL
6291 print(writer, indent, flags, encoding, depth);
6294 PUGI__FN void xml_node::print(std::basic_ostream<
wchar_t, std::char_traits<wchar_t> >& stream,
const char_t* indent,
unsigned int flags,
unsigned int depth)
const
6304 if (!
_root)
return -1;
6306 impl::xml_document_struct& doc = impl::get_document(
_root);
6309 if (!doc.buffer || doc.extra_buffers)
return -1;
6328 assert(
false &&
"Invalid node type");
6336 return (
bool)lhs && rhs;
6339 PUGI__FN bool operator||(
const xml_node& lhs,
bool rhs)
6341 return (
bool)lhs || rhs;
6358 if (impl::is_text_node(node))
6392 return _data() == 0;
6413 return (d && d->
value) ? impl::get_value_int(d->
value) : def;
6420 return (d && d->
value) ? impl::get_value_uint(d->
value) : def;
6427 return (d && d->
value) ? impl::get_value_double(d->
value) : def;
6434 return (d && d->
value) ? impl::get_value_float(d->
value) : def;
6441 return (d && d->
value) ? impl::get_value_bool(d->
value) : def;
6444#ifdef PUGIXML_HAS_LONG_LONG
6445 PUGI__FN long long xml_text::as_llong(
long long def)
const
6449 return (d && d->
value) ? impl::get_value_llong(d->
value) : def;
6452 PUGI__FN unsigned long long xml_text::as_ullong(
unsigned long long def)
const
6456 return (d && d->value) ? impl::get_value_ullong(d->value) : def;
6464 return dn ? impl::strcpy_insitu(dn->
value, dn->
header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)) :
false;
6471 return dn ? impl::set_value_integer<unsigned int>(dn->
value, dn->
header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) :
false;
6478 return dn ? impl::set_value_integer<unsigned int>(dn->
value, dn->
header, impl::xml_memory_page_value_allocated_mask, rhs,
false) :
false;
6485 return dn ? impl::set_value_integer<unsigned long>(dn->
value, dn->
header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) :
false;
6492 return dn ? impl::set_value_integer<unsigned long>(dn->
value, dn->
header, impl::xml_memory_page_value_allocated_mask, rhs,
false) :
false;
6499 return dn ? impl::set_value_convert(dn->
value, dn->
header, impl::xml_memory_page_value_allocated_mask, rhs) :
false;
6506 return dn ? impl::set_value_convert(dn->
value, dn->
header, impl::xml_memory_page_value_allocated_mask, rhs) :
false;
6513 return dn ? impl::set_value_bool(dn->
value, dn->
header, impl::xml_memory_page_value_allocated_mask, rhs) :
false;
6516#ifdef PUGIXML_HAS_LONG_LONG
6521 return dn ? impl::set_value_integer<unsigned long long>(dn->
value, dn->
header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false;
6528 return dn ? impl::set_value_integer<unsigned long long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs,
false) : false;
6580#ifdef PUGIXML_HAS_LONG_LONG
6602 return (
bool)lhs && rhs;
6605 PUGI__FN bool operator||(
const xml_text& lhs,
bool rhs)
6607 return (
bool)lhs || rhs;
6825 case status_bad_pi:
return "Error parsing document declaration/processing instruction";
6839 default:
return "Unknown error";
6853#ifdef PUGIXML_HAS_MOVE
6862 if (
this == &rhs)
return *
this;
6890 #ifdef PUGIXML_COMPACT
6892 const size_t page_offset =
sizeof(
void*);
6894 const size_t page_offset = 0;
6901 impl::xml_memory_page* page = impl::xml_memory_page::construct(
_memory);
6904 page->busy_size = impl::xml_memory_page_size;
6907 #ifdef PUGIXML_COMPACT
6909 page->compact_page_marker =
reinterpret_cast<uint32_t*
>(
static_cast<void*
>(
reinterpret_cast<char*
>(page) +
sizeof(impl::xml_memory_page)));
6910 *page->compact_page_marker =
sizeof(impl::xml_memory_page);
6914 _root =
new (
reinterpret_cast<char*
>(page) +
sizeof(impl::xml_memory_page) + page_offset) impl::xml_document_struct(page);
6918 page->allocator =
static_cast<impl::xml_document_struct*
>(
_root);
6921 #ifdef PUGIXML_COMPACT
6922 page->allocator->_hash = &
static_cast<impl::xml_document_struct*
>(
_root)->hash;
6926 assert(
reinterpret_cast<char*
>(
_root) +
sizeof(impl::xml_document_struct) <=
_memory +
sizeof(
_memory));
6936 impl::xml_memory::deallocate(
_buffer);
6941 for (impl::xml_extra_buffer* extra =
static_cast<impl::xml_document_struct*
>(
_root)->extra_buffers; extra; extra = extra->next)
6943 if (extra->buffer) impl::xml_memory::deallocate(extra->buffer);
6948 assert(root_page && !root_page->prev);
6949 assert(
reinterpret_cast<char*
>(root_page) >=
_memory &&
reinterpret_cast<char*
>(root_page) <
_memory +
sizeof(
_memory));
6951 for (impl::xml_memory_page* page = root_page->
next; page; )
6953 impl::xml_memory_page* next = page->
next;
6955 impl::xml_allocator::deallocate_page(page);
6960 #ifdef PUGIXML_COMPACT
6962 static_cast<impl::xml_document_struct*
>(
_root)->hash.clear();
6968#ifdef PUGIXML_HAS_MOVE
6971 impl::xml_document_struct* doc =
static_cast<impl::xml_document_struct*
>(_root);
6972 impl::xml_document_struct* other =
static_cast<impl::xml_document_struct*
>(rhs._root);
6977 #ifdef PUGIXML_COMPACT
6980 if (other_first_child)
6982 size_t other_children = 0;
6990 if (!other->_hash->reserve(other_children + 1))
6992 #ifdef PUGIXML_NO_EXCEPTIONS
6995 throw std::bad_alloc();
7002 doc->_root = other->_root;
7003 doc->_busy_size = other->_busy_size;
7006 doc->buffer = other->buffer;
7007 doc->extra_buffers = other->extra_buffers;
7008 _buffer = rhs._buffer;
7010 #ifdef PUGIXML_COMPACT
7012 doc->hash = other->hash;
7013 doc->_hash = &doc->hash;
7021 assert(doc_page && !doc_page->prev && !doc_page->next);
7024 assert(other_page && !other_page->prev);
7027 if (impl::xml_memory_page* page = other_page->next)
7029 assert(page->
prev == other_page);
7031 page->
prev = doc_page;
7033 doc_page->
next = page;
7034 other_page->
next = 0;
7038 for (impl::xml_memory_page* page = doc_page->next; page; page = page->
next)
7044 #ifdef PUGIXML_COMPACT
7046 if (page->compact_shared_parent == other)
7047 page->compact_shared_parent = doc;
7052 assert(!doc->first_child);
7054 doc->first_child = other_first_child;
7056 for (
xml_node_struct* node = other_first_child; node; node = node->next_sibling)
7058 #ifdef PUGIXML_COMPACT
7060 assert(node->parent == other || node->parent == doc);
7064 assert(node->parent == other);
7070 new (other) impl::xml_document_struct(
PUGI__GETPAGE(other));
7075#ifndef PUGIXML_NO_STL
7080 return impl::load_stream_impl(
static_cast<impl::xml_document_struct*
>(
_root), stream, options, encoding, &
_buffer);
7094 #ifdef PUGIXML_WCHAR_MODE
7100 return load_buffer(contents, impl::strlength(contents) *
sizeof(
char_t), options, encoding);
7112 using impl::auto_deleter;
7115 return impl::load_file_impl(
static_cast<impl::xml_document_struct*
>(
_root), file.
data, options, encoding, &
_buffer);
7122 using impl::auto_deleter;
7125 return impl::load_file_impl(
static_cast<impl::xml_document_struct*
>(
_root), file.
data, options, encoding, &
_buffer);
7132 return impl::load_buffer_impl(
static_cast<impl::xml_document_struct*
>(
_root),
_root,
const_cast<void*
>(contents), size, options, encoding,
false,
false, &
_buffer);
7139 return impl::load_buffer_impl(
static_cast<impl::xml_document_struct*
>(
_root),
_root, contents, size, options, encoding,
true,
false, &
_buffer);
7146 return impl::load_buffer_impl(
static_cast<impl::xml_document_struct*
>(
_root),
_root, contents, size, options, encoding,
true,
true, &
_buffer);
7151 impl::xml_buffered_writer buffered_writer(writer, encoding);
7156 #ifdef PUGIXML_WCHAR_MODE
7157 unsigned int bom = 0xfeff;
7158 buffered_writer.write(
static_cast<wchar_t>(bom));
7160 buffered_writer.write(
'\xef',
'\xbb',
'\xbf');
7166 buffered_writer.write_string(
PUGIXML_TEXT(
"<?xml version=\"1.0\""));
7168 buffered_writer.write(
'?',
'>');
7169 if (!(flags &
format_raw)) buffered_writer.write(
'\n');
7172 impl::node_output(buffered_writer,
_root, indent, flags, 0);
7174 buffered_writer.flush();
7177#ifndef PUGIXML_NO_STL
7182 save(writer, indent, flags, encoding);
7195 using impl::auto_deleter;
7198 return impl::save_file_impl(*
this, file.
data, indent, flags, encoding);
7203 using impl::auto_deleter;
7206 return impl::save_file_impl(*
this, file.
data, indent, flags, encoding);
7220#ifndef PUGIXML_NO_STL
7225 return impl::as_utf8_impl(str, impl::strlength_wide(str));
7230 return impl::as_utf8_impl(str.c_str(), str.size());
7237 return impl::as_wide_impl(str, strlen(str));
7242 return impl::as_wide_impl(str.c_str(), str.size());
7248 impl::xml_memory::allocate = allocate;
7249 impl::xml_memory::deallocate = deallocate;
7254 return impl::xml_memory::allocate;
7259 return impl::xml_memory::deallocate;
7263#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC))
7269 return std::bidirectional_iterator_tag();
7274 return std::bidirectional_iterator_tag();
7279 return std::bidirectional_iterator_tag();
7284#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC)
7290 return std::bidirectional_iterator_tag();
7295 return std::bidirectional_iterator_tag();
7300 return std::bidirectional_iterator_tag();
7305#ifndef PUGIXML_NO_XPATH
7310 template <
typename T>
bool operator()(
const T& lhs,
const T& rhs)
const
7318 template <
typename T>
bool operator()(
const T& lhs,
const T& rhs)
const
7326 template <
typename T>
bool operator()(
const T& lhs,
const T& rhs)
const
7334 template <
typename T>
bool operator()(
const T& lhs,
const T& rhs)
const
7340 template <
typename T>
void swap(T& lhs, T& rhs)
7347 template <
typename I,
typename Pred> I
min_element(I begin, I end,
const Pred& pred)
7351 for (I it = begin + 1; it != end; ++it)
7352 if (pred(*it, *result))
7358 template <
typename I>
void reverse(I begin, I end)
7360 while (end - begin > 1)
swap(*begin++, *--end);
7363 template <
typename I> I
unique(I begin, I end)
7366 while (end - begin > 1 && *begin != *(begin + 1)) begin++;
7368 if (begin == end)
return begin;
7374 while (begin != end)
7376 if (*begin != *write)
7377 *++write = *begin++;
7386 template <
typename T,
typename Pred>
void insertion_sort(T* begin, T* end,
const Pred& pred)
7391 for (T* it = begin + 1; it != end; ++it)
7397 while (hole > begin && pred(val, *(hole - 1)))
7399 *hole = *(hole - 1);
7408 template <
typename I,
typename Pred> I
median3(I first, I middle, I last,
const Pred& pred)
7410 if (pred(*middle, *first))
swap(middle, first);
7411 if (pred(*last, *middle))
swap(last, middle);
7412 if (pred(*middle, *first))
swap(middle, first);
7417 template <
typename T,
typename Pred>
void partition3(T* begin, T* end, T pivot,
const Pred& pred, T** out_eqbeg, T** out_eqend)
7426 if (pred(*lt, pivot))
7428 else if (*lt == pivot)
7437 for (T* it = begin; it != eq; ++it)
7438 swap(*it, *--eqbeg);
7444 template <
typename I,
typename Pred>
void sort(I begin, I end,
const Pred& pred)
7447 while (end - begin > 16)
7450 I middle = begin + (end - begin) / 2;
7451 I median =
median3(begin, middle, end - 1, pred);
7455 partition3(begin, end, *median, pred, &eqbeg, &eqend);
7458 if (eqbeg - begin > end - eqend)
7460 sort(eqend, end, pred);
7465 sort(begin, eqbeg, pred);
7478 #ifdef PUGIXML_MEMORY_XPATH_PAGE_SIZE
7479 PUGIXML_MEMORY_XPATH_PAGE_SIZE
7523 size_t block_capacity_base =
sizeof(
_root->
data);
7524 size_t block_capacity_req = size + block_capacity_base / 4;
7525 size_t block_capacity = (block_capacity_base > block_capacity_req) ? block_capacity_base : block_capacity_req;
7556 if (ptr &&
_root_size - old_size + new_size <= _root->capacity)
7564 if (!result)
return 0;
7570 assert(new_size >= old_size);
7571 memcpy(result, ptr, old_size);
7598 while (cur != state.
_root)
7684 char_t* result =
static_cast<char_t*
>(alloc->
allocate((
length + 1) *
sizeof(char_t)));
7685 if (!result)
return 0;
7687 memcpy(result,
string,
length *
sizeof(char_t));
7705 assert(begin <= end && *end == 0);
7707 return xpath_string(begin,
true,
static_cast<size_t>(end - begin));
7712 assert(begin <= end);
7717 size_t length =
static_cast<size_t>(end - begin);
7740 size_t target_length =
length();
7741 size_t source_length = o.
length();
7742 size_t result_length = target_length + source_length;
7745 char_t* result =
static_cast<char_t*
>(alloc->
reallocate(
_uses_heap ?
const_cast<char_t*
>(
_buffer) : 0, (target_length + 1) *
sizeof(char_t), (result_length + 1) *
sizeof(char_t)));
7746 if (!result)
return;
7752 memcpy(result + target_length, o.
_buffer, source_length *
sizeof(char_t));
7753 result[result_length] = 0;
7780 if (!data_)
return 0;
7787 return const_cast<char_t*
>(
_buffer);
7815 while (*pattern && *
string == *pattern)
7821 return *pattern == 0;
7826 #ifdef PUGIXML_WCHAR_MODE
7827 return wcschr(s, c);
7829 return strchr(s, c);
7835 #ifdef PUGIXML_WCHAR_MODE
7837 return (*p == 0) ? s : wcsstr(s, p);
7839 return strstr(s, p);
7846 return static_cast<unsigned int>(ch -
'A') < 26 ?
static_cast<char_t
>(ch |
' ') : ch;
7855 xml_node n = na.node();
7874 xml_node cur = n.first_child();
7876 while (cur && cur != n)
7878 if (cur.type() == node_pcdata || cur.type() == node_cdata)
7881 if (cur.first_child())
7882 cur = cur.first_child();
7883 else if (cur.next_sibling())
7884 cur = cur.next_sibling();
7887 while (!cur.next_sibling() && cur != n)
7890 if (cur != n) cur = cur.next_sibling();
7905 assert(ln->parent == rn->parent);
7908 if (!ln->parent)
return ln < rn;
7916 if (ls == rn)
return true;
7917 if (rs == ln)
return false;
7919 ls = ls->next_sibling;
7920 rs = rs->next_sibling;
7933 while (lp && rp && lp->parent != rp->parent)
7943 bool left_higher = !lp;
7958 if (ln == rn)
return left_higher;
7961 while (ln->parent != rn->parent)
7972 while (node && node != parent) node = node->parent;
7974 return parent && node == parent;
7985 if (node->name && (node->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0)
return node->name;
7986 if (node->value && (node->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0)
return node->value;
7992 xml_attribute_struct* attr = xnode.attribute().internal_object();
7998 if ((attr->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0)
return attr->name;
7999 if ((attr->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0)
return attr->value;
8010 bool operator()(
const xpath_node& lhs,
const xpath_node& rhs)
const
8016 if (lo && ro)
return lo < ro;
8019 xml_node ln = lhs.node(), rn = rhs.node();
8022 if (lhs.attribute() && rhs.attribute())
8025 if (lhs.parent() == rhs.parent())
8028 for (xml_attribute a = lhs.attribute(); a; a = a.next_attribute())
8029 if (a == rhs.attribute())
8039 else if (lhs.attribute())
8042 if (lhs.parent() == rhs.node())
return false;
8046 else if (rhs.attribute())
8049 if (rhs.parent() == lhs.node())
return true;
8054 if (ln == rn)
return false;
8056 if (!ln || !rn)
return ln < rn;
8058 return node_is_before(ln.internal_object(), rn.internal_object());
8064 bool operator()(
const xpath_node& lhs,
const xpath_node& rhs)
const
8066 if (lhs.attribute())
return rhs.attribute() ? lhs.attribute() < rhs.attribute() :
true;
8067 else return rhs.attribute() ? false : lhs.node() < rhs.node();
8073 #if defined(__STDC_IEC_559__) || ((FLT_RADIX - 0 == 2) && (FLT_MAX_EXP - 0 == 128) && (FLT_MANT_DIG - 0 == 24))
8075 typedef uint32_t UI;
8076 union {
float f; UI i; } u;
8081 const volatile double zero = 0.0;
8088 #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__)
8089 return !!_isnan(value);
8090 #elif defined(fpclassify) && defined(FP_NAN)
8091 return fpclassify(value) == FP_NAN;
8094 const volatile double v = value;
8101 #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__)
8102 if (_finite(value))
return (value == 0) ?
PUGIXML_TEXT(
"0") : 0;
8105 #elif defined(fpclassify) && defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO)
8106 switch (fpclassify(value))
8122 const volatile double v = value;
8133 return (value != 0 && !
is_nan(value));
8138 while (begin != end && end[-1] ==
'0') end--;
8144#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE)
8149 _ecvt_s(buffer,
sizeof(buffer), value, DBL_DIG + 1, &exponent, &sign);
8155 *out_mantissa = buffer;
8156 *out_exponent = exponent;
8165 char* exponent_string = strchr(buffer,
'e');
8166 assert(exponent_string);
8168 int exponent = atoi(exponent_string + 1);
8171 char* mantissa = buffer[0] ==
'-' ? buffer + 1 : buffer;
8172 assert(mantissa[0] !=
'0' && mantissa[1] ==
'.');
8175 mantissa[1] = mantissa[0];
8183 *out_mantissa = mantissa;
8184 *out_exponent = exponent;
8195 char mantissa_buffer[32];
8202 size_t result_size = strlen(mantissa_buffer) + (exponent > 0 ? exponent : -exponent) + 4;
8203 char_t* result =
static_cast<char_t*
>(alloc->
allocate(
sizeof(char_t) * result_size));
8210 if (value < 0) *s++ =
'-';
8219 while (exponent > 0)
8221 assert(*mantissa == 0 ||
static_cast<unsigned int>(*mantissa -
'0') <= 9);
8222 *s++ = *mantissa ? *mantissa++ :
'0';
8234 while (exponent < 0)
8243 assert(
static_cast<unsigned int>(*mantissa -
'0') <= 9);
8249 assert(s < result + result_size);
8261 if (*
string ==
'-') ++string;
8263 if (!*
string)
return false;
8282 return *
string == 0;
8291 #ifdef PUGIXML_WCHAR_MODE
8292 return wcstod(
string, 0);
8294 return strtod(
string, 0);
8300 size_t length =
static_cast<size_t>(end - begin);
8301 char_t* scratch = buffer;
8303 if (length >=
sizeof(buffer) /
sizeof(buffer[0]))
8307 if (!scratch)
return false;
8311 memcpy(scratch, begin, length *
sizeof(char_t));
8312 scratch[length] = 0;
8324 return floor(value + 0.5);
8331 return (value >= -0.5 && value <= 0) ? ceil(value) : floor(value + 0.5);
8336 return node.attribute() ? node.attribute().name() : node.node().name();
8344 return p ? p + 1 : name;
8354 const char_t* pos =
find_char(name,
':');
8362 const char_t* name = a.name();
8378 xml_attribute a = p.find_attribute(pred);
8380 if (a)
return a.value();
8395 xml_node p = parent;
8399 xml_attribute a = p.find_attribute(pred);
8401 if (a)
return a.value();
8416 char_t* write = buffer;
8418 for (char_t* it = buffer; *it; )
8428 if (write != buffer) *write++ =
' ';
8444 char_t* write = buffer;
8450 const char_t* pos =
find_char(from, ch);
8454 else if (
static_cast<size_t>(pos - from) < to_length)
8455 *write++ = to[pos - from];
8466 unsigned char table[128] = {0};
8470 unsigned int fc =
static_cast<unsigned int>(*from);
8471 unsigned int tc =
static_cast<unsigned int>(*to);
8473 if (fc >= 128 || tc >= 128)
8478 table[fc] =
static_cast<unsigned char>(tc ? tc : 128);
8484 for (
int i = 0; i < 128; ++i)
8486 table[i] =
static_cast<unsigned char>(i);
8488 void* result = alloc->
allocate(
sizeof(table));
8489 if (!result)
return 0;
8491 memcpy(result, table,
sizeof(table));
8493 return static_cast<unsigned char*
>(result);
8498 char_t* write = buffer;
8502 char_t ch = *buffer++;
8503 unsigned int index =
static_cast<unsigned int>(ch);
8507 unsigned char code = table[index];
8511 *write =
static_cast<char_t
>(code);
8512 write += 1 - (code >> 7);
8581 unsigned int result = 0;
8585 result +=
static_cast<unsigned int>(*str++);
8586 result += result << 10;
8587 result ^= result >> 6;
8590 result += result << 3;
8591 result ^= result >> 11;
8592 result += result << 15;
8600 if (length == 0)
return 0;
8604 if (!memory)
return 0;
8606 T* result =
new (memory) T();
8608 memcpy(result->name, name, (length + 1) *
sizeof(char_t));
8617 case xpath_type_node_set:
8618 return new_xpath_variable<xpath_variable_node_set>(name);
8620 case xpath_type_number:
8621 return new_xpath_variable<xpath_variable_number>(name);
8623 case xpath_type_string:
8624 return new_xpath_variable<xpath_variable_string>(name);
8626 case xpath_type_boolean:
8627 return new_xpath_variable<xpath_variable_boolean>(name);
8644 case xpath_type_node_set:
8648 case xpath_type_number:
8652 case xpath_type_string:
8656 case xpath_type_boolean:
8661 assert(
false &&
"Invalid variable type");
8667 switch (rhs->type())
8669 case xpath_type_node_set:
8672 case xpath_type_number:
8675 case xpath_type_string:
8678 case xpath_type_boolean:
8682 assert(
false &&
"Invalid variable type");
8689 size_t length =
static_cast<size_t>(end - begin);
8690 char_t* scratch = buffer;
8692 if (length >=
sizeof(buffer) /
sizeof(buffer[0]))
8696 if (!scratch)
return false;
8700 memcpy(scratch, begin, length *
sizeof(char_t));
8701 scratch[length] = 0;
8703 *out_result = set->get(scratch);
8716 if (end - begin < 2)
8717 return xpath_node_set::type_sorted;
8721 bool first = cmp(begin[0], begin[1]);
8723 for (
const xpath_node* it = begin + 1; it + 1 < end; ++it)
8724 if (cmp(it[0], it[1]) != first)
8725 return xpath_node_set::type_unsorted;
8727 return first ? xpath_node_set::type_sorted : xpath_node_set::type_sorted_reverse;
8730 PUGI__FN xpath_node_set::type_t
xpath_sort(xpath_node* begin, xpath_node* end, xpath_node_set::type_t type,
bool rev)
8732 xpath_node_set::type_t order = rev ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted;
8734 if (type == xpath_node_set::type_unsorted)
8738 if (sorted == xpath_node_set::type_unsorted)
8742 type = xpath_node_set::type_sorted;
8748 if (type != order)
reverse(begin, end);
8755 if (begin == end)
return xpath_node();
8759 case xpath_node_set::type_sorted:
8762 case xpath_node_set::type_sorted_reverse:
8765 case xpath_node_set::type_unsorted:
8769 assert(
false &&
"Invalid node set type");
8770 return xpath_node();
8824 if (begin_ == end_)
return;
8826 size_t size_ =
static_cast<size_t>(
_end -
_begin);
8827 size_t capacity =
static_cast<size_t>(
_eos -
_begin);
8828 size_t count =
static_cast<size_t>(end_ - begin_);
8830 if (size_ + count > capacity)
8833 xpath_node* data =
static_cast<xpath_node*
>(alloc->
reallocate(
_begin, capacity *
sizeof(xpath_node), (size_ + count) *
sizeof(xpath_node)));
8838 _end = data + size_;
8839 _eos = data + size_ + count;
8842 memcpy(
_end, begin_, count *
sizeof(xpath_node));
8860 if (
_type == xpath_node_set::type_unsorted)
8866 xpath_node_set::type_t
type()
const
8879 size_t capacity =
static_cast<size_t>(
_eos -
_begin);
8882 size_t new_capacity = capacity + capacity / 2 + 1;
8885 xpath_node* data =
static_cast<xpath_node*
>(alloc->
reallocate(
_begin, capacity *
sizeof(xpath_node), new_capacity *
sizeof(xpath_node)));
8890 _end = data + capacity;
8891 _eos = data + new_capacity;
8951 size_t length =
static_cast<size_t>(
end -
begin);
8978 const char_t* cur =
_cur;
8992 if (*(cur+1) ==
'=')
9005 if (*(cur+1) ==
'=')
9018 if (*(cur+1) ==
'=')
9117 if (*(cur+1) ==
'/')
9130 if (*(cur+1) ==
'.')
9163 char_t terminator = *cur;
9168 while (*cur && *cur != terminator) cur++;
9183 if (*(cur+1) ==
':')
9419 if (lt != xpath_type_node_set && rt != xpath_type_node_set)
9421 if (lt == xpath_type_boolean || rt == xpath_type_boolean)
9423 else if (lt == xpath_type_number || rt == xpath_type_number)
9425 else if (lt == xpath_type_string || rt == xpath_type_string)
9432 return comp(ls, rs);
9435 else if (lt == xpath_type_node_set && rt == xpath_type_node_set)
9442 for (
const xpath_node* li = ls.
begin(); li != ls.
end(); ++li)
9443 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9455 if (lt == xpath_type_node_set)
9461 if (lt == xpath_type_boolean)
9463 else if (lt == xpath_type_number)
9470 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9480 else if (lt == xpath_type_string)
9487 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9499 assert(
false &&
"Wrong types");
9512 if (lt != xpath_type_node_set && rt != xpath_type_node_set)
9514 else if (lt == xpath_type_node_set && rt == xpath_type_node_set)
9521 for (
const xpath_node* li = ls.
begin(); li != ls.
end(); ++li)
9527 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9538 else if (lt != xpath_type_node_set && rt == xpath_type_node_set)
9545 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9555 else if (lt == xpath_type_node_set && rt != xpath_type_node_set)
9562 for (
const xpath_node* li = ls.
begin(); li != ls.
end(); ++li)
9574 assert(
false &&
"Wrong types");
9581 assert(ns.
size() >= first);
9582 assert(expr->
rettype() != xpath_type_number);
9585 size_t size = ns.
size() - first;
9587 xpath_node* last = ns.
begin() + first;
9590 for (xpath_node* it = last; it != ns.
end(); ++it, ++i)
9607 assert(ns.
size() >= first);
9608 assert(expr->
rettype() == xpath_type_number);
9611 size_t size = ns.
size() - first;
9613 xpath_node* last = ns.
begin() + first;
9616 for (xpath_node* it = last; it != ns.
end(); ++it, ++i)
9633 assert(ns.
size() >= first);
9634 assert(expr->
rettype() == xpath_type_number);
9636 size_t size = ns.
size() - first;
9638 xpath_node* last = ns.
begin() + first;
9644 if (er >= 1.0 && er <= size)
9646 size_t eri =
static_cast<size_t>(er);
9650 xpath_node r = last[eri - 1];
9661 if (ns.
size() == first)
return;
9675 if (ns.
size() == first)
return;
9680 pred->apply_predicate(ns, first, stack, !pred->_next && last_once);
9687 const char_t* name = a->name ? a->name + 0 :
PUGIXML_TEXT(
"");
9694 ns.
push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9703 ns.
push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9711 ns.
push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9732 if (type == node_element && n->name &&
strequal(n->name,
_data.nodetest))
9744 if (type == node_comment)
9752 if (type == node_pcdata || type == node_cdata)
9760 if (type == node_pi)
9768 if (type == node_pi && n->name &&
strequal(n->name,
_data.nodetest))
9776 if (type == node_element)
9784 if (type == node_element && n->name &&
starts_with(n->name,
_data.nodetest))
9792 assert(
false &&
"Unknown axis");
9800 const axis_t axis = T::axis;
9806 for (xml_attribute_struct* a = n->first_attribute; a; a = a->next_attribute)
9836 if (cur->first_child)
9837 cur = cur->first_child;
9840 while (!cur->next_sibling)
9844 if (cur == n)
return;
9847 cur = cur->next_sibling;
9865 for (
xml_node_struct* c = n->prev_sibling_c; c->next_sibling; c = c->prev_sibling_c)
9877 while (!cur->next_sibling)
9884 cur = cur->next_sibling;
9891 if (cur->first_child)
9892 cur = cur->first_child;
9895 while (!cur->next_sibling)
9902 cur = cur->next_sibling;
9914 while (!cur->prev_sibling_c->next_sibling)
9921 cur = cur->prev_sibling_c;
9925 if (cur->first_child)
9926 cur = cur->first_child->prev_sibling_c;
9933 while (!cur->prev_sibling_c->next_sibling)
9944 cur = cur->prev_sibling_c;
9987 assert(
false &&
"Unimplemented axis");
9993 const axis_t axis = T::axis;
10032 if (cur->first_child)
10033 cur = cur->first_child;
10036 while (!cur->next_sibling)
10043 cur = cur->next_sibling;
10068 assert(
false &&
"Unimplemented axis");
10074 const axis_t axis = T::axis;
10078 step_fill(ns, xn.node().internal_object(), alloc, once, v);
10079 else if (axis_has_attributes && xn.attribute() && xn.parent())
10080 step_fill(ns, xn.attribute().internal_object(), xn.parent().internal_object(), alloc, once, v);
10085 const axis_t axis = T::axis;
10087 const xpath_node_set::type_t axis_type = axis_reverse ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted;
10104 for (
const xpath_node* it = s.
begin(); it != s.
end(); ++it)
10106 size_t size = ns.
size();
10109 if (axis !=
axis_self && size != 0) ns.
set_type(xpath_node_set::type_unsorted);
10134 _data.string = value;
10141 _data.number = value;
10148 _data.variable = value;
10160 _data.nodetest = contents;
10241 if (c.
n.attribute())
return false;
10247 for (xml_node n = c.
n.node(); n; n = n.parent())
10249 xml_attribute a = n.attribute(
PUGIXML_TEXT(
"xml:lang"));
10253 const char_t* value = a.value();
10256 for (
const char_t* lit = lang.
c_str(); *lit; ++lit)
10262 return *value == 0 || *value ==
'-';
10282 if (
_rettype == xpath_type_boolean)
10283 return _data.variable->get_boolean();
10291 case xpath_type_number:
10294 case xpath_type_string:
10301 case xpath_type_node_set:
10309 assert(
false &&
"Wrong expression for return type boolean");
10339 return _data.number;
10342 return static_cast<double>(c.
size);
10345 return static_cast<double>(c.
position);
10386 for (
const xpath_node* it = ns.
begin(); it != ns.
end(); ++it)
10400 return r == r ? floor(r) : r;
10407 return r == r ? ceil(r) : r;
10417 if (
_rettype == xpath_type_number)
10418 return _data.variable->get_number();
10426 case xpath_type_boolean:
10429 case xpath_type_string:
10436 case xpath_type_node_set:
10444 assert(
false &&
"Wrong expression for return type number");
10473 assert(pos == count);
10477 for (
size_t i = 0; i < count; ++i) length += buffer[i].length();
10480 char_t* result =
static_cast<char_t*
>(stack.
result->
allocate((length + 1) *
sizeof(char_t)));
10483 char_t* ri = result;
10485 for (
size_t j = 0; j < count; ++j)
10486 for (
const char_t* bi = buffer[j].c_str(); *bi; ++bi)
10503 xpath_node na = c.
n;
10513 xpath_node na = ns.
first();
10520 xpath_node na = c.
n;
10530 xpath_node na = ns.
first();
10537 xpath_node na = c.
n;
10547 xpath_node na = ns.
first();
10587 const char_t* rbegin = pos + p.
length();
10600 size_t s_length = s.
length();
10605 else if (first >= s_length + 1)
return xpath_string();
10607 size_t pos = first < 1 ? 1 : static_cast<size_t>(first);
10608 assert(1 <= pos && pos <= s_length + 1);
10610 const char_t* rbegin = s.
c_str() + (pos - 1);
10623 size_t s_length = s.
length();
10629 else if (first >= s_length + 1)
return xpath_string();
10633 size_t pos = first < 1 ? 1 : static_cast<size_t>(first);
10634 size_t end = last >= s_length + 1 ? s_length + 1 :
static_cast<size_t>(last);
10636 assert(1 <= pos && pos <= end && end <= s_length + 1);
10637 const char_t* rbegin = s.
c_str() + (pos - 1);
10638 const char_t* rend = s.
c_str() + (end - 1);
10701 if (
_rettype == xpath_type_string)
10710 case xpath_type_boolean:
10713 case xpath_type_number:
10716 case xpath_type_node_set:
10727 assert(
false &&
"Wrong expression for return type string");
10748 rs.
set_type(xpath_node_set::type_unsorted);
10818 assert(
false &&
"Unknown axis");
10829 ns.
set_type(xpath_node_set::type_sorted);
10841 if (
_rettype == xpath_type_node_set)
10843 const xpath_node_set& s =
_data.variable->get_node_set();
10856 assert(
false &&
"Wrong expression for return type node set");
10960 if (!n->is_posinv_expr())
return false;
10983 return static_cast<xpath_value_type
>(
_rettype);
11023 return memory ?
new (memory)
xpath_ast_node(type, rettype, value) : 0;
11029 return memory ?
new (memory)
xpath_ast_node(type, rettype, value) : 0;
11035 return memory ?
new (memory)
xpath_ast_node(type, rettype, value) : 0;
11041 return memory ?
new (memory)
xpath_ast_node(type, rettype, left, right) : 0;
11047 return memory ?
new (memory)
xpath_ast_node(type, left, axis, test, contents) : 0;
11053 return memory ?
new (memory)
xpath_ast_node(type, left, right, test) : 0;
11061 size_t length =
static_cast<size_t>(value.
end - value.
begin);
11063 char_t* c =
static_cast<char_t*
>(
_alloc->
allocate((length + 1) *
sizeof(char_t)));
11066 memcpy(c, value.
begin, length *
sizeof(char_t));
11074 switch (name.
begin[0])
11085 if (args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11088 else if (name ==
PUGIXML_TEXT(
"contains") && argc == 2)
11092 else if (name ==
PUGIXML_TEXT(
"ceiling") && argc == 1)
11116 else if (name ==
PUGIXML_TEXT(
"local-name") && argc <= 1)
11118 if (argc == 1 && args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11127 if (argc == 1 && args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11130 else if (name ==
PUGIXML_TEXT(
"namespace-uri") && argc <= 1)
11132 if (argc == 1 && args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11135 else if (name ==
PUGIXML_TEXT(
"normalize-space") && argc <= 1)
11159 else if (name ==
PUGIXML_TEXT(
"string-length") && argc <= 1)
11161 else if (name ==
PUGIXML_TEXT(
"starts-with") && argc == 2)
11163 else if (name ==
PUGIXML_TEXT(
"substring-before") && argc == 2)
11165 else if (name ==
PUGIXML_TEXT(
"substring-after") && argc == 2)
11167 else if (name ==
PUGIXML_TEXT(
"substring") && (argc == 2 || argc == 3))
11171 if (args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11189 return error(
"Unrecognized function or wrong parameter count");
11196 switch (name.
begin[0])
11262 switch (name.
begin[0])
11305 return error(
"Unknown variable: variable set is not provided");
11312 return error(
"Unknown variable: variable set does not contain the given name");
11327 return error(
"Expected ')' to match an opening '('");
11337 if (!value)
return 0;
11367 return error(
"Unrecognized function call");
11375 return error(
"No comma between function arguments");
11382 if (argc < 2) args[argc] = n;
11395 return error(
"Unrecognizable primary expression");
11411 if (n->
rettype() != xpath_type_node_set)
11412 return error(
"Predicate has to be applied to node set");
11415 if (!expr)
return 0;
11421 return error(
"Expected ']' to match an opening '['");
11436 if (set && set->
rettype() != xpath_type_node_set)
11437 return error(
"Step has to be applied to node set");
11439 bool axis_specified =
false;
11445 axis_specified =
true;
11454 return error(
"Predicates are not allowed after an abbreviated step");
11463 return error(
"Predicates are not allowed after an abbreviated step");
11481 if (axis_specified)
11482 return error(
"Two axis specifiers in one step");
11486 if (!axis_specified)
11487 return error(
"Unknown axis");
11505 return error(
"Unrecognized node test");
11523 return error(
"Unrecognized node type");
11527 else if (nt_name ==
PUGIXML_TEXT(
"processing-instruction"))
11530 return error(
"Only literals are allowed as arguments to processing-instruction()");
11537 return error(
"Unmatched brace near processing-instruction()");
11542 return error(
"Unmatched brace near node type test");
11548 if (nt_name.
end - nt_name.
begin > 2 && nt_name.
end[-2] ==
':' && nt_name.
end[-1] ==
'*')
11568 return error(
"Unrecognized node test");
11572 if (!nt_name_copy)
return 0;
11584 if (!expr)
return 0;
11587 if (!pred)
return 0;
11590 return error(
"Expected ']' to match an opening '['");
11705 if (n->
rettype() != xpath_type_node_set)
11706 return error(
"Step has to be applied to node set");
11809 if (!rhs)
return 0;
11816 if (!rhs)
return 0;
11822 return error(
"Union operator has to be applied to node sets");
11825 if (!lhs)
return 0;
11870 return error(
"Incorrect query");
11879 return parser.
parse();
11888 if (!memory)
return 0;
11916 if (!impl)
return 0;
11918 if (impl->
root->
rettype() != xpath_type_node_set)
11920 #ifdef PUGIXML_NO_EXCEPTIONS
11923 xpath_parse_result res;
11924 res.error =
"Expression does not evaluate to node set";
11926 throw xpath_exception(res);
11936#ifndef PUGIXML_NO_EXCEPTIONS
12007 return (
bool)lhs && rhs;
12010 PUGI__FN bool operator||(
const xpath_node& lhs,
bool rhs)
12012 return (
bool)lhs || rhs;
12018 assert(begin_ <= end_);
12020 size_t size_ =
static_cast<size_t>(end_ - begin_);
12028 if (begin_ != end_)
_storage = *begin_;
12041 #ifdef PUGIXML_NO_EXCEPTIONS
12044 throw std::bad_alloc();
12048 memcpy(storage, begin_, size_ *
sizeof(
xpath_node));
12055 _end = storage + size_;
12060#ifdef PUGIXML_HAS_MOVE
12064 _storage = rhs._storage;
12065 _begin = (rhs._begin == &rhs._storage) ? &_storage : rhs._begin;
12066 _end = _begin + (rhs._end - rhs._begin);
12068 rhs._type = type_unsorted;
12069 rhs._begin = &rhs._storage;
12070 rhs._end = rhs._begin;
12080 _assign(begin_, end_, type_);
12086 impl::xml_memory::deallocate(
_begin);
12096 if (
this == &ns)
return *
this;
12103#ifdef PUGIXML_HAS_MOVE
12111 if (
this == &rhs)
return *
this;
12113 if (_begin != &_storage)
12114 impl::xml_memory::deallocate(_begin);
12139 assert(index <
size());
12186 return static_cast<const impl::xpath_variable_node_set*
>(
this)->
name;
12189 return static_cast<const impl::xpath_variable_number*
>(
this)->
name;
12192 return static_cast<const impl::xpath_variable_string*
>(
this)->
name;
12195 return static_cast<const impl::xpath_variable_boolean*
>(
this)->
name;
12198 assert(
false &&
"Invalid variable type");
12210 return (
_type ==
xpath_type_boolean) ?
static_cast<const impl::xpath_variable_boolean*
>(
this)->value :
false;
12215 return (
_type ==
xpath_type_number) ?
static_cast<const impl::xpath_variable_number*
>(
this)->value : impl::gen_nan();
12226 return (
_type ==
xpath_type_node_set) ?
static_cast<const impl::xpath_variable_node_set*
>(
this)->value : impl::dummy_node_set;
12233 static_cast<impl::xpath_variable_boolean*
>(
this)->value = value;
12241 static_cast<impl::xpath_variable_number*
>(
this)->value = value;
12249 impl::xpath_variable_string* var =
static_cast<impl::xpath_variable_string*
>(
this);
12252 size_t size = (impl::strlength(value) + 1) *
sizeof(
char_t);
12254 char_t* copy =
static_cast<char_t*
>(impl::xml_memory::allocate(size));
12255 if (!copy)
return false;
12257 memcpy(copy, value, size);
12260 if (var->value) impl::xml_memory::deallocate(var->value);
12270 static_cast<impl::xpath_variable_node_set*
>(
this)->value = value;
12276 for (
size_t i = 0; i <
sizeof(
_data) /
sizeof(
_data[0]); ++i)
12282 for (
size_t i = 0; i <
sizeof(
_data) /
sizeof(
_data[0]); ++i)
12288 for (
size_t i = 0; i <
sizeof(
_data) /
sizeof(
_data[0]); ++i)
12296 if (
this == &rhs)
return *
this;
12303#ifdef PUGIXML_HAS_MOVE
12306 for (
size_t i = 0; i <
sizeof(_data) /
sizeof(_data[0]); ++i)
12308 _data[i] = rhs._data[i];
12315 for (
size_t i = 0; i <
sizeof(_data) /
sizeof(_data[0]); ++i)
12317 _destroy(_data[i]);
12319 _data[i] = rhs._data[i];
12331 for (
size_t i = 0; i <
sizeof(
_data) /
sizeof(
_data[0]); ++i)
12340 for (
size_t i = 0; i <
sizeof(
_data) /
sizeof(
_data[0]); ++i)
12345 rhs.
_data[i] = chain;
12351 const size_t hash_size =
sizeof(
_data) /
sizeof(
_data[0]);
12352 size_t hash = impl::hash_string(name) % hash_size;
12356 if (impl::strequal(var->name(), name))
12370 if (!nvar)
return false;
12374 last->
_next = nvar;
12376 *out_result = nvar;
12381 if (!impl::copy_xpath_variable(nvar, var))
return false;
12395 impl::delete_xpath_variable(var->
_type, var);
12403 const size_t hash_size =
sizeof(
_data) /
sizeof(
_data[0]);
12404 size_t hash = impl::hash_string(name) % hash_size;
12408 if (impl::strequal(var->name(), name))
12409 return var->type() == type ? var : 0;
12418 _data[hash] = result;
12427 return var ? var->
set(value) :
false;
12433 return var ? var->
set(value) :
false;
12439 return var ? var->
set(value) :
false;
12445 return var ? var->
set(value) :
false;
12450 return _find(name);
12455 return _find(name);
12460 impl::xpath_query_impl* qimpl = impl::xpath_query_impl::create();
12464 #ifdef PUGIXML_NO_EXCEPTIONS
12467 throw std::bad_alloc();
12472 using impl::auto_deleter;
12475 qimpl->root = impl::xpath_parser::parse(query, variables, &qimpl->alloc, &
_result);
12479 qimpl->root->optimize(&qimpl->alloc);
12486 #ifdef PUGIXML_NO_EXCEPTIONS
12489 if (qimpl->oom)
throw std::bad_alloc();
12503 impl::xpath_query_impl::destroy(
static_cast<impl::xpath_query_impl*
>(
_impl));
12506#ifdef PUGIXML_HAS_MOVE
12510 _result = rhs._result;
12517 if (
this == &rhs)
return *
this;
12520 impl::xpath_query_impl::destroy(
static_cast<impl::xpath_query_impl*
>(_impl));
12523 _result = rhs._result;
12525 rhs._result = xpath_parse_result();
12535 return static_cast<impl::xpath_query_impl*
>(
_impl)->root->rettype();
12540 if (!
_impl)
return false;
12542 impl::xpath_context c(n, 1, 1);
12543 impl::xpath_stack_data
sd;
12545 bool r =
static_cast<impl::xpath_query_impl*
>(
_impl)->root->eval_boolean(c,
sd.stack);
12549 #ifdef PUGIXML_NO_EXCEPTIONS
12552 throw std::bad_alloc();
12561 if (!
_impl)
return impl::gen_nan();
12563 impl::xpath_context c(n, 1, 1);
12564 impl::xpath_stack_data
sd;
12566 double r =
static_cast<impl::xpath_query_impl*
>(
_impl)->root->eval_number(c,
sd.stack);
12570 #ifdef PUGIXML_NO_EXCEPTIONS
12571 return impl::gen_nan();
12573 throw std::bad_alloc();
12580#ifndef PUGIXML_NO_STL
12585 impl::xpath_context c(n, 1, 1);
12586 impl::xpath_stack_data
sd;
12588 impl::xpath_string r =
static_cast<impl::xpath_query_impl*
>(
_impl)->root->eval_string(c,
sd.stack);
12592 #ifdef PUGIXML_NO_EXCEPTIONS
12595 throw std::bad_alloc();
12599 return string_t(r.c_str(), r.length());
12605 impl::xpath_context c(n, 1, 1);
12606 impl::xpath_stack_data
sd;
12608 impl::xpath_string r =
_impl ?
static_cast<impl::xpath_query_impl*
>(
_impl)->root->eval_string(c,
sd.stack) : impl::xpath_string();
12612 #ifdef PUGIXML_NO_EXCEPTIONS
12613 r = impl::xpath_string();
12615 throw std::bad_alloc();
12619 size_t full_size = r.length() + 1;
12623 size_t size = (full_size < capacity) ? full_size : capacity;
12626 memcpy(buffer, r.c_str(), (size - 1) *
sizeof(
char_t));
12627 buffer[size - 1] = 0;
12635 impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(
static_cast<impl::xpath_query_impl*
>(
_impl));
12638 impl::xpath_context c(n, 1, 1);
12639 impl::xpath_stack_data
sd;
12641 impl::xpath_node_set_raw r = root->eval_node_set(c,
sd.stack, impl::nodeset_eval_all);
12645 #ifdef PUGIXML_NO_EXCEPTIONS
12648 throw std::bad_alloc();
12657 impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(
static_cast<impl::xpath_query_impl*
>(
_impl));
12660 impl::xpath_context c(n, 1, 1);
12661 impl::xpath_stack_data
sd;
12663 impl::xpath_node_set_raw r = root->eval_node_set(c,
sd.stack, impl::nodeset_eval_first);
12667 #ifdef PUGIXML_NO_EXCEPTIONS
12670 throw std::bad_alloc();
12738#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
12739# pragma warning(pop)
12742#if defined(_MSC_VER) && defined(__c2__)
12743# pragma clang diagnostic pop
12746#if defined(__clang__)
12747# pragma clang diagnostic pop
12751#undef PUGI__NO_INLINE
12752#undef PUGI__UNLIKELY
12753#undef PUGI__STATIC_ASSERT
12754#undef PUGI__DMC_VOLATILE
12755#undef PUGI__UNSIGNED_OVERFLOW
12756#undef PUGI__MSVC_CRT_VERSION
12757#undef PUGI__SNPRINTF
12758#undef PUGI__NS_BEGIN
12761#undef PUGI__FN_NO_INLINE
12762#undef PUGI__GETHEADER_IMPL
12763#undef PUGI__GETPAGE_IMPL
12764#undef PUGI__GETPAGE
12765#undef PUGI__NODETYPE
12766#undef PUGI__IS_CHARTYPE_IMPL
12767#undef PUGI__IS_CHARTYPE
12768#undef PUGI__IS_CHARTYPEX
12769#undef PUGI__ENDSWITH
12772#undef PUGI__PUSHNODE
12773#undef PUGI__POPNODE
12774#undef PUGI__SCANFOR
12775#undef PUGI__SCANWHILE
12776#undef PUGI__SCANWHILE_UNROLL
12778#undef PUGI__THROW_ERROR
12779#undef PUGI__CHECK_ERROR
bool operator!=(const xml_attribute_iterator &rhs) const
const xml_attribute_iterator & operator--()
xml_attribute * operator->() const
xml_attribute & operator*() const
bool operator==(const xml_attribute_iterator &rhs) const
const xml_attribute_iterator & operator++()
const char_t * as_string(const char_t *def=PUGIXML_TEXT("")) const
bool operator>=(const xml_attribute &r) const
bool as_bool(bool def=false) const
bool operator!=(const xml_attribute &r) const
bool operator<(const xml_attribute &r) const
int as_int(int def=0) const
float as_float(float def=0) const
bool operator==(const xml_attribute &r) const
size_t hash_value() const
const char_t * name() const
xml_attribute & operator=(const char_t *rhs)
xml_attribute previous_attribute() const
xml_attribute_struct * _attr
xml_attribute next_attribute() const
bool operator<=(const xml_attribute &r) const
double as_double(double def=0) const
void(* unspecified_bool_type)(xml_attribute ***)
bool set_name(const char_t *rhs)
bool set_value(const char_t *rhs)
unsigned int as_uint(unsigned int def=0) const
xml_attribute_struct * internal_object() const
bool operator>(const xml_attribute &r) const
const char_t * value() const
xml_parse_result load_buffer_inplace(void *contents, size_t size, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
xml_node document_element() const
xml_parse_result load_string(const char_t *contents, unsigned int options=parse_default)
bool save_file(const char *path, const char_t *indent=PUGIXML_TEXT("\t"), unsigned int flags=format_default, xml_encoding encoding=encoding_auto) const
xml_parse_result load_buffer_inplace_own(void *contents, size_t size, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
xml_parse_result load_file(const char *path, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
xml_parse_result load_buffer(const void *contents, size_t size, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
xml_document & operator=(const xml_document &)
xml_parse_result load(std::basic_istream< char, std::char_traits< char > > &stream, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
void save(xml_writer &writer, const char_t *indent=PUGIXML_TEXT("\t"), unsigned int flags=format_default, xml_encoding encoding=encoding_auto) const
void _move(xml_document &rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT
xml_named_node_iterator()
bool operator!=(const xml_named_node_iterator &rhs) const
xml_node * operator->() const
const xml_named_node_iterator & operator--()
bool operator==(const xml_named_node_iterator &rhs) const
xml_node & operator*() const
const xml_named_node_iterator & operator++()
bool operator==(const xml_node_iterator &rhs) const
const xml_node_iterator & operator--()
xml_node * operator->() const
bool operator!=(const xml_node_iterator &rhs) const
const xml_node_iterator & operator++()
xml_node & operator*() const
string_t path(char_t delimiter='/') const
size_t hash_value() const
PUGIXML_DEPRECATED xpath_node select_single_node(const char_t *query, xpath_variable_set *variables=0) const
bool set_value(const char_t *rhs)
xml_node_type type() const
xml_node append_child(xml_node_type type=node_element)
xml_node child(const char_t *name) const
friend class xml_named_node_iterator
xml_node insert_move_after(const xml_node &moved, const xml_node &node)
xml_node last_child() const
xml_node append_move(const xml_node &moved)
xml_node first_child() const
bool operator>(const xml_node &r) const
xml_object_range< xml_node_iterator > children() const
xml_node prepend_move(const xml_node &moved)
xml_attribute append_attribute(const char_t *name)
xml_node next_sibling() const
xml_node_struct * internal_object() const
xml_object_range< xml_attribute_iterator > attributes() const
bool remove_child(const xml_node &n)
xml_attribute append_copy(const xml_attribute &proto)
xml_node insert_child_after(xml_node_type type, const xml_node &node)
xml_attribute last_attribute() const
attribute_iterator attributes_end() const
xml_node previous_sibling() const
xpath_node select_node(const char_t *query, xpath_variable_set *variables=0) const
ptrdiff_t offset_debug() const
xml_attribute insert_attribute_before(const char_t *name, const xml_attribute &attr)
xml_attribute insert_attribute_after(const char_t *name, const xml_attribute &attr)
bool operator!=(const xml_node &r) const
bool operator<(const xml_node &r) const
xml_attribute prepend_attribute(const char_t *name)
xml_parse_result append_buffer(const void *contents, size_t size, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
const char_t * value() const
void(* unspecified_bool_type)(xml_node ***)
xml_attribute_iterator attribute_iterator
bool traverse(xml_tree_walker &walker)
xml_node find_child_by_attribute(const char_t *name, const char_t *attr_name, const char_t *attr_value) const
const char_t * child_value() const
bool set_name(const char_t *rhs)
xml_node prepend_child(xml_node_type type=node_element)
xml_attribute first_attribute() const
bool operator>=(const xml_node &r) const
xml_attribute insert_copy_after(const xml_attribute &proto, const xml_attribute &attr)
xml_attribute prepend_copy(const xml_attribute &proto)
xml_node insert_move_before(const xml_node &moved, const xml_node &node)
xml_node first_element_by_path(const char_t *path, char_t delimiter='/') const
xml_attribute attribute(const char_t *name) const
const char_t * name() const
xml_attribute insert_copy_before(const xml_attribute &proto, const xml_attribute &attr)
attribute_iterator attributes_begin() const
xpath_node_set select_nodes(const char_t *query, xpath_variable_set *variables=0) const
xml_node_iterator iterator
bool operator<=(const xml_node &r) const
bool remove_attribute(const xml_attribute &a)
void print(xml_writer &writer, const char_t *indent=PUGIXML_TEXT("\t"), unsigned int flags=format_default, xml_encoding encoding=encoding_auto, unsigned int depth=0) const
xml_node insert_child_before(xml_node_type type, const xml_node &node)
bool operator==(const xml_node &r) const
const char_t * as_string(const char_t *def=PUGIXML_TEXT("")) const
double as_double(double def=0) const
xml_text & operator=(const char_t *rhs)
float as_float(float def=0) const
xml_node_struct * _data_new()
bool as_bool(bool def=false) const
bool set(const char_t *rhs)
int as_int(int def=0) const
unsigned int as_uint(unsigned int def=0) const
void(* unspecified_bool_type)(xml_text ***)
const char_t * get() const
xml_node_struct * _data() const
virtual bool end(xml_node &node)
virtual bool for_each(xml_node &node)=0
virtual bool begin(xml_node &node)
virtual ~xml_tree_walker()
xml_writer_file(void *file)
virtual void write(const void *data, size_t size) PUGIXML_OVERRIDE
xml_writer_stream(std::basic_ostream< char, std::char_traits< char > > &stream)
std::basic_ostream< wchar_t, std::char_traits< wchar_t > > * wide_stream
virtual void write(const void *data, size_t size) PUGIXML_OVERRIDE
std::basic_ostream< char, std::char_traits< char > > * narrow_stream
const xpath_parse_result & result() const
xpath_exception(const xpath_parse_result &result)
virtual const char * what() const noexcept PUGIXML_OVERRIDE
xpath_parse_result _result
xpath_node_set & operator=(const xpath_node_set &ns)
void _assign(const_iterator begin, const_iterator end, type_t type)
const_iterator end() const
void sort(bool reverse=false)
const_iterator begin() const
const xpath_node & operator[](size_t index) const
void _move(xpath_node_set &rhs) PUGIXML_NOEXCEPT
void(* unspecified_bool_type)(xpath_node ***)
xml_attribute attribute() const
bool operator!=(const xpath_node &n) const
bool operator==(const xpath_node &n) const
string_t evaluate_string(const xpath_node &n) const
void(* unspecified_bool_type)(xpath_query ***)
double evaluate_number(const xpath_node &n) const
xpath_node_set evaluate_node_set(const xpath_node &n) const
xpath_value_type return_type() const
xpath_parse_result _result
xpath_query & operator=(const xpath_query &)
const xpath_parse_result & result() const
bool evaluate_boolean(const xpath_node &n) const
xpath_node evaluate_node(const xpath_node &n) const
xpath_variable * add(const char_t *name, xpath_value_type type)
void _swap(xpath_variable_set &rhs)
bool set(const char_t *name, bool value)
void _assign(const xpath_variable_set &rhs)
static void _destroy(xpath_variable *var)
static bool _clone(xpath_variable *var, xpath_variable **out_result)
xpath_variable * get(const char_t *name)
xpath_variable * _data[64]
xpath_variable * _find(const char_t *name) const
xpath_variable_set & operator=(const xpath_variable_set &rhs)
xpath_variable(xpath_value_type type)
double get_number() const
const char_t * get_string() const
const xpath_node_set & get_node_set() const
xpath_value_type type() const
const char_t * name() const
void write_direct(const char_t *data, size_t length)
void write_string(const char_t *data)
union xml_buffered_writer::@16 scratch
xml_buffered_writer(xml_writer &writer_, xml_encoding user_encoding)
void write(char_t d0, char_t d1)
xml_buffered_writer(const xml_buffered_writer &)
char_t data_char[bufcapacity]
xml_buffered_writer & operator=(const xml_buffered_writer &)
char_t buffer[bufcapacity]
void flush(const char_t *data, size_t size)
uint16_t data_u16[2 *bufcapacity]
void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4)
uint8_t data_u8[4 *bufcapacity]
void write_buffer(const char_t *data, size_t length)
void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4, char_t d5)
void write(char_t d0, char_t d1, char_t d2, char_t d3)
void write(char_t d0, char_t d1, char_t d2)
uint32_t data_u32[bufcapacity]
const unsigned char * table
xpath_variable * variable
void set_next(xpath_ast_node *value)
bool step_push(xpath_node_set_raw &ns, xml_node_struct *n, xpath_allocator *alloc)
xpath_value_type rettype() const
xpath_node_set_raw step_do(const xpath_context &c, const xpath_stack &stack, nodeset_eval_t eval, T v)
static bool eval_once(xpath_node_set::type_t type, nodeset_eval_t eval)
void optimize_self(xpath_allocator *alloc)
bool is_posinv_expr() const
bool step_push(xpath_node_set_raw &ns, xml_attribute_struct *a, xml_node_struct *parent, xpath_allocator *alloc)
xpath_node_set_raw eval_node_set(const xpath_context &c, const xpath_stack &stack, nodeset_eval_t eval)
xpath_string eval_string(const xpath_context &c, const xpath_stack &stack)
union xpath_ast_node::@19 _data
xpath_ast_node(ast_type_t type, xpath_ast_node *left, axis_t axis, nodetest_t test, const char_t *contents)
void apply_predicate(xpath_node_set_raw &ns, size_t first, const xpath_stack &stack, bool once)
static void apply_predicate_number_const(xpath_node_set_raw &ns, size_t first, xpath_ast_node *expr, const xpath_stack &stack)
xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_variable *value)
double eval_number(const xpath_context &c, const xpath_stack &stack)
void optimize(xpath_allocator *alloc)
static bool compare_eq(xpath_ast_node *lhs, xpath_ast_node *rhs, const xpath_context &c, const xpath_stack &stack, const Comp &comp)
bool is_posinv_step() const
xpath_string eval_string_concat(const xpath_context &c, const xpath_stack &stack)
static void apply_predicate_boolean(xpath_node_set_raw &ns, size_t first, xpath_ast_node *expr, const xpath_stack &stack, bool once)
bool eval_boolean(const xpath_context &c, const xpath_stack &stack)
static bool compare_rel(xpath_ast_node *lhs, xpath_ast_node *rhs, const xpath_context &c, const xpath_stack &stack, const Comp &comp)
static void apply_predicate_number(xpath_node_set_raw &ns, size_t first, xpath_ast_node *expr, const xpath_stack &stack, bool once)
xpath_ast_node & operator=(const xpath_ast_node &)
void step_fill(xpath_node_set_raw &ns, xml_attribute_struct *a, xml_node_struct *p, xpath_allocator *alloc, bool once, T v)
void step_fill(xpath_node_set_raw &ns, xml_node_struct *n, xpath_allocator *alloc, bool once, T)
void step_fill(xpath_node_set_raw &ns, const xpath_node &xn, xpath_allocator *alloc, bool once, T v)
xpath_ast_node(ast_type_t type, xpath_value_type rettype_, double value)
xpath_ast_node(const xpath_ast_node &)
xpath_ast_node(ast_type_t type, xpath_ast_node *left, xpath_ast_node *right, predicate_t test)
void apply_predicates(xpath_node_set_raw &ns, size_t first, const xpath_stack &stack, nodeset_eval_t eval)
xpath_ast_node(ast_type_t type, xpath_value_type rettype_, const char_t *value)
xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_ast_node *left=0, xpath_ast_node *right=0)
void set_right(xpath_ast_node *value)
const char_t * _cur_lexeme_pos
const char_t * current_pos() const
xpath_lexer_string _cur_lexeme_contents
const xpath_lexer_string & contents() const
xpath_lexer(const char_t *query)
const char_t * state() const
xpath_node_set::type_t _type
void append(const xpath_node *begin_, const xpath_node *end_, xpath_allocator *alloc)
xpath_node_set::type_t type() const
void push_back(const xpath_node &node, xpath_allocator *alloc)
xpath_node * begin() const
void truncate(xpath_node *pos)
void push_back_grow(const xpath_node &node, xpath_allocator *alloc)
void set_type(xpath_node_set::type_t value)
static xpath_string from_heap_preallocated(const char_t *begin, const char_t *end)
static xpath_string from_const(const char_t *str)
bool operator!=(const xpath_string &o) const
xpath_string(const char_t *buffer, bool uses_heap_, size_t length_heap)
void append(const xpath_string &o, xpath_allocator *alloc)
static xpath_string from_heap(const char_t *begin, const char_t *end, xpath_allocator *alloc)
char_t * data(xpath_allocator *alloc)
bool operator==(const xpath_string &o) const
static char_t * duplicate_string(const char_t *string, size_t length, xpath_allocator *alloc)
const char_t * c_str() const
std::basic_string< PUGIXML_CHAR, std::char_traits< PUGIXML_CHAR >, std::allocator< PUGIXML_CHAR > > string_t
PUGI__FN deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function()
PUGI__FN allocation_function PUGIXML_FUNCTION get_memory_allocation_function()
const unsigned int format_no_declaration
const unsigned int format_raw
void(* deallocation_function)(void *ptr)
static PUGI__FN void unspecified_bool_xpath_query(xpath_query ***)
static PUGI__FN void unspecified_bool_xml_node(xml_node ***)
void *(* allocation_function)(size_t size)
PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const wchar_t *str)
static PUGI__FN void unspecified_bool_xml_attribute(xml_attribute ***)
@ status_append_invalid_root
@ status_end_element_mismatch
@ status_bad_start_element
@ status_unrecognized_tag
@ status_no_document_element
const unsigned int format_save_file_text
const unsigned int format_write_bom
PUGI__FN void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate)
static PUGI__FN void unspecified_bool_xpath_node(xpath_node ***)
static PUGI__FN void unspecified_bool_xml_text(xml_text ***)
PUGI__FN std::basic_string< wchar_t > PUGIXML_FUNCTION as_wide(const char *str)
void destroy_node(xml_node_struct *n, xml_allocator &alloc)
#define PUGI__CHECK_ERROR(err, m)
PUGI__FN void default_deallocate(void *ptr)
PUGI__FN size_t strlength_wide(const wchar_t *s)
void insertion_sort(T *begin, T *end, const Pred &pred)
static const size_t xml_memory_page_size
PUGI__FN void node_copy_string(String &dest, Header &header, uintptr_t header_mask, char_t *source, Header &source_header, xml_allocator *alloc)
#define PUGI__OPTSET(OPT)
PUGI__FN double round_nearest_nzero(double value)
PUGI__FN size_t get_latin1_7bit_prefix_length(const uint8_t *data, size_t size)
PUGI__FN xml_parse_result load_buffer_impl(xml_document_struct *doc, xml_node_struct *root, void *contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own, char_t **out_buffer)
#define PUGI__NODETYPE(n)
@ ast_opt_translate_table
@ ast_opt_compare_attribute
@ ast_func_substring_before
@ ast_func_string_length_0
@ ast_func_namespace_uri_0
@ ast_func_normalize_space_1
@ ast_func_normalize_space_0
@ ast_func_substring_after
@ ast_func_namespace_uri_1
@ ast_func_string_length_1
@ ast_op_greater_or_equal
I median3(I first, I middle, I last, const Pred &pred)
PUGI__FN xml_encoding get_write_native_encoding()
PUGI__FN const char_t * qualified_name(const xpath_node &node)
PUGI__FN bool convert_number_to_boolean(double value)
PUGI__FN bool allow_insert_attribute(xml_node_type parent)
char_t *(* strconv_attribute_t)(char_t *, char_t)
#define PUGI__SCANWHILE_UNROLL(X)
PUGI__FN const void * document_buffer_order(const xpath_node &xnode)
PUGI__FN void as_utf8_end(char *buffer, size_t size, const wchar_t *str, size_t length)
wchar_selector< sizeof(wchar_t)>::writer wchar_writer
PUGI__FN xml_encoding get_wchar_encoding()
PUGI__FN PUGI__UNSIGNED_OVERFLOW U string_to_integer(const char_t *value, U minv, U maxv)
PUGI__FN void node_copy_attribute(xml_attribute_struct *da, xml_attribute_struct *sa)
PUGI__FN bool allow_insert_child(xml_node_type parent, xml_node_type child)
PUGI__FN FILE * open_file_wide(const wchar_t *path, const wchar_t *mode)
PUGI__FN size_t convert_buffer_output_generic(typename T::value_type dest, const char_t *data, size_t length, D, T)
PUGI__FN void text_output_cdata(xml_buffered_writer &writer, const char_t *s)
PUGI__FN PUGI__UNSIGNED_OVERFLOW unsigned int hash_string(const char_t *str)
PUGI__FN bool get_mutable_buffer(char_t *&out_buffer, size_t &out_length, const void *contents, size_t size, bool is_mutable)
PUGI__FN bool set_value_integer(String &dest, Header &header, uintptr_t header_mask, U value, bool negative)
PUGI__FN bool convert_buffer_generic(char_t *&out_buffer, size_t &out_length, const void *contents, size_t size, D)
static const uintptr_t xml_memory_page_type_mask
#define PUGI__UNSIGNED_OVERFLOW
PUGI__FN void node_copy_tree(xml_node_struct *dn, xml_node_struct *sn)
PUGI__FN xpath_string convert_number_to_string(double value, xpath_allocator *alloc)
PUGI__FN bool is_little_endian()
PUGI__FN void node_output(xml_buffered_writer &writer, xml_node_struct *root, const char_t *indent, unsigned int flags, unsigned int depth)
PUGI__FN size_t zero_terminate_buffer(void *buffer, size_t size, xml_encoding encoding)
PUGI__FN void node_output_simple(xml_buffered_writer &writer, xml_node_struct *node, unsigned int flags)
PUGI__FN float get_value_float(const char_t *value)
PUGI__FN char_t * strconv_comment(char_t *s, char_t endch)
#define PUGI__IS_CHARTYPE(c, ct)
PUGI__FN void node_copy_contents(xml_node_struct *dn, xml_node_struct *sn, xml_allocator *shared_alloc)
PUGI__FN double gen_nan()
PUGI__FN strconv_attribute_t get_strconv_attribute(unsigned int optmask)
PUGI__FN strconv_pcdata_t get_strconv_pcdata(unsigned int optmask)
PUGI__FN bool convert_buffer(char_t *&out_buffer, size_t &out_length, xml_encoding encoding, const void *contents, size_t size, bool is_mutable)
PUGI__FN xml_parse_status load_stream_data_seek(std::basic_istream< T > &stream, void **out_buffer, size_t *out_size)
PUGI__FN bool set_value_bool(String &dest, Header &header, uintptr_t header_mask, bool value)
I min_element(I begin, I end, const Pred &pred)
xml_document_struct & get_document(const Object *object)
PUGI__FN xml_encoding guess_buffer_encoding(const uint8_t *data, size_t size)
PUGI__FN char_t * strconv_escape(char_t *s, gap &g)
PUGI__FN void node_output_comment(xml_buffered_writer &writer, const char_t *s)
PUGI__FN bool node_is_ancestor(xml_node_struct *parent, xml_node_struct *node)
void sort(I begin, I end, const Pred &pred)
void destroy_attribute(xml_attribute_struct *a, xml_allocator &alloc)
PUGI__FN void node_output_pi_value(xml_buffered_writer &writer, const char_t *s)
wchar_selector< sizeof(wchar_t)>::counter wchar_counter
PUGI__NS_END PUGI__NS_BEGIN PUGI__FN bool starts_with(const char_t *string, const char_t *pattern)
static const uintptr_t xml_memory_page_name_allocated_or_shared_mask
#define PUGI__IS_CHARTYPEX(c, ct)
void remove_attribute(xml_attribute_struct *attr, xml_node_struct *node)
PUGI__NS_END PUGI__NS_BEGIN PUGI__FN xpath_node_set::type_t xpath_get_order(const xpath_node *begin, const xpath_node *end)
PUGI__FN int get_value_int(const char_t *value)
PUGI__FN bool node_is_before_sibling(xml_node_struct *ln, xml_node_struct *rn)
static const unsigned char chartypex_table[256]
PUGI__FN bool check_string_to_number_format(const char_t *string)
static const uintptr_t xml_memory_page_contents_shared_mask
void prepend_node(xml_node_struct *child, xml_node_struct *node)
PUGI__NS_END static PUGI__NS_BEGIN const uintptr_t xml_memory_block_alignment
PUGI__FN_NO_INLINE xml_attribute_struct * append_new_attribute(xml_node_struct *node, xml_allocator &alloc)
PUGI__FN T * new_xpath_variable(const char_t *name)
PUGI__FN const char_t * find_char(const char_t *s, char_t c)
PUGI__FN size_t get_valid_length(const char_t *data, size_t length)
void insert_node_before(xml_node_struct *child, xml_node_struct *node)
PUGI__FN std::string as_utf8_impl(const wchar_t *str, size_t length)
xml_memory_management_function_storage< int > xml_memory
PUGI__FN bool node_is_before(xml_node_struct *ln, xml_node_struct *rn)
PUGI__FN xml_parse_status get_file_size(FILE *file, size_t &out_result)
bool is_xpath_attribute(const char_t *name)
#define PUGI__SCANCHARTYPE(ct)
char_t *(* strconv_pcdata_t)(char_t *)
static const uintptr_t xpath_memory_block_alignment
void remove_node(xml_node_struct *node)
#define PUGI__GETPAGE_IMPL(header)
static const unsigned char chartype_table[256]
#define PUGI__ENDSWITH(c, e)
PUGI__NS_END PUGI__NS_BEGIN uint16_t endian_swap(uint16_t value)
PUGI__FN impl::xpath_ast_node * evaluate_node_set_prepare(xpath_query_impl *impl)
PUGI__FN bool get_variable_scratch(char_t(&buffer)[32], xpath_variable_set *set, const char_t *begin, const char_t *end, xpath_variable **out_result)
PUGI__FN char_t * normalize_space(char_t *buffer)
bool is_text_node(xml_node_struct *node)
PUGI__FN xpath_string string_value(const xpath_node &na, xpath_allocator *alloc)
PUGI__FN bool parse_declaration_encoding(const uint8_t *data, size_t size, const uint8_t *&out_encoding, size_t &out_length)
void reverse(I begin, I end)
#define PUGI__FN_NO_INLINE
#define PUGI__STATIC_ASSERT(cond)
PUGI__FN void text_output_indent(xml_buffered_writer &writer, const char_t *indent, size_t indent_length, unsigned int depth)
PUGI__FN void node_output_end(xml_buffered_writer &writer, xml_node_struct *node)
PUGI__FN double get_value_double(const char_t *value)
PUGI__FN xml_parse_status load_stream_data_noseek(std::basic_istream< T > &stream, void **out_buffer, size_t *out_size)
PUGI__FN void close_file(FILE *file)
PUGI__FN_NO_INLINE xml_node_struct * append_new_node(xml_node_struct *node, xml_allocator &alloc, xml_node_type type=node_element)
PUGI__FN PUGI__UNSIGNED_OVERFLOW char_t * integer_to_string(char_t *begin, char_t *end, U value, bool negative)
#define PUGI__DMC_VOLATILE
PUGI__NS_END PUGI__NS_BEGIN xml_attribute_struct * allocate_attribute(xml_allocator &alloc)
#define PUGI__UNLIKELY(cond)
#define PUGI__THROW_ERROR(err, m)
PUGI__FN const char_t * namespace_uri(xml_node node)
xml_parse_result make_parse_result(xml_parse_status status, ptrdiff_t offset=0)
xml_allocator & get_allocator(const Object *object)
PUGI__FN bool set_value_convert(String &dest, Header &header, uintptr_t header_mask, float value)
PUGI__FN bool allow_move(xml_node parent, xml_node child)
PUGI__FN size_t convert_buffer_output(char_t *, uint8_t *r_u8, uint16_t *r_u16, uint32_t *r_u32, const char_t *data, size_t length, xml_encoding encoding)
PUGI__FN char_t * translate_table(char_t *buffer, const unsigned char *table)
PUGI__FN const char_t * convert_number_to_string_special(double value)
PUGI__FN xml_parse_result load_stream_impl(xml_document_struct *doc, std::basic_istream< T > &stream, unsigned int options, xml_encoding encoding, char_t **out_buffer)
PUGI__FN bool is_attribute_of(xml_attribute_struct *attr, xml_node_struct *node)
static const uintptr_t xml_memory_page_name_allocated_mask
PUGI__FN bool convert_string_to_number_scratch(char_t(&buffer)[32], const char_t *begin, const char_t *end, double *out_result)
PUGI__FN xpath_node_set::type_t xpath_sort(xpath_node *begin, xpath_node *end, xpath_node_set::type_t type, bool rev)
PUGI__FN xml_encoding get_write_encoding(xml_encoding encoding)
PUGI__FN void delete_xpath_variable(T *var)
PUGI__FN bool convert_buffer_latin1(char_t *&out_buffer, size_t &out_length, const void *contents, size_t size, bool is_mutable)
void swap(T &lhs, T &rhs)
PUGI__NS_END PUGI__NS_BEGIN PUGI__FN size_t strlength(const char_t *s)
PUGI__FN char * convert_path_heap(const wchar_t *str)
PUGI__FN double round_nearest(double value)
PUGI__FN char_t * translate(char_t *buffer, const char_t *from, const char_t *to, size_t to_length)
void insert_node_after(xml_node_struct *child, xml_node_struct *node)
@ nodetest_all_in_namespace
void insert_attribute_before(xml_attribute_struct *attr, xml_attribute_struct *place, xml_node_struct *node)
PUGI__FN const char_t * find_substring(const char_t *s, const char_t *p)
PUGI__FN bool strequalrange(const char_t *lhs, const char_t *rhs, size_t count)
static const uintptr_t xml_memory_page_value_allocated_or_shared_mask
#define PUGI__SCANCHAR(ch)
PUGI__FN bool save_file_impl(const xml_document &doc, FILE *file, const char_t *indent, unsigned int flags, xml_encoding encoding)
PUGI__FN bool node_output_start(xml_buffered_writer &writer, xml_node_struct *node, const char_t *indent, size_t indent_length, unsigned int flags, unsigned int depth)
PUGI__FN bool has_declaration(xml_node_struct *node)
PUGI__FN double convert_string_to_number(const char_t *string)
PUGI__FN bool is_nan(double value)
PUGI__FN bool set_value_ascii(String &dest, Header &header, uintptr_t header_mask, char *buf)
static const uintptr_t xml_memory_page_value_allocated_mask
PUGI__FN xpath_node xpath_first(const xpath_node *begin, const xpath_node *end, xpath_node_set::type_t type)
#define PUGI__PUSHNODE(TYPE)
static const xpath_node_set dummy_node_set
PUGI__FN size_t as_utf8_begin(const wchar_t *str, size_t length)
PUGI__FN unsigned char * translate_table_generate(xpath_allocator *alloc, const char_t *from, const char_t *to)
PUGI__FN void text_output(xml_buffered_writer &writer, const char_t *s, chartypex_t type, unsigned int flags)
void append_attribute(xml_attribute_struct *attr, xml_node_struct *node)
void prepend_attribute(xml_attribute_struct *attr, xml_node_struct *node)
xml_node_struct * allocate_node(xml_allocator &alloc, xml_node_type type)
#define PUGI__GETHEADER_IMPL(object, page, flags)
PUGI__FN bool strcpy_insitu(String &dest, Header &header, uintptr_t header_mask, const char_t *source, size_t source_length)
#define PUGI__SCANWHILE(X)
PUGI__FN void node_output_attributes(xml_buffered_writer &writer, xml_node_struct *node, const char_t *indent, size_t indent_length, unsigned int flags, unsigned int depth)
PUGI__FN void truncate_zeros(char *begin, char *end)
@ axis_descendant_or_self
PUGI__FN xml_encoding get_buffer_encoding(xml_encoding encoding, const void *contents, size_t size)
PUGI__FN xml_parse_result load_file_impl(xml_document_struct *doc, FILE *file, unsigned int options, xml_encoding encoding, char_t **out_buffer)
void partition3(T *begin, T *end, T pivot, const Pred &pred, T **out_eqbeg, T **out_eqend)
PUGI__FN bool copy_xpath_variable(xpath_variable *lhs, const xpath_variable *rhs)
PUGI__FN const char_t * local_name(const xpath_node &node)
void append_node(xml_node_struct *child, xml_node_struct *node)
PUGI__FN unsigned int get_value_uint(const char_t *value)
PUGI__FN void convert_number_to_mantissa_exponent(double value, char(&buffer)[32], char **out_mantissa, int *out_exponent)
PUGI__FN bool get_value_bool(const char_t *value)
PUGI__NS_END static PUGI__NS_BEGIN const size_t xpath_memory_page_size
PUGI__FN bool strequal(const char_t *src, const char_t *dst)
PUGI__FN std::basic_string< wchar_t > as_wide_impl(const char *str, size_t size)
PUGI__FN char_t * strconv_cdata(char_t *s, char_t endch)
PUGI__NS_BEGIN PUGI__FN void * default_allocate(size_t size)
bool strcpy_insitu_allow(size_t length, const Header &header, uintptr_t header_mask, char_t *target)
PUGI__FN char_t tolower_ascii(char_t ch)
PUGI__FN void text_output_escaped(xml_buffered_writer &writer, const char_t *s, chartypex_t type)
void insert_attribute_after(xml_attribute_struct *attr, xml_attribute_struct *place, xml_node_struct *node)
#define PUGIXML_NOEXCEPT_IF_NOT_COMPACT
auto_deleter(T *data_, D deleter_)
bool operator()(const xpath_node &lhs, const xpath_node &rhs) const
bool operator()(const xpath_node &lhs, const xpath_node &rhs) const
bool operator()(const T &lhs, const T &rhs) const
char_t * flush(char_t *s)
void push(char_t *&s, size_t count)
static Traits::value_type process(const uint8_t *data, size_t size, typename Traits::value_type result, Traits)
static value_type high(value_type result, uint32_t ch)
static value_type low(value_type result, uint32_t ch)
bool operator()(const T &lhs, const T &rhs) const
bool operator()(const T &lhs, const T &rhs) const
name_null_sentry(xml_node_struct *node_)
namespace_uri_predicate(const char_t *name)
bool operator()(xml_attribute a) const
bool operator()(const T &lhs, const T &rhs) const
xml_attribute_struct * prev_attribute_c
xml_attribute_struct(impl::xml_memory_page *page)
xml_attribute_struct * next_attribute
xml_attribute_struct * first_attribute
xml_node_struct * prev_sibling_c
xml_node_struct * next_sibling
xml_node_struct * first_child
xml_node_struct(impl::xml_memory_page *page, xml_node_type type)
const char * description() const
const char * description() const
static char_t * parse_eol(char_t *s, char_t end_quote)
static char_t * parse_simple(char_t *s, char_t end_quote)
static char_t * parse_wnorm(char_t *s, char_t end_quote)
static char_t * parse_wconv(char_t *s, char_t end_quote)
static char_t * parse(char_t *s)
static value_type low(value_type result, uint32_t)
static value_type high(value_type result, uint32_t)
static Traits::value_type process(const uint16_t *data, size_t size, typename Traits::value_type result, Traits)
static value_type high(value_type result, uint32_t ch)
static value_type low(value_type result, uint32_t ch)
static value_type any(value_type result, uint32_t ch)
static value_type low(value_type result, uint32_t)
static value_type high(value_type result, uint32_t)
static Traits::value_type process(const uint32_t *data, size_t size, typename Traits::value_type result, Traits)
static value_type low(value_type result, uint32_t ch)
static value_type high(value_type result, uint32_t ch)
static value_type any(value_type result, uint32_t ch)
static value_type low(value_type result, uint32_t ch)
static value_type high(value_type result, uint32_t)
static Traits::value_type process(const uint8_t *data, size_t size, typename Traits::value_type result, Traits)
static value_type any(value_type result, uint32_t ch)
static value_type high(value_type result, uint32_t ch)
static value_type low(value_type result, uint32_t ch)
static Traits::value_type process(const wchar_t *data, size_t size, typename Traits::value_type result, Traits traits)
utf16_decoder< opt_false > decoder
utf32_decoder< opt_false > decoder
void * allocate_memory(size_t size, xml_memory_page *&out_page)
void * allocate_object(size_t size, xml_memory_page *&out_page)
char_t * allocate_string(size_t length)
static void deallocate_page(xml_memory_page *page)
void * allocate_memory_oob(size_t size, xml_memory_page *&out_page)
void deallocate_memory(void *ptr, size_t size, xml_memory_page *page)
xml_memory_page * allocate_page(size_t data_size)
xml_allocator(xml_memory_page *root)
void deallocate_string(char_t *string)
xml_document_struct(xml_memory_page *page)
xml_extra_buffer * extra_buffers
static deallocation_function deallocate
static allocation_function allocate
static xml_memory_page * construct(void *memory)
xml_allocator * allocator
static char_t * parse_skip_bom(char_t *s)
xml_parse_status error_status
xml_parser(xml_allocator *alloc_)
char_t * parse_doctype_primitive(char_t *s)
char_t * parse_tree(char_t *s, xml_node_struct *root, unsigned int optmsk, char_t endch)
static xml_parse_result parse(char_t *buffer, size_t length, xml_document_struct *xmldoc, xml_node_struct *root, unsigned int optmsk)
static bool has_element_node_siblings(xml_node_struct *node)
char_t * parse_doctype_group(char_t *s, char_t endch)
char_t * parse_question(char_t *s, xml_node_struct *&ref_cursor, unsigned int optmsk, char_t endch)
char_t * parse_doctype_ignore(char_t *s)
char_t * parse_exclamation(char_t *s, xml_node_struct *cursor, unsigned int optmsk, char_t endch)
static xml_stream_chunk * create()
T data[xml_memory_page_size/sizeof(T)]
static void destroy(xml_stream_chunk *chunk)
~xpath_allocator_capture()
xpath_allocator * _target
xpath_allocator_capture(xpath_allocator *alloc)
void * reallocate(void *ptr, size_t old_size, size_t new_size)
void * allocate(size_t size)
xpath_memory_block * _root
void revert(const xpath_allocator &state)
xpath_allocator(xpath_memory_block *root, bool *error=0)
xpath_context(const xpath_node &n_, size_t position_, size_t size_)
bool operator==(const char_t *other) const
char data[xpath_memory_page_size]
xpath_memory_block * next
binary_op_t(ast_type_t asttype_, xpath_value_type rettype_, int precedence_)
static binary_op_t parse(xpath_lexer &lexer)
xpath_ast_node * error(const char *message)
xpath_ast_node * parse_step(xpath_ast_node *set)
xpath_ast_node * error_oom()
xpath_variable_set * _variables
xpath_parser(const char_t *query, xpath_variable_set *variables, xpath_allocator *alloc, xpath_parse_result *result)
xpath_ast_node * alloc_node(ast_type_t type, xpath_ast_node *left, axis_t axis, nodetest_t test, const char_t *contents)
xpath_ast_node * parse_primary_expression()
xpath_ast_node * alloc_node(ast_type_t type, xpath_ast_node *left, xpath_ast_node *right, predicate_t test)
xpath_ast_node * alloc_node(ast_type_t type, xpath_value_type rettype, xpath_ast_node *left=0, xpath_ast_node *right=0)
xpath_ast_node * parse_filter_expression()
xpath_ast_node * parse_expression(int limit=0)
nodetest_t parse_node_test_type(const xpath_lexer_string &name)
const char_t * alloc_string(const xpath_lexer_string &value)
xpath_parse_result * _result
xpath_ast_node * parse_function(const xpath_lexer_string &name, size_t argc, xpath_ast_node *args[2])
xpath_ast_node * alloc_node(ast_type_t type, xpath_value_type rettype, xpath_variable *value)
xpath_ast_node * alloc_node(ast_type_t type, xpath_value_type rettype, double value)
static xpath_ast_node * parse(const char_t *query, xpath_variable_set *variables, xpath_allocator *alloc, xpath_parse_result *result)
xpath_ast_node * parse_path_or_unary_expression()
axis_t parse_axis_name(const xpath_lexer_string &name, bool &specified)
xpath_ast_node * parse_expression_rec(xpath_ast_node *lhs, int limit)
xpath_ast_node * parse_relative_location_path(xpath_ast_node *set)
xpath_ast_node * alloc_node(ast_type_t type, xpath_value_type rettype, const char_t *value)
xpath_ast_node * parse_location_path()
static void destroy(xpath_query_impl *impl)
static xpath_query_impl * create()
xpath_memory_block blocks[2]
xpath_variable_node_set()