14#ifndef SOURCE_PUGIXML_CPP
15#define SOURCE_PUGIXML_CPP
25#ifdef PUGIXML_WCHAR_MODE
29#ifndef PUGIXML_NO_XPATH
45# pragma warning(disable: 4127)
46# pragma warning(disable: 4324)
47# pragma warning(disable: 4702)
48# pragma warning(disable: 4996)
51#if defined(_MSC_VER) && defined(__c2__)
52# pragma clang diagnostic push
53# pragma clang diagnostic ignored "-Wdeprecated"
56#ifdef __INTEL_COMPILER
57# pragma warning(disable: 177)
58# pragma warning(disable: 279)
59# pragma warning(disable: 1478 1786)
60# pragma warning(disable: 1684)
63#if defined(__BORLANDC__) && defined(PUGIXML_HEADER_ONLY)
75# pragma diag_suppress=178
76# pragma diag_suppress=237
79#ifdef __TI_COMPILER_VERSION__
80# pragma diag_suppress 179
84#if defined(_MSC_VER) && _MSC_VER >= 1300
85# define PUGI__NO_INLINE __declspec(noinline)
86#elif defined(__GNUC__)
87# define PUGI__NO_INLINE __attribute__((noinline))
89# define PUGI__NO_INLINE
93#if defined(__GNUC__) && !defined(__c2__)
94# define PUGI__UNLIKELY(cond) __builtin_expect(cond, 0)
96# define PUGI__UNLIKELY(cond) (cond)
100#define PUGI__STATIC_ASSERT(cond) { static const char condition_failed[(cond) ? 1 : -1] = {0}; (void)condition_failed[0]; }
104# define PUGI__DMC_VOLATILE volatile
106# define PUGI__DMC_VOLATILE
110#if defined(__clang__) && defined(__has_attribute)
111# if __has_attribute(no_sanitize)
112# define PUGI__UNSIGNED_OVERFLOW __attribute__((no_sanitize("unsigned-integer-overflow")))
114# define PUGI__UNSIGNED_OVERFLOW
117# define PUGI__UNSIGNED_OVERFLOW
121#if defined(__BORLANDC__) && !defined(__MEM_H_USING_LIST)
128#if defined(PUGIXML_HAS_LONG_LONG) && defined(__GNUC__) && !defined(LLONG_MAX) && !defined(LLONG_MIN) && !defined(ULLONG_MAX)
129# define LLONG_MIN (-LLONG_MAX - 1LL)
130# define LLONG_MAX __LONG_LONG_MAX__
131# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
135#if defined(_MSC_VER) && !defined(__S3E__) && !defined(_WIN32_WCE)
136# define PUGI__MSVC_CRT_VERSION _MSC_VER
137#elif defined(_WIN32_WCE)
138# define PUGI__MSVC_CRT_VERSION 1310
142#if __cplusplus >= 201103
143# define PUGI__SNPRINTF(buf, ...) snprintf(buf, sizeof(buf), __VA_ARGS__)
144#elif defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400
145# define PUGI__SNPRINTF(buf, ...) _snprintf_s(buf, _countof(buf), _TRUNCATE, __VA_ARGS__)
147# define PUGI__SNPRINTF sprintf
151#ifdef PUGIXML_HEADER_ONLY
152# define PUGI__NS_BEGIN namespace pugi { namespace impl {
153# define PUGI__NS_END } }
154# define PUGI__FN inline
155# define PUGI__FN_NO_INLINE inline
157# if defined(_MSC_VER) && _MSC_VER < 1300
158# define PUGI__NS_BEGIN namespace pugi { namespace impl {
159# define PUGI__NS_END } }
161# define PUGI__NS_BEGIN namespace pugi { namespace impl { namespace {
162# define PUGI__NS_END } } }
165# define PUGI__FN_NO_INLINE PUGI__NO_INLINE
169#if (defined(_MSC_VER) && _MSC_VER < 1600) || (defined(__BORLANDC__) && __BORLANDC__ < 0x561)
172# ifndef _UINTPTR_T_DEFINED
173 typedef size_t uintptr_t;
176 typedef unsigned __int8 uint8_t;
177 typedef unsigned __int16 uint16_t;
178 typedef unsigned __int32 uint32_t;
196 template <
typename T>
218 #ifdef PUGIXML_WCHAR_MODE
230 #ifdef PUGIXML_WCHAR_MODE
231 return wcscmp(src, dst) == 0;
233 return strcmp(src, dst) == 0;
240 for (
size_t i = 0; i < count; ++i)
241 if (lhs[i] != rhs[i])
244 return lhs[count] == 0;
252 #ifdef PUGIXML_WCHAR_MODE
255 const wchar_t* end = s;
257 return static_cast<size_t>(end - s);
266 typedef void (*
D)(T*);
289#ifdef PUGIXML_COMPACT
291 class compact_hash_table
294 compact_hash_table(): _items(0), _capacity(0), _count(0)
309 void* find(
const void* key)
311 if (_capacity == 0)
return 0;
313 item_t* item = get_item(key);
315 assert(item->key == key || (item->key == 0 && item->value == 0));
320 void insert(
const void* key,
void* value)
322 assert(_capacity != 0 && _count < _capacity - _capacity / 4);
324 item_t* item = get_item(key);
336 bool reserve(
size_t extra = 16)
338 if (_count + extra >= _capacity - _capacity / 4)
339 return rehash(_count + extra);
356 bool rehash(
size_t count);
358 item_t* get_item(
const void* key)
361 assert(_capacity > 0);
363 size_t hashmod = _capacity - 1;
364 size_t bucket = hash(key) & hashmod;
366 for (
size_t probe = 0; probe <= hashmod; ++probe)
368 item_t& probe_item = _items[bucket];
370 if (probe_item.key == key || probe_item.key == 0)
374 bucket = (bucket + probe + 1) & hashmod;
377 assert(
false &&
"Hash table is full");
383 unsigned int h =
static_cast<unsigned int>(
reinterpret_cast<uintptr_t
>(key) & 0xffffffff);
398 size_t capacity = 32;
399 while (count >= capacity - capacity / 4)
402 compact_hash_table rt;
403 rt._capacity = capacity;
409 memset(rt._items, 0,
sizeof(item_t) * capacity);
411 for (
size_t i = 0; i < _capacity; ++i)
413 rt.insert(_items[i].key, _items[i].value);
418 _capacity = capacity;
421 assert(_count == rt._count);
430#ifdef PUGIXML_COMPACT
446#ifdef PUGIXML_COMPACT
447 #define PUGI__GETHEADER_IMPL(object, page, flags)
448 #define PUGI__GETPAGE_IMPL(header) (header).get_page()
450 #define PUGI__GETHEADER_IMPL(object, page, flags) (((reinterpret_cast<char*>(object) - reinterpret_cast<char*>(page)) << 8) | (flags))
452 #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))))
455 #define PUGI__GETPAGE(n) PUGI__GETPAGE_IMPL((n)->header)
456 #define PUGI__NODETYPE(n) static_cast<xml_node_type>((n)->header & impl::xml_memory_page_type_mask)
472 #ifdef PUGIXML_COMPACT
473 result->compact_string_base = 0;
474 result->compact_shared_parent = 0;
475 result->compact_page_marker = 0;
489 #ifdef PUGIXML_COMPACT
490 char_t* compact_string_base;
491 void* compact_shared_parent;
492 uint32_t* compact_page_marker;
497 #ifdef PUGIXML_MEMORY_PAGE_SIZE
498 (PUGIXML_MEMORY_PAGE_SIZE)
514 #ifdef PUGIXML_COMPACT
525 if (!memory)
return 0;
558 #ifdef PUGIXML_COMPACT
562 if (!result)
return 0;
565 ptrdiff_t offset =
static_cast<char*
>(result) -
reinterpret_cast<char*
>(out_page->compact_page_marker);
570 uint32_t* marker =
static_cast<uint32_t*
>(result);
572 *marker =
static_cast<uint32_t
>(
reinterpret_cast<char*
>(marker) -
reinterpret_cast<char*
>(out_page));
573 out_page->compact_page_marker = marker;
610 assert(
_root == page);
616 #ifdef PUGIXML_COMPACT
618 page->compact_string_base = 0;
619 page->compact_shared_parent = 0;
620 page->compact_page_marker = 0;
627 assert(
_root != page);
655 if (!header)
return 0;
658 ptrdiff_t page_offset =
reinterpret_cast<char*
>(header) -
reinterpret_cast<char*
>(page) -
sizeof(
xml_memory_page);
661 assert(page_offset >= 0 &&
static_cast<size_t>(page_offset) < max_encoded_offset);
666 assert(full_size < max_encoded_offset || (page->
busy_size == full_size && page_offset == 0));
671 return static_cast<char_t*
>(
static_cast<void*
>(header + 1));
695 #ifdef PUGIXML_COMPACT
696 return _hash->reserve();
705 #ifdef PUGIXML_COMPACT
706 compact_hash_table* _hash;
719 if (size <= large_allocation_threshold)
749#ifdef PUGIXML_COMPACT
751 static const uintptr_t compact_alignment_log2 = 2;
752 static const uintptr_t compact_alignment = 1 << compact_alignment_log2;
761 ptrdiff_t offset = (
reinterpret_cast<char*
>(
this) -
reinterpret_cast<char*
>(page->compact_page_marker));
762 assert(offset % compact_alignment == 0 &&
static_cast<uintptr_t
>(offset) < 256 * compact_alignment);
764 _page =
static_cast<unsigned char>(offset >> compact_alignment_log2);
765 _flags =
static_cast<unsigned char>(flags);
768 void operator&=(uintptr_t mod)
770 _flags &=
static_cast<unsigned char>(mod);
773 void operator|=(uintptr_t mod)
775 _flags |=
static_cast<unsigned char>(mod);
786 const char* page_marker =
reinterpret_cast<const char*
>(
this) - (_page << compact_alignment_log2);
787 const char* page = page_marker - *
reinterpret_cast<const uint32_t*
>(
static_cast<const void*
>(page_marker));
794 unsigned char _flags;
799 const compact_header* header =
reinterpret_cast<const compact_header*
>(
static_cast<const char*
>(object) - header_offset);
801 return header->get_page();
804 template <
int header_offset,
typename T>
PUGI__FN_NO_INLINE T* compact_get_value(
const void*
object)
806 return static_cast<T*
>(compact_get_page(
object, header_offset)->allocator->_hash->find(
object));
809 template <
int header_offset,
typename T>
PUGI__FN_NO_INLINE void compact_set_value(
const void*
object, T* value)
811 compact_get_page(
object, header_offset)->allocator->_hash->insert(
object, value);
814 template <
typename T,
int header_offset,
int start = -126>
class compact_pointer
817 compact_pointer(): _data(0)
821 void operator=(
const compact_pointer& rhs)
826 void operator=(T* value)
834 ptrdiff_t diff =
reinterpret_cast<char*
>(value) -
reinterpret_cast<char*
>(
this);
835 ptrdiff_t offset = ((diff + int(compact_alignment - 1)) >> compact_alignment_log2) - start;
837 if (
static_cast<uintptr_t
>(offset) <= 253)
838 _data =
static_cast<unsigned char>(offset + 1);
841 compact_set_value<header_offset>(
this, value);
856 uintptr_t base =
reinterpret_cast<uintptr_t
>(
this) & ~(compact_alignment - 1);
858 return reinterpret_cast<T*
>(base + (_data - 1 + start) * compact_alignment);
861 return compact_get_value<header_offset, T>(
this);
867 T* operator->()
const
876 template <
typename T,
int header_offset>
class compact_pointer_parent
879 compact_pointer_parent(): _data(0)
883 void operator=(
const compact_pointer_parent& rhs)
888 void operator=(T* value)
896 ptrdiff_t diff =
reinterpret_cast<char*
>(value) -
reinterpret_cast<char*
>(
this);
897 ptrdiff_t offset = ((diff + int(compact_alignment - 1)) >> compact_alignment_log2) + 65533;
899 if (
static_cast<uintptr_t
>(offset) <= 65533)
901 _data =
static_cast<unsigned short>(offset + 1);
908 page->compact_shared_parent = value;
910 if (page->compact_shared_parent == value)
916 compact_set_value<header_offset>(
this, value);
934 uintptr_t base =
reinterpret_cast<uintptr_t
>(
this) & ~(compact_alignment - 1);
936 return reinterpret_cast<T*
>(base + (_data - 1 - 65533) * compact_alignment);
938 else if (_data == 65534)
939 return static_cast<T*
>(compact_get_page(
this, header_offset)->compact_shared_parent);
941 return compact_get_value<header_offset, T>(
this);
947 T* operator->()
const
956 template <
int header_offset,
int base_offset>
class compact_string
959 compact_string(): _data(0)
963 void operator=(
const compact_string& rhs)
968 void operator=(char_t* value)
975 page->compact_string_base = value;
977 ptrdiff_t offset = value - page->compact_string_base;
979 if (
static_cast<uintptr_t
>(offset) < (65535 << 7))
982 uint16_t* base =
reinterpret_cast<uint16_t*
>(
static_cast<void*
>(
reinterpret_cast<char*
>(
this) - base_offset));
986 *base =
static_cast<uint16_t
>((offset >> 7) + 1);
987 _data =
static_cast<unsigned char>((offset & 127) + 1);
991 ptrdiff_t remainder = offset - ((*base - 1) << 7);
993 if (
static_cast<uintptr_t
>(remainder) <= 253)
995 _data =
static_cast<unsigned char>(remainder + 1);
999 compact_set_value<header_offset>(
this, value);
1007 compact_set_value<header_offset>(
this, value);
1027 const uint16_t* base =
reinterpret_cast<const uint16_t*
>(
static_cast<const void*
>(
reinterpret_cast<const char*
>(
this) - base_offset));
1030 ptrdiff_t offset = ((*base - 1) << 7) + (_data - 1);
1032 return page->compact_string_base + offset;
1036 return compact_get_value<header_offset, char_t>(
this);
1044 unsigned char _data;
1049#ifdef PUGIXML_COMPACT
1052 struct xml_attribute_struct
1059 impl::compact_header
header;
1061 uint16_t namevalue_base;
1063 impl::compact_string<4, 2>
name;
1064 impl::compact_string<5, 3>
value;
1067 impl::compact_pointer<xml_attribute_struct, 7, 0>
next_attribute;
1070 struct xml_node_struct
1077 impl::compact_header
header;
1079 uint16_t namevalue_base;
1081 impl::compact_string<4, 2>
name;
1082 impl::compact_string<5, 3>
value;
1084 impl::compact_pointer_parent<xml_node_struct, 6>
parent;
1086 impl::compact_pointer<xml_node_struct, 8, 0>
first_child;
1089 impl::compact_pointer<xml_node_struct, 10, 0>
next_sibling;
1154 #ifdef PUGIXML_COMPACT
1155 compact_hash_table hash;
1179 void* memory = alloc.
allocate_object(
sizeof(xml_attribute_struct), page);
1180 if (!memory)
return 0;
1182 return new (memory) xml_attribute_struct(page);
1189 if (!memory)
return 0;
1191 return new (memory) xml_node_struct(page, type);
1196 if (a->header & impl::xml_memory_page_name_allocated_mask)
1199 if (a->header & impl::xml_memory_page_value_allocated_mask)
1207 if (n->header & impl::xml_memory_page_name_allocated_mask)
1210 if (n->header & impl::xml_memory_page_value_allocated_mask)
1213 for (xml_attribute_struct* attr = n->first_attribute; attr; )
1215 xml_attribute_struct* next = attr->next_attribute;
1222 for (xml_node_struct* child = n->first_child; child; )
1224 xml_node_struct* next = child->next_sibling;
1234 inline void append_node(xml_node_struct* child, xml_node_struct* node)
1236 child->parent = node;
1238 xml_node_struct* head = node->first_child;
1242 xml_node_struct* tail = head->prev_sibling_c;
1244 tail->next_sibling = child;
1245 child->prev_sibling_c = tail;
1246 head->prev_sibling_c = child;
1250 node->first_child = child;
1251 child->prev_sibling_c = child;
1257 child->parent = node;
1259 xml_node_struct* head = node->first_child;
1263 child->prev_sibling_c = head->prev_sibling_c;
1264 head->prev_sibling_c = child;
1267 child->prev_sibling_c = child;
1269 child->next_sibling = head;
1270 node->first_child = child;
1275 xml_node_struct* parent = node->parent;
1277 child->parent = parent;
1279 if (node->next_sibling)
1280 node->next_sibling->prev_sibling_c = child;
1282 parent->first_child->prev_sibling_c = child;
1284 child->next_sibling = node->next_sibling;
1285 child->prev_sibling_c = node;
1287 node->next_sibling = child;
1292 xml_node_struct* parent = node->parent;
1294 child->parent = parent;
1296 if (node->prev_sibling_c->next_sibling)
1297 node->prev_sibling_c->next_sibling = child;
1299 parent->first_child = child;
1301 child->prev_sibling_c = node->prev_sibling_c;
1302 child->next_sibling = node;
1304 node->prev_sibling_c = child;
1309 xml_node_struct* parent = node->parent;
1311 if (node->next_sibling)
1312 node->next_sibling->prev_sibling_c = node->prev_sibling_c;
1314 parent->first_child->prev_sibling_c = node->prev_sibling_c;
1316 if (node->prev_sibling_c->next_sibling)
1317 node->prev_sibling_c->next_sibling = node->next_sibling;
1319 parent->first_child = node->next_sibling;
1322 node->prev_sibling_c = 0;
1323 node->next_sibling = 0;
1328 xml_attribute_struct* head = node->first_attribute;
1332 xml_attribute_struct* tail = head->prev_attribute_c;
1334 tail->next_attribute = attr;
1335 attr->prev_attribute_c = tail;
1336 head->prev_attribute_c = attr;
1340 node->first_attribute = attr;
1341 attr->prev_attribute_c = attr;
1347 xml_attribute_struct* head = node->first_attribute;
1351 attr->prev_attribute_c = head->prev_attribute_c;
1352 head->prev_attribute_c = attr;
1355 attr->prev_attribute_c = attr;
1357 attr->next_attribute = head;
1358 node->first_attribute = attr;
1363 if (place->next_attribute)
1364 place->next_attribute->prev_attribute_c = attr;
1366 node->first_attribute->prev_attribute_c = attr;
1368 attr->next_attribute = place->next_attribute;
1369 attr->prev_attribute_c = place;
1370 place->next_attribute = attr;
1375 if (place->prev_attribute_c->next_attribute)
1376 place->prev_attribute_c->next_attribute = attr;
1378 node->first_attribute = attr;
1380 attr->prev_attribute_c = place->prev_attribute_c;
1381 attr->next_attribute = place;
1382 place->prev_attribute_c = attr;
1387 if (attr->next_attribute)
1388 attr->next_attribute->prev_attribute_c = attr->prev_attribute_c;
1390 node->first_attribute->prev_attribute_c = attr->prev_attribute_c;
1392 if (attr->prev_attribute_c->next_attribute)
1393 attr->prev_attribute_c->next_attribute = attr->next_attribute;
1395 node->first_attribute = attr->next_attribute;
1397 attr->prev_attribute_c = 0;
1398 attr->next_attribute = 0;
1403 if (!alloc.
reserve())
return 0;
1406 if (!child)
return 0;
1415 if (!alloc.
reserve())
return 0;
1418 if (!attr)
return 0;
1443 return static_cast<uint16_t
>(((value & 0xff) << 8) | (value >> 8));
1448 return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value & 0xff0000) >> 8) | (value >> 24);
1458 if (ch < 0x80)
return result + 1;
1460 else if (ch < 0x800)
return result + 2;
1462 else return result + 3;
1481 *result =
static_cast<uint8_t
>(ch);
1485 else if (ch < 0x800)
1487 result[0] =
static_cast<uint8_t
>(0xC0 | (ch >> 6));
1488 result[1] =
static_cast<uint8_t
>(0x80 | (ch & 0x3F));
1494 result[0] =
static_cast<uint8_t
>(0xE0 | (ch >> 12));
1495 result[1] =
static_cast<uint8_t
>(0x80 | ((ch >> 6) & 0x3F));
1496 result[2] =
static_cast<uint8_t
>(0x80 | (ch & 0x3F));
1504 result[0] =
static_cast<uint8_t
>(0xF0 | (ch >> 18));
1505 result[1] =
static_cast<uint8_t
>(0x80 | ((ch >> 12) & 0x3F));
1506 result[2] =
static_cast<uint8_t
>(0x80 | ((ch >> 6) & 0x3F));
1507 result[3] =
static_cast<uint8_t
>(0x80 | (ch & 0x3F));
1513 return (ch < 0x10000) ?
low(result, ch) :
high(result, ch);
1538 *result =
static_cast<uint16_t
>(ch);
1545 uint32_t msh =
static_cast<uint32_t
>(ch - 0x10000) >> 10;
1546 uint32_t lsh =
static_cast<uint32_t
>(ch - 0x10000) & 0x3ff;
1548 result[0] =
static_cast<uint16_t
>(0xD800 + msh);
1549 result[1] =
static_cast<uint16_t
>(0xDC00 + lsh);
1556 return (ch < 0x10000) ?
low(result, ch) :
high(result, ch);
1607 *result =
static_cast<uint8_t
>(ch > 255 ?
'?' : ch);
1626 template <
typename Traits>
static inline typename Traits::value_type
process(
const uint8_t* data,
size_t size,
typename Traits::value_type result, Traits)
1628 const uint8_t utf8_byte_mask = 0x3f;
1632 uint8_t lead = *data;
1637 result = Traits::low(result, lead);
1642 if ((
reinterpret_cast<uintptr_t
>(data) & 3) == 0)
1645 while (size >= 4 && (*
static_cast<const uint32_t*
>(
static_cast<const void*
>(data)) & 0x80808080) == 0)
1647 result = Traits::low(result, data[0]);
1648 result = Traits::low(result, data[1]);
1649 result = Traits::low(result, data[2]);
1650 result = Traits::low(result, data[3]);
1657 else if (
static_cast<unsigned int>(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80)
1659 result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask));
1664 else if (
static_cast<unsigned int>(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80)
1666 result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask));
1671 else if (
static_cast<unsigned int>(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80)
1673 result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask));
1693 template <
typename Traits>
static inline typename Traits::value_type
process(
const uint16_t* data,
size_t size,
typename Traits::value_type result, Traits)
1697 uint16_t lead = opt_swap::value ?
endian_swap(*data) : *data;
1702 result = Traits::low(result, lead);
1707 else if (
static_cast<unsigned int>(lead - 0xE000) < 0x2000)
1709 result = Traits::low(result, lead);
1714 else if (
static_cast<unsigned int>(lead - 0xD800) < 0x400 && size >= 2)
1716 uint16_t next = opt_swap::value ?
endian_swap(data[1]) : data[1];
1718 if (
static_cast<unsigned int>(next - 0xDC00) < 0x400)
1720 result = Traits::high(result, 0x10000 + ((lead & 0x3ff) << 10) + (next & 0x3ff));
1745 template <
typename Traits>
static inline typename Traits::value_type
process(
const uint32_t* data,
size_t size,
typename Traits::value_type result, Traits)
1749 uint32_t lead = opt_swap::value ?
endian_swap(*data) : *data;
1754 result = Traits::low(result, lead);
1761 result = Traits::high(result, lead);
1775 template <
typename Traits>
static inline typename Traits::value_type
process(
const uint8_t* data,
size_t size,
typename Traits::value_type result, Traits)
1779 result = Traits::low(result, *data);
1813 template <
typename Traits>
static inline typename Traits::value_type
process(
const wchar_t* data,
size_t size,
typename Traits::value_type result, Traits traits)
1817 return decoder::process(
reinterpret_cast<const typename decoder::type*
>(data), size, result, traits);
1821#ifdef PUGIXML_WCHAR_MODE
1822 PUGI__FN void convert_wchar_endian_swap(
wchar_t* result,
const wchar_t* data,
size_t length)
1824 for (
size_t i = 0; i < length; ++i)
1845 55, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 63, 0, 0,
1846 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1847 8, 0, 6, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 96, 64, 0,
1848 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 0, 1, 0, 48, 0,
1849 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1850 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 16, 0, 192,
1851 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1852 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 0, 0, 0,
1854 192, 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, 192, 192, 192, 192, 192,
1856 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
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
1875 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 2, 3, 3,
1876 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1877 0, 0, 2, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 16, 16, 0,
1878 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 3, 0, 1, 0,
1880 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1881 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 20,
1882 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1883 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0,
1885 20, 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, 20, 20, 20, 20, 20,
1887 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
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
1895#ifdef PUGIXML_WCHAR_MODE
1896 #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) ((static_cast<unsigned int>(c) < 128 ? table[static_cast<unsigned int>(c)] : table[128]) & (ct))
1898 #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast<unsigned char>(c)] & (ct))
1901 #define PUGI__IS_CHARTYPE(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartype_table)
1902 #define PUGI__IS_CHARTYPEX(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartypex_table)
1906 unsigned int ui = 1;
1908 return *
reinterpret_cast<unsigned char*
>(&ui) == 1;
1915 if (
sizeof(
wchar_t) == 2)
1923 #define PUGI__SCANCHAR(ch) { if (offset >= size || data[offset] != ch) return false; offset++; }
1924 #define PUGI__SCANCHARTYPE(ct) { while (offset < size && PUGI__IS_CHARTYPE(data[offset], ct)) offset++; }
1927 if (size < 6 || !((data[0] ==
'<') & (data[1] ==
'?') & (data[2] ==
'x') & (data[3] ==
'm') & (data[4] ==
'l') &&
PUGI__IS_CHARTYPE(data[5],
ct_space)))
1931 for (
size_t i = 6; i + 1 < size; ++i)
1937 if (data[i] ==
'e' && data[i + 1] ==
'n')
1951 uint8_t delimiter = (offset < size && data[offset] ==
'"') ?
'"' :
'\'';
1955 size_t start = offset;
1957 out_encoding = data + offset;
1961 out_length = offset - start;
1971 #undef PUGI__SCANCHAR
1972 #undef PUGI__SCANCHARTYPE
1978 if (size < 4)
return encoding_utf8;
1980 uint8_t d0 = data[0], d1 = data[1], d2 = data[2], d3 = data[3];
1983 if (d0 == 0 && d1 == 0 && d2 == 0xfe && d3 == 0xff)
return encoding_utf32_be;
1984 if (d0 == 0xff && d1 == 0xfe && d2 == 0 && d3 == 0)
return encoding_utf32_le;
1985 if (d0 == 0xfe && d1 == 0xff)
return encoding_utf16_be;
1986 if (d0 == 0xff && d1 == 0xfe)
return encoding_utf16_le;
1987 if (d0 == 0xef && d1 == 0xbb && d2 == 0xbf)
return encoding_utf8;
1990 if (d0 == 0 && d1 == 0 && d2 == 0 && d3 == 0x3c)
return encoding_utf32_be;
1991 if (d0 == 0x3c && d1 == 0 && d2 == 0 && d3 == 0)
return encoding_utf32_le;
1992 if (d0 == 0 && d1 == 0x3c && d2 == 0 && d3 == 0x3f)
return encoding_utf16_be;
1993 if (d0 == 0x3c && d1 == 0 && d2 == 0x3f && d3 == 0)
return encoding_utf16_le;
1996 if (d0 == 0 && d1 == 0x3c)
return encoding_utf16_be;
1997 if (d0 == 0x3c && d1 == 0)
return encoding_utf16_le;
2000 const uint8_t* enc = 0;
2001 size_t enc_length = 0;
2006 if (enc_length == 10
2007 && (enc[0] |
' ') ==
'i' && (enc[1] |
' ') ==
's' && (enc[2] |
' ') ==
'o'
2008 && enc[3] ==
'-' && enc[4] ==
'8' && enc[5] ==
'8' && enc[6] ==
'5' && enc[7] ==
'9'
2009 && enc[8] ==
'-' && enc[9] ==
'1')
2010 return encoding_latin1;
2014 && (enc[0] |
' ') ==
'l' && (enc[1] |
' ') ==
'a' && (enc[2] |
' ') ==
't'
2015 && (enc[3] |
' ') ==
'i' && (enc[4] |
' ') ==
'n'
2017 return encoding_latin1;
2020 return encoding_utf8;
2029 if (encoding == encoding_utf16)
return is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
2032 if (encoding == encoding_utf32)
return is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
2035 if (encoding != encoding_auto)
return encoding;
2038 const uint8_t* data =
static_cast<const uint8_t*
>(contents);
2045 size_t length = size /
sizeof(char_t);
2049 out_buffer =
static_cast<char_t*
>(
const_cast<void*
>(contents));
2050 out_length = length;
2055 if (!buffer)
return false;
2058 memcpy(buffer, contents, length *
sizeof(char_t));
2060 assert(length == 0);
2064 out_buffer = buffer;
2065 out_length = length + 1;
2071#ifdef PUGIXML_WCHAR_MODE
2072 PUGI__FN bool need_endian_swap_utf(xml_encoding le, xml_encoding re)
2078 PUGI__FN bool convert_buffer_endian_swap(char_t*& out_buffer,
size_t& out_length,
const void* contents,
size_t size,
bool is_mutable)
2080 const char_t* data =
static_cast<const char_t*
>(contents);
2081 size_t length = size /
sizeof(
char_t);
2087 convert_wchar_endian_swap(buffer, data, length);
2089 out_buffer = buffer;
2090 out_length = length;
2095 if (!buffer)
return false;
2097 convert_wchar_endian_swap(buffer, data, length);
2100 out_buffer = buffer;
2101 out_length = length + 1;
2109 const typename D::type* data =
static_cast<const typename D::type*
>(contents);
2110 size_t data_length = size /
sizeof(
typename D::type);
2113 size_t length = D::process(data, data_length, 0,
wchar_counter());
2117 if (!buffer)
return false;
2120 wchar_writer::value_type obegin =
reinterpret_cast<wchar_writer::value_type
>(buffer);
2121 wchar_writer::value_type oend = D::process(data, data_length, obegin,
wchar_writer());
2123 assert(oend == obegin + length);
2126 out_buffer = buffer;
2127 out_length = length + 1;
2132 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)
2138 if (encoding == wchar_encoding)
2142 if (need_endian_swap_utf(encoding, wchar_encoding))
2143 return convert_buffer_endian_swap(out_buffer, out_length, contents, size, is_mutable);
2146 if (encoding == encoding_utf8)
2150 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
2154 return (native_encoding == encoding) ?
2160 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
2164 return (native_encoding == encoding) ?
2170 if (encoding == encoding_latin1)
2173 assert(
false &&
"Invalid encoding");
2179 const typename D::type* data =
static_cast<const typename D::type*
>(contents);
2180 size_t data_length = size /
sizeof(
typename D::type);
2183 size_t length = D::process(data, data_length, 0,
utf8_counter());
2187 if (!buffer)
return false;
2190 uint8_t* obegin =
reinterpret_cast<uint8_t*
>(buffer);
2191 uint8_t* oend = D::process(data, data_length, obegin,
utf8_writer());
2193 assert(oend == obegin + length);
2196 out_buffer = buffer;
2197 out_length = length + 1;
2204 for (
size_t i = 0; i < size; ++i)
2213 const uint8_t* data =
static_cast<const uint8_t*
>(contents);
2214 size_t data_length = size;
2218 assert(prefix_length <= data_length);
2220 const uint8_t* postfix = data + prefix_length;
2221 size_t postfix_length = data_length - prefix_length;
2224 if (postfix_length == 0)
return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable);
2231 if (!buffer)
return false;
2234 memcpy(buffer, data, prefix_length);
2236 uint8_t* obegin =
reinterpret_cast<uint8_t*
>(buffer);
2239 assert(oend == obegin + length);
2242 out_buffer = buffer;
2243 out_length = length + 1;
2248 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)
2251 if (encoding == encoding_utf8)
2255 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
2257 xml_encoding native_encoding =
is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
2259 return (native_encoding == encoding) ?
2265 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
2267 xml_encoding native_encoding =
is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
2269 return (native_encoding == encoding) ?
2275 if (encoding == encoding_latin1)
2278 assert(
false &&
"Invalid encoding");
2292 uint8_t* begin =
reinterpret_cast<uint8_t*
>(buffer);
2295 assert(begin + size == end);
2300#ifndef PUGIXML_NO_STL
2308 result.resize(size);
2311 if (size > 0)
as_utf8_end(&result[0], size, str, length);
2318 const uint8_t* data =
reinterpret_cast<const uint8_t*
>(str);
2324 std::basic_string<wchar_t> result;
2325 result.resize(length);
2330 wchar_writer::value_type begin =
reinterpret_cast<wchar_writer::value_type
>(&result[0]);
2333 assert(begin + length == end);
2341 template <
typename Header>
2347 size_t target_length =
strlength(target);
2350 if ((header & header_mask) == 0)
return target_length >= length;
2353 const size_t reuse_threshold = 32;
2355 return target_length >= length && (target_length < reuse_threshold || target_length - length < target_length / 2);
2358 template <
typename String,
typename Header>
2359 PUGI__FN bool strcpy_insitu(String& dest, Header& header, uintptr_t header_mask,
const char_t* source,
size_t source_length)
2361 if (source_length == 0)
2370 header &= ~header_mask;
2377 memcpy(dest, source, source_length *
sizeof(char_t));
2378 dest[source_length] = 0;
2386 if (!alloc->
reserve())
return false;
2390 if (!buf)
return false;
2393 memcpy(buf, source, source_length *
sizeof(char_t));
2394 buf[source_length] = 0;
2401 header |= header_mask;
2418 void push(char_t*& s,
size_t count)
2424 memmove(
end -
size,
end,
reinterpret_cast<char*
>(s) -
reinterpret_cast<char*
>(
end));
2441 memmove(
end -
size,
end,
reinterpret_cast<char*
>(s) -
reinterpret_cast<char*
>(
end));
2451 char_t* stre = s + 1;
2457 unsigned int ucsc = 0;
2465 if (ch ==
';')
return stre;
2469 if (
static_cast<unsigned int>(ch -
'0') <= 9)
2470 ucsc = 16 * ucsc + (ch -
'0');
2471 else if (
static_cast<unsigned int>((ch |
' ') -
'a') <= 5)
2472 ucsc = 16 * ucsc + ((ch |
' ') -
'a' + 10);
2485 char_t ch = *++stre;
2487 if (ch ==
';')
return stre;
2491 if (
static_cast<unsigned int>(ch -
'0') <= 9)
2492 ucsc = 10 * ucsc + (ch -
'0');
2504 #ifdef PUGIXML_WCHAR_MODE
2505 s =
reinterpret_cast<char_t*
>(wchar_writer::any(
reinterpret_cast<wchar_writer::value_type
>(s), ucsc));
2507 s =
reinterpret_cast<char_t*
>(
utf8_writer::any(
reinterpret_cast<uint8_t*
>(s), ucsc));
2510 g.
push(s, stre - s);
2520 if (*++stre ==
'p' && *++stre ==
';')
2525 g.
push(s, stre - s);
2529 else if (*stre ==
'p')
2531 if (*++stre ==
'o' && *++stre ==
's' && *++stre ==
';')
2536 g.
push(s, stre - s);
2545 if (*++stre ==
't' && *++stre ==
';')
2550 g.
push(s, stre - s);
2558 if (*++stre ==
't' && *++stre ==
';')
2563 g.
push(s, stre - s);
2571 if (*++stre ==
'u' && *++stre ==
'o' && *++stre ==
't' && *++stre ==
';')
2576 g.
push(s, stre - s);
2590 #define PUGI__ENDSWITH(c, e) ((c) == (e) || ((c) == 0 && endch == (e)))
2591 #define PUGI__SKIPWS() { while (PUGI__IS_CHARTYPE(*s, ct_space)) ++s; }
2592 #define PUGI__OPTSET(OPT) ( optmsk & (OPT) )
2593 #define PUGI__PUSHNODE(TYPE) { cursor = append_new_node(cursor, *alloc, TYPE); if (!cursor) PUGI__THROW_ERROR(status_out_of_memory, s); }
2594 #define PUGI__POPNODE() { cursor = cursor->parent; }
2595 #define PUGI__SCANFOR(X) { while (*s != 0 && !(X)) ++s; }
2596 #define PUGI__SCANWHILE(X) { while (X) ++s; }
2597 #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; } }
2598 #define PUGI__ENDSEG() { ch = *s; *s = 0; ++s; }
2599 #define PUGI__THROW_ERROR(err, m) return error_offset = m, error_status = err, static_cast<char_t*>(0)
2600 #define PUGI__CHECK_ERROR(err, m) { if (*s == 0) PUGI__THROW_ERROR(err, m); }
2614 if (*s ==
'\n') g.
push(s, 1);
2616 else if (s[0] ==
'-' && s[1] ==
'-' &&
PUGI__ENDSWITH(s[2],
'>'))
2620 return s + (s[2] ==
'>' ? 3 : 2);
2642 if (*s ==
'\n') g.
push(s, 1);
2644 else if (s[0] ==
']' && s[1] ==
']' &&
PUGI__ENDSWITH(s[2],
'>'))
2658 typedef char_t* (*strconv_pcdata_t)(char_t*);
2674 char_t* end = g.
flush(s);
2676 if (opt_trim::value)
2684 else if (opt_eol::value && *s ==
'\r')
2688 if (*s ==
'\n') g.
push(s, 1);
2690 else if (opt_escape::value && *s ==
'&')
2696 char_t* end = g.
flush(s);
2698 if (opt_trim::value)
2713 PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_trim_pcdata == 0x0800);
2715 switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4))
2725 default: assert(
false);
return 0;
2729 typedef char_t* (*strconv_attribute_t)(char_t*, char_t);
2752 if (*s == end_quote)
2754 char_t* str = g.
flush(s);
2767 char_t* str = s + 1;
2773 else if (opt_escape::value && *s ==
'&')
2793 if (*s == end_quote)
2805 if (*s ==
'\n') g.
push(s, 1);
2809 else if (opt_escape::value && *s ==
'&')
2829 if (*s == end_quote)
2835 else if (*s ==
'\r')
2839 if (*s ==
'\n') g.
push(s, 1);
2841 else if (opt_escape::value && *s ==
'&')
2861 if (*s == end_quote)
2867 else if (opt_escape::value && *s ==
'&')
2882 PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80);
2884 switch ((optmask >> 4) & 15)
2902 default: assert(
false);
return 0;
2908 xml_parse_result result;
2909 result.status = status;
2910 result.offset = offset;
2934 if (*s ==
'"' || *s ==
'\'')
2943 else if (s[0] ==
'<' && s[1] ==
'?')
2952 else if (s[0] ==
'<' && s[1] ==
'!' && s[2] ==
'-' && s[3] ==
'-')
2969 assert(s[0] ==
'<' && s[1] ==
'!' && s[2] ==
'[');
2974 if (s[0] ==
'<' && s[1] ==
'!' && s[2] ==
'[')
2980 else if (s[0] ==
']' && s[1] ==
']' && s[2] ==
'>')
3000 assert((s[0] ==
'<' || s[0] == 0) && s[1] ==
'!');
3005 if (s[0] ==
'<' && s[1] ==
'!' && s[2] !=
'-')
3020 else if (s[0] ==
'<' || s[0] ==
'"' || s[0] ==
'\'')
3076 s += (s[2] ==
'>' ? 3 : 2);
3084 if (*++s==
'C' && *++s==
'D' && *++s==
'A' && *++s==
'T' && *++s==
'A' && *++s ==
'[')
3117 s += (s[1] ==
'>' ? 2 : 1);
3121 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'))
3127 char_t* mark = s + 9;
3132 assert((*s == 0 && endch ==
'>') || *s ==
'>');
3141 cursor->value = mark;
3151 char_t*
parse_question(char_t* s, xml_node_struct*& ref_cursor,
unsigned int optmsk, char_t endch)
3154 xml_node_struct* cursor = ref_cursor;
3169 bool declaration = (target[0] |
' ') ==
'x' && (target[1] |
' ') ==
'm' && (target[2] |
' ') ==
'l' && target + 3 == s;
3185 cursor->name = target;
3219 cursor->value = value;
3236 s += (s[1] ==
'>' ? 2 : 1);
3240 ref_cursor = cursor;
3245 char_t*
parse_tree(char_t* s, xml_node_struct* root,
unsigned int optmsk, char_t endch)
3251 xml_node_struct* cursor = root;
3303 if (*s ==
'"' || *s ==
'\'')
3309 s = strconv_attribute(s, ch);
3332 else if (*s == 0 && endch ==
'>')
3345 else if (*s == 0 && endch ==
'>')
3377 char_t* name = cursor->name;
3387 if (*s == 0 && name[0] == endch && name[1] == 0)
PUGI__THROW_ERROR(status_bad_end_element, s);
3411 if (
PUGI__NODETYPE(cursor) == node_declaration)
goto LOC_ATTRIBUTES;
3427 if (*s ==
'<' || !*s)
3438 if (s[0] !=
'<' || s[1] !=
'/' || cursor->first_child)
continue;
3447 if (
PUGI__OPTSET(parse_embed_pcdata) && cursor->parent && !cursor->first_child && !cursor->value)
3460 s = strconv_pcdata(s);
3483 #ifdef PUGIXML_WCHAR_MODE
3486 unsigned int bom = 0xfeff;
3487 return (s[0] ==
static_cast<wchar_t>(bom)) ? s + 1 : s;
3492 return (s[0] ==
'\xef' && s[1] ==
'\xbb' && s[2] ==
'\xbf') ? s + 3 : s;
3502 node = node->next_sibling;
3515 xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c + 0 : 0;
3521 char_t endch = buffer[length - 1];
3522 buffer[length - 1] = 0;
3528 parser.
parse_tree(buffer_data, root, optmsk, endch);
3531 assert(result.offset >= 0 &&
static_cast<size_t>(result.offset) <= length);
3540 xml_node_struct* first_root_child_parsed = last_root_child ? last_root_child->next_sibling + 0 : root->first_child+ 0;
3548 if (result.offset > 0 &&
static_cast<size_t>(result.offset) == length - 1 && endch == 0)
3559 #ifdef PUGIXML_WCHAR_MODE
3562 return encoding_utf8;
3572 if (encoding == encoding_utf16)
return is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
3575 if (encoding == encoding_utf32)
return is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
3578 if (encoding != encoding_auto)
return encoding;
3581 return encoding_utf8;
3588 typename T::value_type end = D::process(
reinterpret_cast<const typename D::type*
>(data), length, dest, T());
3590 return static_cast<size_t>(end - dest) *
sizeof(*dest);
3597 typename T::value_type end = D::process(
reinterpret_cast<const typename D::type*
>(data), length, dest, T());
3601 for (
typename T::value_type i = dest; i != end; ++i)
3605 return static_cast<size_t>(end - dest) *
sizeof(*dest);
3608#ifdef PUGIXML_WCHAR_MODE
3611 if (length < 1)
return 0;
3614 return (
sizeof(
wchar_t) == 2 &&
static_cast<unsigned int>(
static_cast<uint16_t
>(data[length - 1]) - 0xD800) < 0x400) ? length - 1 : length;
3617 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)
3622 convert_wchar_endian_swap(r_char, data, length);
3624 return length *
sizeof(
char_t);
3628 if (encoding == encoding_utf8)
3632 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
3640 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
3648 if (encoding == encoding_latin1)
3651 assert(
false &&
"Invalid encoding");
3657 if (length < 5)
return 0;
3659 for (
size_t i = 1; i <= 4; ++i)
3661 uint8_t ch =
static_cast<uint8_t
>(data[length - i]);
3664 if ((ch & 0xc0) != 0x80)
return length - i;
3673 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
3675 xml_encoding native_encoding =
is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
3680 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
3682 xml_encoding native_encoding =
is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
3687 if (encoding == encoding_latin1)
3690 assert(
false &&
"Invalid encoding");
3713 void flush(
const char_t* data,
size_t size)
3715 if (size == 0)
return;
3719 writer.write(data, size *
sizeof(char_t));
3724 assert(result <=
sizeof(
scratch));
3742 writer.write(data, length *
sizeof(char_t));
3755 flush(data, chunk_size);
3759 length -= chunk_size;
3776 memcpy(
buffer + offset, data, length *
sizeof(char_t));
3791 buffer[offset++] = *data++;
3801 size_t length = offset -
bufsize;
3829 void write(char_t d0, char_t d1, char_t d2)
3840 void write(char_t d0, char_t d1, char_t d2, char_t d3)
3852 void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4)
3865 void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4, char_t d5)
3885 #ifdef PUGIXML_MEMORY_OUTPUT_STACK
3886 PUGIXML_MEMORY_OUTPUT_STACK
3913 const char_t* prev = s;
3918 writer.
write_buffer(prev,
static_cast<size_t>(s - prev));
3924 writer.
write(
'&',
'a',
'm',
'p',
';');
3928 writer.
write(
'&',
'l',
't',
';');
3932 writer.
write(
'&',
'g',
't',
';');
3936 if (flags & format_attribute_single_quote)
3939 writer.
write(
'&',
'q',
'u',
'o',
't',
';');
3943 if (flags & format_attribute_single_quote)
3944 writer.
write(
'&',
'a',
'p',
'o',
's',
';');
3951 unsigned int ch =
static_cast<unsigned int>(*s++);
3954 if (!(flags & format_skip_control_chars))
3955 writer.
write(
'&',
'#',
static_cast<char_t
>((ch / 10) +
'0'),
static_cast<char_t
>((ch % 10) +
'0'),
';');
3963 if (flags & format_no_escapes)
3973 writer.
write(
'<',
'!',
'[',
'C',
'D');
3974 writer.
write(
'A',
'T',
'A',
'[');
3976 const char_t* prev = s;
3979 while (*s && !(s[0] ==
']' && s[1] ==
']' && s[2] ==
'>')) ++s;
3984 writer.
write_buffer(prev,
static_cast<size_t>(s - prev));
3986 writer.
write(
']',
']',
'>');
3993 switch (indent_length)
3997 for (
unsigned int i = 0; i < depth; ++i)
3998 writer.
write(indent[0]);
4004 for (
unsigned int i = 0; i < depth; ++i)
4005 writer.
write(indent[0], indent[1]);
4011 for (
unsigned int i = 0; i < depth; ++i)
4012 writer.
write(indent[0], indent[1], indent[2]);
4018 for (
unsigned int i = 0; i < depth; ++i)
4019 writer.
write(indent[0], indent[1], indent[2], indent[3]);
4025 for (
unsigned int i = 0; i < depth; ++i)
4033 writer.
write(
'<',
'!',
'-',
'-');
4037 const char_t* prev = s;
4040 while (*s && !(s[0] ==
'-' && (s[1] ==
'-' || s[1] == 0))) ++s;
4042 writer.
write_buffer(prev,
static_cast<size_t>(s - prev));
4048 writer.
write(
'-',
' ');
4053 writer.
write(
'-',
'-',
'>');
4060 const char_t* prev = s;
4063 while (*s && !(s[0] ==
'?' && s[1] ==
'>')) ++s;
4065 writer.
write_buffer(prev,
static_cast<size_t>(s - prev));
4069 assert(s[0] ==
'?' && s[1] ==
'>');
4071 writer.
write(
'?',
' ',
'>');
4079 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4080 const char_t enquotation_char = (flags & format_attribute_single_quote) ?
'\'' :
'"';
4082 for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute)
4084 if ((flags & (format_indent_attributes | format_raw)) == format_indent_attributes)
4095 writer.
write_string(a->name ? a->name + 0 : default_name);
4096 writer.
write(
'=', enquotation_char);
4101 writer.
write(enquotation_char);
4107 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4108 const char_t* name = node->name ? node->name + 0 : default_name;
4113 if (node->first_attribute)
4119 if (!node->first_child)
4121 if (flags & format_no_empty_element_tags)
4123 writer.
write(
'>',
'<',
'/');
4131 if ((flags & format_raw) == 0)
4134 writer.
write(
'/',
'>');
4152 if (!node->first_child)
4154 writer.
write(
'<',
'/');
4169 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4170 const char_t* name = node->name ? node->name + 0 : default_name;
4172 writer.
write(
'<',
'/');
4179 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4196 writer.
write(
'<',
'?');
4197 writer.
write_string(node->name ? node->name + 0 : default_name);
4205 writer.
write(
'?',
'>');
4208 case node_declaration:
4209 writer.
write(
'<',
'?');
4210 writer.
write_string(node->name ? node->name + 0 : default_name);
4212 writer.
write(
'?',
'>');
4216 writer.
write(
'<',
'!',
'D',
'O',
'C');
4217 writer.
write(
'T',
'Y',
'P',
'E');
4229 assert(
false &&
"Invalid node type");
4241 size_t indent_length = ((flags & (format_indent | format_indent_attributes)) && (flags & format_raw) == 0) ?
strlength(indent) : 0;
4244 xml_node_struct* node = root;
4259 if ((indent_flags &
indent_newline) && (flags & format_raw) == 0)
4275 node = node->first_child;
4284 if (node->first_child)
4286 node = node->first_child;
4299 while (node != root)
4301 if (node->next_sibling)
4303 node = node->next_sibling;
4307 node = node->parent;
4314 if ((indent_flags &
indent_newline) && (flags & format_raw) == 0)
4326 while (node != root);
4328 if ((indent_flags &
indent_newline) && (flags & format_raw) == 0)
4334 for (xml_node_struct* child = node->first_child; child; child = child->next_sibling)
4338 if (type == node_declaration)
return true;
4339 if (type == node_element)
return false;
4347 for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute)
4356 return parent == node_element || parent == node_declaration;
4361 if (parent != node_document && parent != node_element)
return false;
4362 if (child == node_document || child == node_null)
return false;
4363 if (parent != node_document && (child == node_declaration || child == node_doctype))
return false;
4375 if (parent.root() != child.root())
4379 xml_node cur = parent;
4392 template <
typename String,
typename Header>
4395 assert(!dest && (header & header_mask) == 0);
4399 if (alloc && (source_header & header_mask) == 0)
4417 for (xml_attribute_struct* sa = sn->first_attribute; sa; sa = sa->next_attribute)
4436 xml_node_struct* dit = dn;
4437 xml_node_struct* sit = sn->first_child;
4439 while (sit && sit != sn)
4453 if (sit->first_child)
4456 sit = sit->first_child;
4465 if (sit->next_sibling)
4467 sit = sit->next_sibling;
4475 assert(sit == sn || dit);
4480 assert(!sit || dit == dn->parent);
4496 return type == node_pcdata || type == node_cdata;
4503 const char_t* s = value;
4508 bool negative = (*s ==
'-');
4510 s += (*s ==
'+' || *s ==
'-');
4512 bool overflow =
false;
4514 if (s[0] ==
'0' && (s[1] |
' ') ==
'x')
4522 const char_t* start = s;
4526 if (
static_cast<unsigned>(*s -
'0') < 10)
4527 result = result * 16 + (*s -
'0');
4528 else if (
static_cast<unsigned>((*s |
' ') -
'a') < 6)
4529 result = result * 16 + ((*s |
' ') -
'a' + 10);
4536 size_t digits =
static_cast<size_t>(s - start);
4538 overflow = digits >
sizeof(U) * 2;
4546 const char_t* start = s;
4550 if (
static_cast<unsigned>(*s -
'0') < 10)
4551 result = result * 10 + (*s -
'0');
4558 size_t digits =
static_cast<size_t>(s - start);
4562 const size_t max_digits10 =
sizeof(U) == 8 ? 20 :
sizeof(U) == 4 ? 10 : 5;
4563 const char_t max_lead =
sizeof(U) == 8 ?
'1' :
sizeof(U) == 4 ?
'4' :
'6';
4564 const size_t high_bit =
sizeof(U) * 8 - 1;
4566 overflow = digits >= max_digits10 && !(digits == max_digits10 && (*start < max_lead || (*start == max_lead && result >> high_bit)));
4573 return (overflow || result > ~minv + 1) ? minv : ~result + 1;
4575 return (overflow || result > 0 - minv) ? minv : 0 - result;
4579 return (overflow || result > maxv) ? maxv : result;
4584 return string_to_integer<unsigned int>(value,
static_cast<unsigned int>(INT_MIN), INT_MAX);
4589 return string_to_integer<unsigned int>(value, 0, UINT_MAX);
4594 #ifdef PUGIXML_WCHAR_MODE
4595 return wcstod(value, 0);
4597 return strtod(value, 0);
4603 #ifdef PUGIXML_WCHAR_MODE
4604 return static_cast<float>(wcstod(value, 0));
4606 return static_cast<float>(strtod(value, 0));
4613 char_t first = *value;
4616 return (first ==
'1' || first ==
't' || first ==
'T' || first ==
'y' || first ==
'Y');
4619#ifdef PUGIXML_HAS_LONG_LONG
4620 PUGI__FN long long get_value_llong(
const char_t* value)
4622 return string_to_integer<unsigned long long>(value,
static_cast<unsigned long long>(LLONG_MIN), LLONG_MAX);
4625 PUGI__FN unsigned long long get_value_ullong(
const char_t* value)
4627 return string_to_integer<unsigned long long>(value, 0, ULLONG_MAX);
4633 char_t* result = end - 1;
4634 U rest = negative ? 0 - value : value;
4638 *result-- =
static_cast<char_t
>(
'0' + (rest % 10));
4643 assert(result >= begin);
4648 return result + !negative;
4652 template <
typename String,
typename Header>
4655 #ifdef PUGIXML_WCHAR_MODE
4657 assert(strlen(buf) <
sizeof(wbuf) /
sizeof(wbuf[0]));
4660 for (; buf[offset]; ++offset) wbuf[offset] = buf[offset];
4662 return strcpy_insitu(dest, header, header_mask, wbuf, offset);
4664 return strcpy_insitu(dest, header, header_mask, buf, strlen(buf));
4668 template <
typename U,
typename String,
typename Header>
4672 char_t* end = buf +
sizeof(buf) /
sizeof(buf[0]);
4675 return strcpy_insitu(dest, header, header_mask, begin, end - begin);
4678 template <
typename String,
typename Header>
4687 template <
typename String,
typename Header>
4696 template <
typename String,
typename Header>
4708 xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size);
4715 if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable))
return impl::make_parse_result(status_out_of_memory);
4718 if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents);
4721 if (own || buffer != contents) *out_buffer = buffer;
4727 xml_parse_result res = impl::xml_parser::parse(buffer, length, doc, root, options);
4730 res.encoding = buffer_encoding;
4738 #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400
4740 typedef __int64 length_type;
4742 _fseeki64(file, 0, SEEK_END);
4743 length_type length = _ftelli64(file);
4744 _fseeki64(file, 0, SEEK_SET);
4745 #elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))
4747 typedef off64_t length_type;
4749 fseeko64(file, 0, SEEK_END);
4750 length_type length = ftello64(file);
4751 fseeko64(file, 0, SEEK_SET);
4754 typedef long length_type;
4756 fseek(file, 0, SEEK_END);
4757 length_type length = ftell(file);
4758 fseek(file, 0, SEEK_SET);
4762 if (length < 0)
return status_io_error;
4765 size_t result =
static_cast<size_t>(length);
4767 if (
static_cast<length_type
>(result) != length)
return status_out_of_memory;
4770 out_result = result;
4779 #ifdef PUGIXML_WCHAR_MODE
4782 if (encoding == wchar_encoding || need_endian_swap_utf(encoding, wchar_encoding))
4784 size_t length = size /
sizeof(char_t);
4786 static_cast<char_t*
>(buffer)[length] = 0;
4787 return (length + 1) *
sizeof(char_t);
4790 if (encoding == encoding_utf8)
4792 static_cast<char*
>(buffer)[size] = 0;
4809 size_t max_suffix_size =
sizeof(char_t);
4816 size_t read_size = fread(contents, 1, size, file);
4818 if (read_size != size)
4826 return load_buffer_impl(doc, doc, contents,
zero_terminate_buffer(contents, size, real_encoding), options, real_encoding,
true,
true, out_buffer);
4834#ifndef PUGIXML_NO_STL
4840 if (!memory)
return 0;
4876 while (!stream.eof())
4880 if (!chunk)
return status_out_of_memory;
4883 if (last) last = last->
next = chunk;
4884 else chunks.
data = last = chunk;
4887 stream.read(chunk->
data,
static_cast<std::streamsize
>(
sizeof(chunk->
data) /
sizeof(T)));
4888 chunk->
size =
static_cast<size_t>(stream.gcount()) *
sizeof(T);
4891 if (stream.bad() || (!stream.eof() && stream.fail()))
return status_io_error;
4894 if (total + chunk->
size < total)
return status_out_of_memory;
4895 total += chunk->
size;
4898 size_t max_suffix_size =
sizeof(char_t);
4902 if (!buffer)
return status_out_of_memory;
4904 char* write = buffer;
4908 assert(write + chunk->size <= buffer + total);
4909 memcpy(write, chunk->data, chunk->size);
4910 write += chunk->size;
4913 assert(write == buffer + total);
4916 *out_buffer = buffer;
4925 typename std::basic_istream<T>::pos_type pos = stream.tellg();
4926 stream.seekg(0, std::ios::end);
4927 std::streamoff length = stream.tellg() - pos;
4930 if (stream.fail() || pos < 0)
return status_io_error;
4933 size_t read_length =
static_cast<size_t>(length);
4935 if (
static_cast<std::streamsize
>(read_length) != length || length < 0)
return status_out_of_memory;
4937 size_t max_suffix_size =
sizeof(char_t);
4941 if (!buffer.
data)
return status_out_of_memory;
4943 stream.read(
static_cast<T*
>(buffer.
data),
static_cast<std::streamsize
>(read_length));
4946 if (stream.bad() || (!stream.eof() && stream.fail()))
return status_io_error;
4949 size_t actual_length =
static_cast<size_t>(stream.gcount());
4950 assert(actual_length <= read_length);
4952 *out_buffer = buffer.
release();
4953 *out_size = actual_length *
sizeof(T);
4962 xml_parse_status status = status_ok;
4968 if (stream.tellg() < 0)
4980 return load_buffer_impl(doc, doc, buffer,
zero_terminate_buffer(buffer, size, real_encoding), options, real_encoding,
true,
true, out_buffer);
4984#if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR)))
4987#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400
4989 return _wfopen_s(&file, path, mode) == 0 ? file : 0;
4991 return _wfopen(path, mode);
5005 if (!result)
return 0;
5020 if (!path_utf8)
return 0;
5023 char mode_ascii[4] = {0};
5024 for (
size_t i = 0; mode[i]; ++i) mode_ascii[i] =
static_cast<char>(mode[i]);
5027 FILE* result = fopen(path_utf8, mode_ascii);
5038#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400
5040 return fopen_s(&file, path, mode) == 0 ? file : 0;
5042 return fopen(path, mode);
5046 PUGI__FN bool save_file_impl(
const xml_document& doc, FILE* file,
const char_t* indent,
unsigned int flags, xml_encoding encoding)
5048 if (!file)
return false;
5050 xml_writer_file writer(file);
5051 doc.save(writer, indent, flags, encoding);
5053 return ferror(file) == 0;
5081 size_t result = fwrite(data, 1, size,
static_cast<FILE*
>(file));
5085#ifndef PUGIXML_NO_STL
5098 assert(!wide_stream);
5099 narrow_stream->write(
reinterpret_cast<const char*
>(data),
static_cast<std::streamsize
>(size));
5103 assert(wide_stream);
5104 assert(size %
sizeof(
wchar_t) == 0);
5106 wide_stream->write(
reinterpret_cast<const wchar_t*
>(data),
static_cast<std::streamsize
>(size /
sizeof(
wchar_t)));
5146 PUGI__FN xml_attribute::operator xml_attribute::unspecified_bool_type()
const
5158 return (_attr == r._attr);
5163 return (_attr != r._attr);
5168 return (_attr < r._attr);
5173 return (_attr > r._attr);
5178 return (_attr <= r._attr);
5183 return (_attr >= r._attr);
5198 return (_attr && _attr->
value) ? _attr->
value + 0 : def;
5203 return (_attr && _attr->
value) ? impl::get_value_int(_attr->
value) : def;
5208 return (_attr && _attr->
value) ? impl::get_value_uint(_attr->
value) : def;
5213 return (_attr && _attr->
value) ? impl::get_value_double(_attr->
value) : def;
5218 return (_attr && _attr->
value) ? impl::get_value_float(_attr->
value) : def;
5223 return (_attr && _attr->
value) ? impl::get_value_bool(_attr->
value) : def;
5226#ifdef PUGIXML_HAS_LONG_LONG
5227 PUGI__FN long long xml_attribute::as_llong(
long long def)
const
5229 return (_attr && _attr->
value) ? impl::get_value_llong(_attr->
value) : def;
5232 PUGI__FN unsigned long long xml_attribute::as_ullong(
unsigned long long def)
const
5234 return (_attr && _attr->
value) ? impl::get_value_ullong(_attr->
value) : def;
5311#ifdef PUGIXML_HAS_LONG_LONG
5327 if (!_attr)
return false;
5329 return impl::strcpy_insitu(_attr->
name, _attr->
header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
5334 if (!_attr)
return false;
5336 return impl::strcpy_insitu(_attr->
value, _attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs));
5341 if (!_attr)
return false;
5343 return impl::set_value_integer<unsigned int>(_attr->
value, _attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5348 if (!_attr)
return false;
5350 return impl::set_value_integer<unsigned int>(_attr->
value, _attr->
header, impl::xml_memory_page_value_allocated_mask, rhs,
false);
5355 if (!_attr)
return false;
5357 return impl::set_value_integer<unsigned long>(_attr->
value, _attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5362 if (!_attr)
return false;
5364 return impl::set_value_integer<unsigned long>(_attr->
value, _attr->
header, impl::xml_memory_page_value_allocated_mask, rhs,
false);
5369 if (!_attr)
return false;
5376 if (!_attr)
return false;
5378 return impl::set_value_convert(_attr->
value, _attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, precision);
5383 if (!_attr)
return false;
5390 if (!_attr)
return false;
5392 return impl::set_value_convert(_attr->
value, _attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, precision);
5397 if (!_attr)
return false;
5399 return impl::set_value_bool(_attr->
value, _attr->
header, impl::xml_memory_page_value_allocated_mask, rhs);
5402#ifdef PUGIXML_HAS_LONG_LONG
5405 if (!_attr)
return false;
5407 return impl::set_value_integer<unsigned long long>(_attr->
value, _attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5412 if (!_attr)
return false;
5414 return impl::set_value_integer<unsigned long long>(_attr->
value, _attr->
header, impl::xml_memory_page_value_allocated_mask, rhs,
false);
5419 PUGI__FN bool operator&&(
const xml_attribute& lhs,
bool rhs)
5421 return (
bool)lhs && rhs;
5424 PUGI__FN bool operator||(
const xml_attribute& lhs,
bool rhs)
5426 return (
bool)lhs || rhs;
5542 if (i->name && impl::strequal(name_, i->name))
return xml_node(i);
5552 if (i->name && impl::strequal(name_, i->name))
5563 if (i->name && impl::strequal(name_, i->name))
return xml_node(i);
5578 if (i->name && impl::strequal(name_, i->name))
return xml_node(i);
5588 assert(!hint || (
_root && impl::is_attribute_of(hint,
_root)));
5594 if (i->name && impl::strequal(name_, i->name))
5605 if (j->name && impl::strequal(name_, j->name))
5648 if (impl::is_text_node(i) && i->value)
5686 return impl::strcpy_insitu(
_root->
name,
_root->
header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
5696 return impl::strcpy_insitu(
_root->
value,
_root->
header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs));
5703 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5709 impl::append_attribute(a._attr,
_root);
5720 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5726 impl::prepend_attribute(a._attr,
_root);
5738 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5744 impl::insert_attribute_after(a._attr, attr._attr,
_root);
5756 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5762 impl::insert_attribute_before(a._attr, attr._attr,
_root);
5774 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5780 impl::append_attribute(a._attr,
_root);
5781 impl::node_copy_attribute(a._attr, proto._attr);
5791 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5797 impl::prepend_attribute(a._attr,
_root);
5798 impl::node_copy_attribute(a._attr, proto._attr);
5809 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5815 impl::insert_attribute_after(a._attr, attr._attr,
_root);
5816 impl::node_copy_attribute(a._attr, proto._attr);
5827 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5833 impl::insert_attribute_before(a._attr, attr._attr,
_root);
5834 impl::node_copy_attribute(a._attr, proto._attr);
5841 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5843 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5844 if (!alloc.reserve())
return xml_node();
5846 xml_node n(impl::allocate_node(alloc, type_));
5858 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5860 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5861 if (!alloc.reserve())
return xml_node();
5863 xml_node n(impl::allocate_node(alloc, type_));
5875 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5878 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5879 if (!alloc.reserve())
return xml_node();
5881 xml_node n(impl::allocate_node(alloc, type_));
5884 impl::insert_node_before(n.
_root, node.
_root);
5893 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5896 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5897 if (!alloc.reserve())
return xml_node();
5899 xml_node n(impl::allocate_node(alloc, type_));
5902 impl::insert_node_after(n.
_root, node.
_root);
5948 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5950 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5951 if (!alloc.reserve())
return xml_node();
5953 xml_node n(impl::allocate_node(alloc, type_));
5965 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5967 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5968 if (!alloc.reserve())
return xml_node();
5970 xml_node n(impl::allocate_node(alloc, type_));
5982 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5985 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5986 if (!alloc.reserve())
return xml_node();
5988 xml_node n(impl::allocate_node(alloc, type_));
5991 impl::insert_node_after(n.
_root, node.
_root);
6000 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
6003 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6004 if (!alloc.reserve())
return xml_node();
6006 xml_node n(impl::allocate_node(alloc, type_));
6009 impl::insert_node_before(n.
_root, node.
_root);
6017 if (!impl::allow_move(*
this, moved))
return xml_node();
6019 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6020 if (!alloc.reserve())
return xml_node();
6023 impl::get_document(
_root).header |= impl::xml_memory_page_contents_shared_mask;
6025 impl::remove_node(moved.
_root);
6033 if (!impl::allow_move(*
this, moved))
return xml_node();
6035 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6036 if (!alloc.reserve())
return xml_node();
6039 impl::get_document(
_root).header |= impl::xml_memory_page_contents_shared_mask;
6041 impl::remove_node(moved.
_root);
6049 if (!impl::allow_move(*
this, moved))
return xml_node();
6053 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6054 if (!alloc.reserve())
return xml_node();
6057 impl::get_document(
_root).header |= impl::xml_memory_page_contents_shared_mask;
6059 impl::remove_node(moved.
_root);
6060 impl::insert_node_after(moved.
_root, node.
_root);
6067 if (!impl::allow_move(*
this, moved))
return xml_node();
6071 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6072 if (!alloc.reserve())
return xml_node();
6075 impl::get_document(
_root).header |= impl::xml_memory_page_contents_shared_mask;
6077 impl::remove_node(moved.
_root);
6078 impl::insert_node_before(moved.
_root, node.
_root);
6090 if (!
_root || !a._attr)
return false;
6091 if (!impl::is_attribute_of(a._attr,
_root))
return false;
6093 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6094 if (!alloc.reserve())
return false;
6096 impl::remove_attribute(a._attr,
_root);
6097 impl::destroy_attribute(a._attr, alloc);
6104 if (!
_root)
return false;
6106 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6107 if (!alloc.reserve())
return false;
6113 impl::destroy_attribute(attr, alloc);
6132 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6133 if (!alloc.reserve())
return false;
6135 impl::remove_node(n.
_root);
6136 impl::destroy_node(n.
_root, alloc);
6143 if (!
_root)
return false;
6145 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6146 if (!alloc.reserve())
return false;
6152 impl::destroy_node(cur, alloc);
6168 impl::xml_document_struct* doc = &impl::get_document(
_root);
6171 doc->header |= impl::xml_memory_page_contents_shared_mask;
6174 impl::xml_memory_page* page = 0;
6175 impl::xml_extra_buffer* extra =
static_cast<impl::xml_extra_buffer*
>(doc->allocate_memory(
sizeof(impl::xml_extra_buffer) +
sizeof(
void*), page));
6180 #ifdef PUGIXML_COMPACT
6183 extra =
reinterpret_cast<impl::xml_extra_buffer*
>((
reinterpret_cast<uintptr_t
>(extra) + (
sizeof(
void*) - 1)) & ~(
sizeof(
void*) - 1));
6188 extra->next = doc->extra_buffers;
6189 doc->extra_buffers = extra;
6192 impl::name_null_sentry sentry(
_root);
6194 return impl::load_buffer_impl(doc,
_root,
const_cast<void*
>(contents), size, options, encoding,
false,
false, &extra->buffer);
6202 if (i->name && impl::strequal(name_, i->name))
6205 if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 :
PUGIXML_TEXT(
"")))
6218 if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 :
PUGIXML_TEXT(
"")))
6224#ifndef PUGIXML_NO_STL
6233 offset += (i !=
_root);
6234 offset += i->name ? impl::strlength(i->name) : 0;
6238 result.resize(offset);
6243 result[--offset] = delimiter;
6247 size_t length = impl::strlength(j->name);
6250 memcpy(&result[offset], j->name, length *
sizeof(
char_t));
6254 assert(offset == 0);
6262 xml_node context = path_[0] == delimiter ?
root() : *
this;
6266 const char_t* path_segment = path_;
6268 while (*path_segment == delimiter) ++path_segment;
6270 const char_t* path_segment_end = path_segment;
6272 while (*path_segment_end && *path_segment_end != delimiter) ++path_segment_end;
6274 if (path_segment == path_segment_end)
return context;
6276 const char_t* next_segment = path_segment_end;
6278 while (*next_segment == delimiter) ++next_segment;
6280 if (*path_segment ==
'.' && path_segment + 1 == path_segment_end)
6282 else if (*path_segment ==
'.' && *(path_segment+1) ==
'.' && path_segment + 2 == path_segment_end)
6288 if (j->name && impl::strequalrange(j->name, path_segment,
static_cast<size_t>(path_segment_end - path_segment)))
6292 if (subsearch)
return subsearch;
6305 if (!walker.
begin(arg_begin))
return false;
6316 if (!walker.
for_each(arg_for_each))
6319 if (cur->first_child)
6322 cur = cur->first_child;
6324 else if (cur->next_sibling)
6325 cur = cur->next_sibling;
6328 while (!cur->next_sibling && cur !=
_root && cur->parent)
6335 cur = cur->next_sibling;
6338 while (cur && cur !=
_root);
6341 assert(walker._depth == -1);
6344 return walker.
end(arg_end);
6361 impl::xml_buffered_writer buffered_writer(writer, encoding);
6363 impl::node_output(buffered_writer,
_root, indent, flags, depth);
6365 buffered_writer.flush();
6368#ifndef PUGIXML_NO_STL
6373 print(writer, indent, flags, encoding, depth);
6376 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
6386 if (!
_root)
return -1;
6388 impl::xml_document_struct& doc = impl::get_document(
_root);
6391 if (!doc.buffer || doc.extra_buffers)
return -1;
6410 assert(
false &&
"Invalid node type");
6418 return (
bool)lhs && rhs;
6421 PUGI__FN bool operator||(
const xml_node& lhs,
bool rhs)
6423 return (
bool)lhs || rhs;
6431 PUGI__FN xml_node_struct* xml_text::_data()
const
6433 if (!_root || impl::is_text_node(_root))
return _root;
6439 for (xml_node_struct* node = _root->
first_child; node; node = node->next_sibling)
6440 if (impl::is_text_node(node))
6446 PUGI__FN xml_node_struct* xml_text::_data_new()
6448 xml_node_struct* d = _data();
6462 PUGI__FN xml_text::operator xml_text::unspecified_bool_type()
const
6474 return _data() == 0;
6481 return (d && d->value) ? d->value + 0 :
PUGIXML_TEXT(
"");
6488 return (d && d->value) ? d->value + 0 : def;
6495 return (d && d->value) ? impl::get_value_int(d->value) : def;
6502 return (d && d->value) ? impl::get_value_uint(d->value) : def;
6509 return (d && d->value) ? impl::get_value_double(d->value) : def;
6516 return (d && d->value) ? impl::get_value_float(d->value) : def;
6523 return (d && d->value) ? impl::get_value_bool(d->value) : def;
6526#ifdef PUGIXML_HAS_LONG_LONG
6527 PUGI__FN long long xml_text::as_llong(
long long def)
const
6531 return (d && d->value) ? impl::get_value_llong(d->value) : def;
6534 PUGI__FN unsigned long long xml_text::as_ullong(
unsigned long long def)
const
6536 xml_node_struct* d = _data();
6538 return (d && d->value) ? impl::get_value_ullong(d->value) : def;
6546 return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)) :
false;
6553 return dn ? impl::set_value_integer<unsigned int>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) :
false;
6560 return dn ? impl::set_value_integer<unsigned int>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs,
false) :
false;
6567 return dn ? impl::set_value_integer<unsigned long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) :
false;
6574 return dn ? impl::set_value_integer<unsigned long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs,
false) :
false;
6581 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs,
default_float_precision) :
false;
6588 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, precision) :
false;
6595 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs,
default_double_precision) :
false;
6602 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, precision) :
false;
6609 return dn ? impl::set_value_bool(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) :
false;
6612#ifdef PUGIXML_HAS_LONG_LONG
6617 return dn ? impl::set_value_integer<unsigned long long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false;
6622 xml_node_struct* dn = _data_new();
6624 return dn ? impl::set_value_integer<unsigned long long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs,
false) : false;
6676#ifdef PUGIXML_HAS_LONG_LONG
6698 return (
bool)lhs && rhs;
6701 PUGI__FN bool operator||(
const xml_text& lhs,
bool rhs)
6703 return (
bool)lhs || rhs;
6731 assert(_wrap.
_root);
6737 assert(_wrap.
_root);
6738 return const_cast<xml_node*
>(&_wrap);
6743 assert(_wrap.
_root);
6782 return _wrap._attr == rhs._wrap._attr && _parent.
_root == rhs._parent.
_root;
6787 return _wrap._attr != rhs._wrap._attr || _parent.
_root != rhs._parent.
_root;
6792 assert(_wrap._attr);
6798 assert(_wrap._attr);
6804 assert(_wrap._attr);
6853 assert(_wrap.
_root);
6859 assert(_wrap.
_root);
6860 return const_cast<xml_node*
>(&_wrap);
6865 assert(_wrap.
_root);
6885 if (!impl::strequal(_wrap.
name(), _name))
6921 case status_bad_pi:
return "Error parsing document declaration/processing instruction";
6935 default:
return "Unknown error";
6949#ifdef PUGIXML_HAS_MOVE
6958 if (
this == &rhs)
return *
this;
6981 PUGI__FN void xml_document::_create()
6985 #ifdef PUGIXML_COMPACT
6987 const size_t page_offset =
sizeof(
void*);
6989 const size_t page_offset = 0;
6993 PUGI__STATIC_ASSERT(
sizeof(impl::xml_memory_page) +
sizeof(impl::xml_document_struct) + page_offset <=
sizeof(_memory));
6996 impl::xml_memory_page* page = impl::xml_memory_page::construct(_memory);
6999 page->busy_size = impl::xml_memory_page_size;
7002 #ifdef PUGIXML_COMPACT
7004 page->compact_page_marker =
reinterpret_cast<uint32_t*
>(
static_cast<void*
>(
reinterpret_cast<char*
>(page) +
sizeof(impl::xml_memory_page)));
7005 *page->compact_page_marker =
sizeof(impl::xml_memory_page);
7009 _root =
new (
reinterpret_cast<char*
>(page) +
sizeof(impl::xml_memory_page) + page_offset) impl::xml_document_struct(page);
7013 page->allocator =
static_cast<impl::xml_document_struct*
>(
_root);
7016 #ifdef PUGIXML_COMPACT
7017 page->allocator->_hash = &
static_cast<impl::xml_document_struct*
>(
_root)->hash;
7021 assert(
reinterpret_cast<char*
>(
_root) +
sizeof(impl::xml_document_struct) <= _memory +
sizeof(_memory));
7024 PUGI__FN void xml_document::_destroy()
7031 impl::xml_memory::deallocate(_buffer);
7036 for (impl::xml_extra_buffer* extra =
static_cast<impl::xml_document_struct*
>(
_root)->extra_buffers; extra; extra = extra->next)
7038 if (extra->buffer) impl::xml_memory::deallocate(extra->buffer);
7043 assert(root_page && !root_page->prev);
7044 assert(
reinterpret_cast<char*
>(root_page) >= _memory &&
reinterpret_cast<char*
>(root_page) < _memory +
sizeof(_memory));
7046 for (impl::xml_memory_page* page = root_page->next; page; )
7048 impl::xml_memory_page* next = page->next;
7050 impl::xml_allocator::deallocate_page(page);
7055 #ifdef PUGIXML_COMPACT
7057 static_cast<impl::xml_document_struct*
>(
_root)->hash.clear();
7063#ifdef PUGIXML_HAS_MOVE
7066 impl::xml_document_struct* doc =
static_cast<impl::xml_document_struct*
>(_root);
7067 impl::xml_document_struct* other =
static_cast<impl::xml_document_struct*
>(rhs._root);
7070 xml_node_struct* other_first_child = other->
first_child;
7072 #ifdef PUGIXML_COMPACT
7075 if (other_first_child)
7077 size_t other_children = 0;
7078 for (xml_node_struct* node = other_first_child; node; node = node->next_sibling)
7085 if (!other->_hash->reserve(other_children + 1))
7087 #ifdef PUGIXML_NO_EXCEPTIONS
7090 throw std::bad_alloc();
7100 doc->_root = other->_root;
7101 doc->_busy_size = other->_busy_size;
7105 doc->buffer = other->buffer;
7106 doc->extra_buffers = other->extra_buffers;
7107 _buffer = rhs._buffer;
7109 #ifdef PUGIXML_COMPACT
7111 doc->hash = other->hash;
7112 doc->_hash = &doc->hash;
7120 assert(doc_page && !doc_page->prev && !doc_page->next);
7123 assert(other_page && !other_page->prev);
7126 if (impl::xml_memory_page* page = other_page->next)
7128 assert(page->prev == other_page);
7130 page->prev = doc_page;
7132 doc_page->next = page;
7133 other_page->next = 0;
7137 for (impl::xml_memory_page* page = doc_page->next; page; page = page->next)
7139 assert(page->allocator == other);
7141 page->allocator = doc;
7143 #ifdef PUGIXML_COMPACT
7145 if (page->compact_shared_parent == other)
7146 page->compact_shared_parent = doc;
7151 assert(!doc->first_child);
7153 doc->first_child = other_first_child;
7155 for (xml_node_struct* node = other_first_child; node; node = node->next_sibling)
7157 #ifdef PUGIXML_COMPACT
7159 assert(node->parent == other || node->parent == doc);
7163 assert(node->parent == other);
7169 new (other) impl::xml_document_struct(
PUGI__GETPAGE(other));
7174#ifndef PUGIXML_NO_STL
7179 return impl::load_stream_impl(
static_cast<impl::xml_document_struct*
>(
_root), stream, options, encoding, &_buffer);
7186 return impl::load_stream_impl(
static_cast<impl::xml_document_struct*
>(
_root), stream, options,
encoding_wchar, &_buffer);
7193 #ifdef PUGIXML_WCHAR_MODE
7199 return load_buffer(contents, impl::strlength(contents) *
sizeof(
char_t), options, encoding);
7211 using impl::auto_deleter;
7214 return impl::load_file_impl(
static_cast<impl::xml_document_struct*
>(
_root), file.
data, options, encoding, &_buffer);
7221 using impl::auto_deleter;
7224 return impl::load_file_impl(
static_cast<impl::xml_document_struct*
>(
_root), file.
data, options, encoding, &_buffer);
7231 return impl::load_buffer_impl(
static_cast<impl::xml_document_struct*
>(
_root),
_root,
const_cast<void*
>(contents), size, options, encoding,
false,
false, &_buffer);
7238 return impl::load_buffer_impl(
static_cast<impl::xml_document_struct*
>(
_root),
_root, contents, size, options, encoding,
true,
false, &_buffer);
7245 return impl::load_buffer_impl(
static_cast<impl::xml_document_struct*
>(
_root),
_root, contents, size, options, encoding,
true,
true, &_buffer);
7250 impl::xml_buffered_writer buffered_writer(writer, encoding);
7255 #ifdef PUGIXML_WCHAR_MODE
7256 unsigned int bom = 0xfeff;
7257 buffered_writer.write(
static_cast<wchar_t>(bom));
7259 buffered_writer.write(
'\xef',
'\xbb',
'\xbf');
7265 buffered_writer.write_string(
PUGIXML_TEXT(
"<?xml version=\"1.0\""));
7267 buffered_writer.write(
'?',
'>');
7268 if (!(flags &
format_raw)) buffered_writer.write(
'\n');
7271 impl::node_output(buffered_writer,
_root, indent, flags, 0);
7273 buffered_writer.flush();
7276#ifndef PUGIXML_NO_STL
7281 save(writer, indent, flags, encoding);
7294 using impl::auto_deleter;
7297 return impl::save_file_impl(*
this, file.
data, indent, flags, encoding);
7302 using impl::auto_deleter;
7305 return impl::save_file_impl(*
this, file.
data, indent, flags, encoding);
7319#ifndef PUGIXML_NO_STL
7324 return impl::as_utf8_impl(str, impl::strlength_wide(str));
7329 return impl::as_utf8_impl(str.c_str(), str.size());
7336 return impl::as_wide_impl(str, strlen(str));
7341 return impl::as_wide_impl(str.c_str(), str.size());
7347 impl::xml_memory::allocate = allocate;
7348 impl::xml_memory::deallocate = deallocate;
7353 return impl::xml_memory::allocate;
7358 return impl::xml_memory::deallocate;
7362#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC))
7368 return std::bidirectional_iterator_tag();
7373 return std::bidirectional_iterator_tag();
7378 return std::bidirectional_iterator_tag();
7383#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC)
7389 return std::bidirectional_iterator_tag();
7394 return std::bidirectional_iterator_tag();
7399 return std::bidirectional_iterator_tag();
7404#ifndef PUGIXML_NO_XPATH
7409 template <
typename T>
bool operator()(
const T& lhs,
const T& rhs)
const
7417 template <
typename T>
bool operator()(
const T& lhs,
const T& rhs)
const
7425 template <
typename T>
bool operator()(
const T& lhs,
const T& rhs)
const
7433 template <
typename T>
bool operator()(
const T& lhs,
const T& rhs)
const
7439 template <
typename T>
inline void swap(T& lhs, T& rhs)
7450 for (I it = begin + 1; it != end; ++it)
7451 if (pred(*it, *result))
7459 while (end - begin > 1)
7460 swap(*begin++, *--end);
7466 while (end - begin > 1 && *begin != *(begin + 1))
7476 while (begin != end)
7478 if (*begin != *write)
7479 *++write = *begin++;
7493 for (T* it = begin + 1; it != end; ++it)
7499 while (hole > begin && pred(val, *(hole - 1)))
7501 *hole = *(hole - 1);
7510 template <
typename I,
typename Pred>
inline I
median3(I first, I middle, I last,
const Pred& pred)
7512 if (pred(*middle, *first))
7513 swap(middle, first);
7514 if (pred(*last, *middle))
7516 if (pred(*middle, *first))
7517 swap(middle, first);
7522 template <
typename T,
typename Pred>
PUGI__FN void partition3(T* begin, T* end, T pivot,
const Pred& pred, T** out_eqbeg, T** out_eqend)
7531 if (pred(*lt, pivot))
7533 else if (*lt == pivot)
7542 for (T* it = begin; it != eq; ++it)
7543 swap(*it, *--eqbeg);
7549 template <
typename I,
typename Pred>
PUGI__FN void sort(I begin, I end,
const Pred& pred)
7552 while (end - begin > 16)
7555 I middle = begin + (end - begin) / 2;
7556 I median =
median3(begin, middle, end - 1, pred);
7560 partition3(begin, end, *median, pred, &eqbeg, &eqend);
7563 if (eqbeg - begin > end - eqend)
7565 sort(eqend, end, pred);
7570 sort(begin, eqbeg, pred);
7583 unsigned int h =
static_cast<unsigned int>(
reinterpret_cast<uintptr_t
>(key));
7592 size_t hashmod = size - 1;
7593 size_t bucket = h & hashmod;
7595 for (
size_t probe = 0; probe <= hashmod; ++probe)
7597 if (table[bucket] == 0)
7599 table[bucket] = key;
7603 if (table[bucket] == key)
7607 bucket = (bucket + probe + 1) & hashmod;
7610 assert(
false &&
"Hash table is full");
7618 #ifdef PUGIXML_MEMORY_XPATH_PAGE_SIZE
7619 PUGIXML_MEMORY_XPATH_PAGE_SIZE
7663 size_t block_capacity_base =
sizeof(
_root->
data);
7664 size_t block_capacity_req = size + block_capacity_base / 4;
7665 size_t block_capacity = (block_capacity_base > block_capacity_req) ? block_capacity_base : block_capacity_req;
7696 if (ptr &&
_root_size - old_size + new_size <= _root->capacity)
7704 if (!result)
return 0;
7710 assert(new_size >= old_size);
7711 memcpy(result, ptr, old_size);
7738 while (cur != state.
_root)
7818 const char_t* _buffer;
7820 size_t _length_heap;
7824 char_t* result =
static_cast<char_t*
>(alloc->
allocate((
length + 1) *
sizeof(char_t)));
7825 if (!result)
return 0;
7827 memcpy(result,
string,
length *
sizeof(char_t));
7833 xpath_string(
const char_t* buffer,
bool uses_heap_,
size_t length_heap): _buffer(buffer), _uses_heap(uses_heap_), _length_heap(length_heap)
7845 assert(begin <= end && *end == 0);
7847 return xpath_string(begin,
true,
static_cast<size_t>(end - begin));
7852 assert(begin <= end);
7857 size_t length =
static_cast<size_t>(end - begin);
7858 const char_t*
data = duplicate_string(begin,
length, alloc);
7870 if (!*o._buffer)
return;
7873 if (!*_buffer && !_uses_heap && !o._uses_heap)
7875 _buffer = o._buffer;
7880 size_t target_length =
length();
7881 size_t source_length = o.
length();
7882 size_t result_length = target_length + source_length;
7885 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)));
7886 if (!result)
return;
7889 if (!_uses_heap) memcpy(result, _buffer, target_length *
sizeof(char_t));
7892 memcpy(result + target_length, o._buffer, source_length *
sizeof(char_t));
7893 result[result_length] = 0;
7898 _length_heap = result_length;
7909 return _uses_heap ? _length_heap :
strlength(_buffer);
7918 const char_t* data_ = duplicate_string(_buffer, length_, alloc);
7920 if (!data_)
return 0;
7924 _length_heap = length_;
7927 return const_cast<char_t*
>(_buffer);
7932 return *_buffer == 0;
7937 return strequal(_buffer, o._buffer);
7942 return !
strequal(_buffer, o._buffer);
7955 while (*pattern && *
string == *pattern)
7961 return *pattern == 0;
7966 #ifdef PUGIXML_WCHAR_MODE
7967 return wcschr(s, c);
7969 return strchr(s, c);
7975 #ifdef PUGIXML_WCHAR_MODE
7977 return (*p == 0) ? s : wcsstr(s, p);
7979 return strstr(s, p);
7986 return static_cast<unsigned int>(ch -
'A') < 26 ?
static_cast<char_t
>(ch |
' ') : ch;
7995 xml_node n = na.node();
8014 xml_node cur = n.first_child();
8016 while (cur && cur != n)
8018 if (cur.type() == node_pcdata || cur.type() == node_cdata)
8021 if (cur.first_child())
8022 cur = cur.first_child();
8023 else if (cur.next_sibling())
8024 cur = cur.next_sibling();
8027 while (!cur.next_sibling() && cur != n)
8030 if (cur != n) cur = cur.next_sibling();
8045 assert(ln->parent == rn->parent);
8048 if (!ln->parent)
return ln < rn;
8051 xml_node_struct* ls = ln;
8052 xml_node_struct* rs = rn;
8056 if (ls == rn)
return true;
8057 if (rs == ln)
return false;
8059 ls = ls->next_sibling;
8060 rs = rs->next_sibling;
8070 xml_node_struct* lp = ln;
8071 xml_node_struct* rp = rn;
8073 while (lp && rp && lp->parent != rp->parent)
8083 bool left_higher = !lp;
8098 if (ln == rn)
return left_higher;
8101 while (ln->parent != rn->parent)
8112 while (node && node != parent) node = node->parent;
8114 return parent && node == parent;
8119 xml_node_struct* node = xnode.node().internal_object();
8125 if (node->name && (node->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0)
return node->name;
8126 if (node->value && (node->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0)
return node->value;
8132 xml_attribute_struct* attr = xnode.attribute().internal_object();
8138 if ((attr->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0)
return attr->name;
8139 if ((attr->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0)
return attr->value;
8150 bool operator()(
const xpath_node& lhs,
const xpath_node& rhs)
const
8156 if (lo && ro)
return lo < ro;
8159 xml_node ln = lhs.node(), rn = rhs.node();
8162 if (lhs.attribute() && rhs.attribute())
8165 if (lhs.parent() == rhs.parent())
8168 for (xml_attribute a = lhs.attribute(); a; a = a.next_attribute())
8169 if (a == rhs.attribute())
8179 else if (lhs.attribute())
8182 if (lhs.parent() == rhs.node())
return false;
8186 else if (rhs.attribute())
8189 if (rhs.parent() == lhs.node())
return true;
8194 if (ln == rn)
return false;
8196 if (!ln || !rn)
return ln < rn;
8198 return node_is_before(ln.internal_object(), rn.internal_object());
8204 #if defined(__STDC_IEC_559__) || ((FLT_RADIX - 0 == 2) && (FLT_MAX_EXP - 0 == 128) && (FLT_MANT_DIG - 0 == 24))
8206 typedef uint32_t UI;
8207 union {
float f; UI i; } u;
8212 const volatile double zero = 0.0;
8219 #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__)
8220 return !!_isnan(value);
8221 #elif defined(fpclassify) && defined(FP_NAN)
8222 return fpclassify(value) == FP_NAN;
8225 const volatile double v = value;
8232 #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__)
8233 if (_finite(value))
return (value == 0) ?
PUGIXML_TEXT(
"0") : 0;
8236 #elif defined(fpclassify) && defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO)
8237 switch (fpclassify(value))
8253 const volatile double v = value;
8264 return (value != 0 && !
is_nan(value));
8269 while (begin != end && end[-1] ==
'0') end--;
8275#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400
8280 _ecvt_s(buffer,
sizeof(buffer), value, DBL_DIG + 1, &exponent, &sign);
8286 *out_mantissa = buffer;
8287 *out_exponent = exponent;
8296 char* exponent_string = strchr(buffer,
'e');
8297 assert(exponent_string);
8299 int exponent = atoi(exponent_string + 1);
8302 char* mantissa = buffer[0] ==
'-' ? buffer + 1 : buffer;
8303 assert(mantissa[0] !=
'0' && mantissa[1] ==
'.');
8306 mantissa[1] = mantissa[0];
8314 *out_mantissa = mantissa;
8315 *out_exponent = exponent;
8326 char mantissa_buffer[32];
8333 size_t result_size = strlen(mantissa_buffer) + (exponent > 0 ? exponent : -exponent) + 4;
8334 char_t* result =
static_cast<char_t*
>(alloc->
allocate(
sizeof(char_t) * result_size));
8341 if (value < 0) *s++ =
'-';
8350 while (exponent > 0)
8352 assert(*mantissa == 0 ||
static_cast<unsigned int>(*mantissa -
'0') <= 9);
8353 *s++ = *mantissa ? *mantissa++ :
'0';
8365 while (exponent < 0)
8374 assert(
static_cast<unsigned int>(*mantissa -
'0') <= 9);
8380 assert(s < result + result_size);
8392 if (*
string ==
'-') ++string;
8394 if (!*
string)
return false;
8413 return *
string == 0;
8422 #ifdef PUGIXML_WCHAR_MODE
8423 return wcstod(
string, 0);
8425 return strtod(
string, 0);
8431 size_t length =
static_cast<size_t>(end - begin);
8432 char_t* scratch = buffer;
8434 if (length >=
sizeof(buffer) /
sizeof(buffer[0]))
8438 if (!scratch)
return false;
8442 memcpy(scratch, begin, length *
sizeof(char_t));
8443 scratch[length] = 0;
8455 return floor(value + 0.5);
8462 return (value >= -0.5 && value <= 0) ? ceil(value) : floor(value + 0.5);
8467 return node.attribute() ? node.attribute().name() : node.node().name();
8475 return p ? p + 1 : name;
8485 const char_t* pos =
find_char(name,
':');
8493 const char_t* name = a.name();
8509 xml_attribute a = p.find_attribute(pred);
8511 if (a)
return a.value();
8526 xml_node p = parent;
8530 xml_attribute a = p.find_attribute(pred);
8532 if (a)
return a.value();
8547 char_t* write = buffer;
8549 for (char_t* it = buffer; *it; )
8559 if (write != buffer) *write++ =
' ';
8575 char_t* write = buffer;
8581 const char_t* pos =
find_char(from, ch);
8585 else if (
static_cast<size_t>(pos - from) < to_length)
8586 *write++ = to[pos - from];
8597 unsigned char table[128] = {0};
8601 unsigned int fc =
static_cast<unsigned int>(*from);
8602 unsigned int tc =
static_cast<unsigned int>(*to);
8604 if (fc >= 128 || tc >= 128)
8609 table[fc] =
static_cast<unsigned char>(tc ? tc : 128);
8615 for (
int i = 0; i < 128; ++i)
8617 table[i] =
static_cast<unsigned char>(i);
8619 void* result = alloc->
allocate(
sizeof(table));
8620 if (!result)
return 0;
8622 memcpy(result, table,
sizeof(table));
8624 return static_cast<unsigned char*
>(result);
8629 char_t* write = buffer;
8633 char_t ch = *buffer++;
8634 unsigned int index =
static_cast<unsigned int>(ch);
8638 unsigned char code = table[index];
8642 *write =
static_cast<char_t
>(code);
8643 write += 1 - (code >> 7);
8712 unsigned int result = 0;
8716 result +=
static_cast<unsigned int>(*str++);
8717 result += result << 10;
8718 result ^= result >> 6;
8721 result += result << 3;
8722 result ^= result >> 11;
8723 result += result << 15;
8731 if (length == 0)
return 0;
8735 if (!memory)
return 0;
8737 T* result =
new (memory) T();
8739 memcpy(result->name, name, (length + 1) *
sizeof(char_t));
8748 case xpath_type_node_set:
8749 return new_xpath_variable<xpath_variable_node_set>(name);
8751 case xpath_type_number:
8752 return new_xpath_variable<xpath_variable_number>(name);
8754 case xpath_type_string:
8755 return new_xpath_variable<xpath_variable_string>(name);
8757 case xpath_type_boolean:
8758 return new_xpath_variable<xpath_variable_boolean>(name);
8775 case xpath_type_node_set:
8779 case xpath_type_number:
8783 case xpath_type_string:
8787 case xpath_type_boolean:
8792 assert(
false &&
"Invalid variable type");
8798 switch (rhs->type())
8800 case xpath_type_node_set:
8803 case xpath_type_number:
8806 case xpath_type_string:
8809 case xpath_type_boolean:
8813 assert(
false &&
"Invalid variable type");
8820 size_t length =
static_cast<size_t>(end - begin);
8821 char_t* scratch = buffer;
8823 if (length >=
sizeof(buffer) /
sizeof(buffer[0]))
8827 if (!scratch)
return false;
8831 memcpy(scratch, begin, length *
sizeof(char_t));
8832 scratch[length] = 0;
8834 *out_result = set->get(scratch);
8847 if (end - begin < 2)
8848 return xpath_node_set::type_sorted;
8852 bool first = cmp(begin[0], begin[1]);
8854 for (
const xpath_node* it = begin + 1; it + 1 < end; ++it)
8855 if (cmp(it[0], it[1]) != first)
8856 return xpath_node_set::type_unsorted;
8858 return first ? xpath_node_set::type_sorted : xpath_node_set::type_sorted_reverse;
8861 PUGI__FN xpath_node_set::type_t
xpath_sort(xpath_node* begin, xpath_node* end, xpath_node_set::type_t type,
bool rev)
8863 xpath_node_set::type_t order = rev ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted;
8865 if (type == xpath_node_set::type_unsorted)
8869 if (sorted == xpath_node_set::type_unsorted)
8873 type = xpath_node_set::type_sorted;
8879 if (type != order)
reverse(begin, end);
8886 if (begin == end)
return xpath_node();
8890 case xpath_node_set::type_sorted:
8893 case xpath_node_set::type_sorted_reverse:
8896 case xpath_node_set::type_unsorted:
8900 assert(
false &&
"Invalid node set type");
8901 return xpath_node();
8907 xpath_node_set::type_t _type;
8930 return _begin == _end;
8935 return static_cast<size_t>(_end - _begin);
8955 if (begin_ == end_)
return;
8957 size_t size_ =
static_cast<size_t>(_end - _begin);
8958 size_t capacity =
static_cast<size_t>(_eos - _begin);
8959 size_t count =
static_cast<size_t>(end_ - begin_);
8961 if (size_ + count > capacity)
8964 xpath_node* data =
static_cast<xpath_node*
>(alloc->
reallocate(_begin, capacity *
sizeof(xpath_node), (size_ + count) *
sizeof(xpath_node)));
8969 _end = data + size_;
8970 _eos = data + size_ + count;
8973 memcpy(_end, begin_, count *
sizeof(xpath_node));
8979 _type =
xpath_sort(_begin, _end, _type,
false);
8984 assert(_begin <= pos && pos <= _end);
8991 if (_type == xpath_node_set::type_unsorted && _end - _begin > 2)
8995 size_t size_ =
static_cast<size_t>(_end - _begin);
8997 size_t hash_size = 1;
8998 while (hash_size < size_ + size_ / 2) hash_size *= 2;
9000 const void** hash_data =
static_cast<const void**
>(alloc->
allocate(hash_size *
sizeof(
void**)));
9001 if (!hash_data)
return;
9003 memset(hash_data, 0, hash_size *
sizeof(
const void**));
9005 xpath_node* write = _begin;
9007 for (xpath_node* it = _begin; it != _end; ++it)
9009 const void* attr = it->attribute().internal_object();
9010 const void* node = it->node().internal_object();
9011 const void* key = attr ? attr : node;
9013 if (key &&
hash_insert(hash_data, hash_size, key))
9023 _end =
unique(_begin, _end);
9027 xpath_node_set::type_t
type()
const
9040 size_t capacity =
static_cast<size_t>(_eos - _begin);
9043 size_t new_capacity = capacity + capacity / 2 + 1;
9046 xpath_node* data =
static_cast<xpath_node*
>(alloc->
reallocate(_begin, capacity *
sizeof(xpath_node), new_capacity *
sizeof(xpath_node)));
9051 _end = data + capacity;
9052 _eos = data + new_capacity;
9112 size_t length =
static_cast<size_t>(
end -
begin);
9121 const char_t* _cur_lexeme_pos;
9139 const char_t* cur = _cur;
9144 _cur_lexeme_pos = cur;
9153 if (*(cur+1) ==
'=')
9166 if (*(cur+1) ==
'=')
9179 if (*(cur+1) ==
'=')
9225 _cur_lexeme_contents.
begin = cur;
9236 _cur_lexeme_contents.
end = cur;
9278 if (*(cur+1) ==
'/')
9291 if (*(cur+1) ==
'.')
9298 _cur_lexeme_contents.
begin = cur;
9304 _cur_lexeme_contents.
end = cur;
9324 char_t terminator = *cur;
9328 _cur_lexeme_contents.
begin = cur;
9329 while (*cur && *cur != terminator) cur++;
9330 _cur_lexeme_contents.
end = cur;
9344 if (*(cur+1) ==
':')
9358 _cur_lexeme_contents.
begin = cur;
9369 _cur_lexeme_contents.
end = cur;
9375 _cur_lexeme_contents.
begin = cur;
9393 _cur_lexeme_contents.
end = cur;
9413 return _cur_lexeme_pos;
9420 return _cur_lexeme_contents;
9580 if (lt != xpath_type_node_set && rt != xpath_type_node_set)
9582 if (lt == xpath_type_boolean || rt == xpath_type_boolean)
9584 else if (lt == xpath_type_number || rt == xpath_type_number)
9586 else if (lt == xpath_type_string || rt == xpath_type_string)
9593 return comp(ls, rs);
9596 else if (lt == xpath_type_node_set && rt == xpath_type_node_set)
9603 for (
const xpath_node* li = ls.
begin(); li != ls.
end(); ++li)
9604 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9616 if (lt == xpath_type_node_set)
9622 if (lt == xpath_type_boolean)
9624 else if (lt == xpath_type_number)
9631 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9641 else if (lt == xpath_type_string)
9648 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9660 assert(
false &&
"Wrong types");
9664 static bool eval_once(xpath_node_set::type_t type,
nodeset_eval_t eval)
9673 if (lt != xpath_type_node_set && rt != xpath_type_node_set)
9675 else if (lt == xpath_type_node_set && rt == xpath_type_node_set)
9682 for (
const xpath_node* li = ls.
begin(); li != ls.
end(); ++li)
9688 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9699 else if (lt != xpath_type_node_set && rt == xpath_type_node_set)
9706 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9716 else if (lt == xpath_type_node_set && rt != xpath_type_node_set)
9723 for (
const xpath_node* li = ls.
begin(); li != ls.
end(); ++li)
9735 assert(
false &&
"Wrong types");
9742 assert(ns.
size() >= first);
9743 assert(expr->
rettype() != xpath_type_number);
9746 size_t size = ns.
size() - first;
9748 xpath_node* last = ns.
begin() + first;
9751 for (xpath_node* it = last; it != ns.
end(); ++it, ++i)
9768 assert(ns.
size() >= first);
9769 assert(expr->
rettype() == xpath_type_number);
9772 size_t size = ns.
size() - first;
9774 xpath_node* last = ns.
begin() + first;
9777 for (xpath_node* it = last; it != ns.
end(); ++it, ++i)
9781 if (expr->
eval_number(c, stack) ==
static_cast<double>(i))
9794 assert(ns.
size() >= first);
9795 assert(expr->
rettype() == xpath_type_number);
9797 size_t size = ns.
size() - first;
9799 xpath_node* last = ns.
begin() + first;
9805 if (er >= 1.0 && er <=
static_cast<double>(size))
9807 size_t eri =
static_cast<size_t>(er);
9809 if (er ==
static_cast<double>(eri))
9811 xpath_node r = last[eri - 1];
9822 if (ns.
size() == first)
return;
9827 apply_predicate_number_const(ns, first, _right, stack);
9828 else if (_right->
rettype() == xpath_type_number)
9829 apply_predicate_number(ns, first, _right, stack, once);
9831 apply_predicate_boolean(ns, first, _right, stack, once);
9836 if (ns.
size() == first)
return;
9838 bool last_once = eval_once(ns.
type(), eval);
9841 pred->apply_predicate(ns, first, stack, !pred->_next && last_once);
9855 ns.
push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9864 ns.
push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9872 ns.
push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9893 if (type == node_element && n->name &&
strequal(n->name, _data.nodetest))
9905 if (type == node_comment)
9913 if (type == node_pcdata || type == node_cdata)
9921 if (type == node_pi)
9929 if (type == node_pi && n->name &&
strequal(n->name, _data.nodetest))
9937 if (type == node_element)
9945 if (type == node_element && n->name &&
starts_with(n->name, _data.nodetest))
9953 assert(
false &&
"Unknown axis");
9961 const axis_t axis = T::axis;
9967 for (xml_attribute_struct* a = n->first_attribute; a; a = a->next_attribute)
9968 if (step_push(ns, a, n, alloc) & once)
9976 for (xml_node_struct* c = n->first_child; c; c = c->next_sibling)
9977 if (step_push(ns, c, alloc) & once)
9987 if (step_push(ns, n, alloc) & once)
9990 xml_node_struct* cur = n->first_child;
9994 if (step_push(ns, cur, alloc) & once)
9997 if (cur->first_child)
9998 cur = cur->first_child;
10001 while (!cur->next_sibling)
10005 if (cur == n)
return;
10008 cur = cur->next_sibling;
10017 for (xml_node_struct* c = n->next_sibling; c; c = c->next_sibling)
10018 if (step_push(ns, c, alloc) & once)
10026 for (xml_node_struct* c = n->prev_sibling_c; c->next_sibling; c = c->prev_sibling_c)
10027 if (step_push(ns, c, alloc) & once)
10035 xml_node_struct* cur = n;
10038 while (!cur->next_sibling)
10045 cur = cur->next_sibling;
10049 if (step_push(ns, cur, alloc) & once)
10052 if (cur->first_child)
10053 cur = cur->first_child;
10056 while (!cur->next_sibling)
10063 cur = cur->next_sibling;
10072 xml_node_struct* cur = n;
10075 while (!cur->prev_sibling_c->next_sibling)
10082 cur = cur->prev_sibling_c;
10086 if (cur->first_child)
10087 cur = cur->first_child->prev_sibling_c;
10091 if (step_push(ns, cur, alloc) & once)
10094 while (!cur->prev_sibling_c->next_sibling)
10101 if (step_push(ns, cur, alloc) & once)
10105 cur = cur->prev_sibling_c;
10116 if (step_push(ns, n, alloc) & once)
10119 xml_node_struct* cur = n->parent;
10123 if (step_push(ns, cur, alloc) & once)
10134 step_push(ns, n, alloc);
10142 step_push(ns, n->parent, alloc);
10148 assert(
false &&
"Unimplemented axis");
10154 const axis_t axis = T::axis;
10162 if (step_push(ns, a, p, alloc) & once)
10165 xml_node_struct* cur = p;
10169 if (step_push(ns, cur, alloc) & once)
10182 step_push(ns, a, p, alloc);
10189 xml_node_struct* cur = p;
10193 if (cur->first_child)
10194 cur = cur->first_child;
10197 while (!cur->next_sibling)
10204 cur = cur->next_sibling;
10207 if (step_push(ns, cur, alloc) & once)
10216 step_push(ns, p, alloc);
10224 step_fill(ns, p, alloc, once, v);
10229 assert(
false &&
"Unimplemented axis");
10235 const axis_t axis = T::axis;
10239 step_fill(ns, xn.node().internal_object(), alloc, once, v);
10240 else if (axis_has_attributes && xn.attribute() && xn.parent())
10241 step_fill(ns, xn.attribute().internal_object(), xn.parent().internal_object(), alloc, once, v);
10246 const axis_t axis = T::axis;
10248 const xpath_node_set::type_t axis_type = axis_reverse ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted;
10252 (!_right && eval_once(axis_type, eval)) ||
10266 for (
const xpath_node* it = s.
begin(); it != s.
end(); ++it)
10268 size_t size = ns.
size();
10271 if (axis !=
axis_self && size != 0) ns.
set_type(xpath_node_set::type_unsorted);
10273 step_fill(ns, *it, stack.
result, once, v);
10274 if (_right) apply_predicates(ns, size, stack, eval);
10279 step_fill(ns, c.
n, stack.
result, once, v);
10280 if (_right) apply_predicates(ns, 0, stack, eval);
10293 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
10296 _data.string = value;
10300 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
10303 _data.number = value;
10307 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
10310 _data.variable = value;
10314 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(left), _right(right), _next(0)
10319 _type(static_cast<char>(type)), _rettype(xpath_type_node_set), _axis(static_cast<char>(axis)), _test(static_cast<char>(test)), _left(left), _right(0), _next(0)
10322 _data.nodetest = contents;
10326 _type(static_cast<char>(type)), _rettype(xpath_type_node_set), _axis(0), _test(static_cast<char>(test)), _left(left), _right(right), _next(0)
10352 return compare_eq(_left, _right, c, stack,
equal_to());
10355 return compare_eq(_left, _right, c, stack,
not_equal_to());
10358 return compare_rel(_left, _right, c, stack,
less());
10361 return compare_rel(_right, _left, c, stack,
less());
10364 return compare_rel(_left, _right, c, stack,
less_equal());
10367 return compare_rel(_right, _left, c, stack,
less_equal());
10403 if (c.
n.attribute())
return false;
10409 for (xml_node n = c.
n.node(); n; n = n.parent())
10411 xml_attribute a = n.attribute(
PUGIXML_TEXT(
"xml:lang"));
10415 const char_t* value = a.value();
10418 for (
const char_t* lit = lang.
c_str(); *lit; ++lit)
10424 return *value == 0 || *value ==
'-';
10435 xml_attribute attr = c.
n.node().attribute(_left->_data.
nodetest);
10442 assert(_rettype == _data.variable->type());
10444 if (_rettype == xpath_type_boolean)
10445 return _data.variable->get_boolean();
10458 case xpath_type_number:
10461 case xpath_type_string:
10468 case xpath_type_node_set:
10476 assert(
false &&
"Wrong expression for return type boolean");
10504 return _data.number;
10507 return static_cast<double>(c.
size);
10510 return static_cast<double>(c.
position);
10551 for (
const xpath_node* it = ns.
begin(); it != ns.
end(); ++it)
10565 return r == r ? floor(r) : r;
10572 return r == r ? ceil(r) : r;
10580 assert(_rettype == _data.variable->type());
10582 if (_rettype == xpath_type_number)
10583 return _data.variable->get_number();
10596 case xpath_type_boolean:
10599 case xpath_type_string:
10606 case xpath_type_node_set:
10614 assert(
false &&
"Wrong expression for return type number");
10636 buffer[0] = _left->
eval_string(c, swapped_stack);
10639 for (
xpath_ast_node* n = _right; n; n = n->_next, ++pos) buffer[pos] = n->eval_string(c, swapped_stack);
10640 assert(pos == count);
10644 for (
size_t i = 0; i < count; ++i) length += buffer[i].length();
10647 char_t* result =
static_cast<char_t*
>(stack.
result->
allocate((length + 1) *
sizeof(char_t)));
10650 char_t* ri = result;
10652 for (
size_t j = 0; j < count; ++j)
10653 for (
const char_t* bi = buffer[j].c_str(); *bi; ++bi)
10670 xpath_node na = c.
n;
10680 xpath_node na = ns.
first();
10687 xpath_node na = c.
n;
10697 xpath_node na = ns.
first();
10704 xpath_node na = c.
n;
10714 xpath_node na = ns.
first();
10754 const char_t* rbegin = pos + p.
length();
10767 size_t s_length = s.
length();
10772 else if (first >=
static_cast<double>(s_length + 1))
return xpath_string();
10774 size_t pos = first < 1 ? 1 : static_cast<size_t>(first);
10775 assert(1 <= pos && pos <= s_length + 1);
10777 const char_t* rbegin = s.
c_str() + (pos - 1);
10790 size_t s_length = s.
length();
10796 else if (first >=
static_cast<double>(s_length + 1))
return xpath_string();
10800 size_t pos = first < 1 ? 1 : static_cast<size_t>(first);
10801 size_t end = last >=
static_cast<double>(s_length + 1) ? s_length + 1 :
static_cast<size_t>(last);
10803 assert(1 <= pos && pos <= end && end <= s_length + 1);
10804 const char_t* rbegin = s.
c_str() + (pos - 1);
10805 const char_t* rend = s.
c_str() + (end - 1);
10866 assert(_rettype == _data.variable->type());
10868 if (_rettype == xpath_type_string)
10882 case xpath_type_boolean:
10885 case xpath_type_number:
10888 case xpath_type_node_set:
10899 assert(
false &&
"Wrong expression for return type string");
10918 ls.
set_type(xpath_node_set::type_unsorted);
10933 bool once = eval_once(set.
type(), eval);
10935 apply_predicate(set, 0, stack, once);
10988 assert(
false &&
"Unknown axis");
10999 ns.
set_type(xpath_node_set::type_sorted);
11009 assert(_rettype == _data.variable->type());
11011 if (_rettype == xpath_type_node_set)
11013 const xpath_node_set& s = _data.variable->get_node_set();
11032 assert(
false &&
"Wrong expression for return type node set");
11059 _right = _right->_right;
11071 else if (_right->_rettype != xpath_type_number && _right->
is_posinv_expr())
11088 _left = _left->_left;
11101 _data.table =
table;
11141 if (!n->is_posinv_expr())
return false;
11164 return static_cast<xpath_value_type
>(_rettype);
11169 #ifdef PUGIXML_XPATH_DEPTH_LIMIT
11170 PUGIXML_XPATH_DEPTH_LIMIT
11208 return error(
"Exceeded maximum allowed query depth");
11219 return memory ?
new (memory)
xpath_ast_node(type, rettype, value) : 0;
11225 return memory ?
new (memory)
xpath_ast_node(type, rettype, value) : 0;
11231 return memory ?
new (memory)
xpath_ast_node(type, rettype, value) : 0;
11237 return memory ?
new (memory)
xpath_ast_node(type, rettype, left, right) : 0;
11243 return memory ?
new (memory)
xpath_ast_node(type, left, axis, test, contents) : 0;
11249 return memory ?
new (memory)
xpath_ast_node(type, left, right, test) : 0;
11257 size_t length =
static_cast<size_t>(value.
end - value.
begin);
11259 char_t* c =
static_cast<char_t*
>(
_alloc->
allocate((length + 1) *
sizeof(char_t)));
11262 memcpy(c, value.
begin, length *
sizeof(char_t));
11270 switch (name.
begin[0])
11281 if (args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11284 else if (name ==
PUGIXML_TEXT(
"contains") && argc == 2)
11288 else if (name ==
PUGIXML_TEXT(
"ceiling") && argc == 1)
11312 else if (name ==
PUGIXML_TEXT(
"local-name") && argc <= 1)
11314 if (argc == 1 && args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11323 if (argc == 1 && args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11326 else if (name ==
PUGIXML_TEXT(
"namespace-uri") && argc <= 1)
11328 if (argc == 1 && args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11331 else if (name ==
PUGIXML_TEXT(
"normalize-space") && argc <= 1)
11355 else if (name ==
PUGIXML_TEXT(
"string-length") && argc <= 1)
11357 else if (name ==
PUGIXML_TEXT(
"starts-with") && argc == 2)
11359 else if (name ==
PUGIXML_TEXT(
"substring-before") && argc == 2)
11361 else if (name ==
PUGIXML_TEXT(
"substring-after") && argc == 2)
11363 else if (name ==
PUGIXML_TEXT(
"substring") && (argc == 2 || argc == 3))
11367 if (args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11385 return error(
"Unrecognized function or wrong parameter count");
11392 switch (name.
begin[0])
11458 switch (name.
begin[0])
11501 return error(
"Unknown variable: variable set is not provided");
11503 xpath_variable* var = 0;
11508 return error(
"Unknown variable: variable set does not contain the given name");
11523 return error(
"Expected ')' to match an opening '('");
11533 if (!value)
return 0;
11563 return error(
"Unrecognized function call");
11566 size_t old_depth =
_depth;
11573 return error(
"No comma between function arguments");
11583 if (argc < 2) args[argc] = n;
11598 return error(
"Unrecognizable primary expression");
11610 size_t old_depth =
_depth;
11619 if (n->
rettype() != xpath_type_node_set)
11620 return error(
"Predicate has to be applied to node set");
11623 if (!expr)
return 0;
11629 return error(
"Expected ']' to match an opening '['");
11646 if (set && set->
rettype() != xpath_type_node_set)
11647 return error(
"Step has to be applied to node set");
11649 bool axis_specified =
false;
11655 axis_specified =
true;
11664 return error(
"Predicates are not allowed after an abbreviated step");
11673 return error(
"Predicates are not allowed after an abbreviated step");
11691 if (axis_specified)
11692 return error(
"Two axis specifiers in one step");
11696 if (!axis_specified)
11697 return error(
"Unknown axis");
11715 return error(
"Unrecognized node test");
11733 return error(
"Unrecognized node type");
11737 else if (nt_name ==
PUGIXML_TEXT(
"processing-instruction"))
11740 return error(
"Only literals are allowed as arguments to processing-instruction()");
11747 return error(
"Unmatched brace near processing-instruction()");
11752 return error(
"Unmatched brace near node type test");
11758 if (nt_name.
end - nt_name.
begin > 2 && nt_name.
end[-2] ==
':' && nt_name.
end[-1] ==
'*')
11778 return error(
"Unrecognized node test");
11782 if (!nt_name_copy)
return 0;
11787 size_t old_depth =
_depth;
11799 if (!expr)
return 0;
11802 if (!pred)
return 0;
11805 return error(
"Expected ']' to match an opening '['");
11825 size_t old_depth =
_depth;
11931 if (n->
rettype() != xpath_type_node_set)
11932 return error(
"Step has to be applied to node set");
12038 if (!rhs)
return 0;
12045 if (!rhs)
return 0;
12051 return error(
"Union operator has to be applied to node sets");
12054 if (!lhs)
return 0;
12082 size_t old_depth =
_depth;
12110 return error(
"Incorrect query");
12119 return parser.
parse();
12128 if (!memory)
return 0;
12156 if (!impl)
return 0;
12158 if (impl->
root->
rettype() != xpath_type_node_set)
12160 #ifdef PUGIXML_NO_EXCEPTIONS
12163 xpath_parse_result res;
12164 res.error =
"Expression does not evaluate to node set";
12166 throw xpath_exception(res);
12176#ifndef PUGIXML_NO_EXCEPTIONS
12179 assert(_result.
error);
12184 return _result.
error;
12207 return _attribute ?
xml_node() : _node;
12217 return _attribute ? _node : _node.
parent();
12224 PUGI__FN xpath_node::operator xpath_node::unspecified_bool_type()
const
12231 return !(_node || _attribute);
12236 return _node == n._node && _attribute == n._attribute;
12241 return _node != n._node || _attribute != n._attribute;
12247 return (
bool)lhs && rhs;
12250 PUGI__FN bool operator||(
const xpath_node& lhs,
bool rhs)
12252 return (
bool)lhs || rhs;
12256 PUGI__FN void xpath_node_set::_assign(const_iterator begin_, const_iterator end_, type_t type_)
12258 assert(begin_ <= end_);
12260 size_t size_ =
static_cast<size_t>(end_ - begin_);
12263 xpath_node* storage = (size_ <= 1) ? _storage : static_cast<xpath_node*>(impl::xml_memory::allocate(size_ *
sizeof(xpath_node)));
12267 #ifdef PUGIXML_NO_EXCEPTIONS
12270 throw std::bad_alloc();
12275 if (_begin != _storage)
12276 impl::xml_memory::deallocate(_begin);
12280 memcpy(storage, begin_, size_ *
sizeof(xpath_node));
12283 _end = storage + size_;
12287#ifdef PUGIXML_HAS_MOVE
12291 _storage[0] = rhs._storage[0];
12292 _begin = (rhs._begin == rhs._storage) ? _storage : rhs._begin;
12293 _end = _begin + (rhs._end - rhs._begin);
12295 rhs._type = type_unsorted;
12296 rhs._begin = rhs._storage;
12297 rhs._end = rhs._storage;
12307 _assign(begin_, end_, type_);
12312 if (_begin != _storage)
12313 impl::xml_memory::deallocate(_begin);
12318 _assign(ns._begin, ns._end, ns._type);
12323 if (
this == &ns)
return *
this;
12325 _assign(ns._begin, ns._end, ns._type);
12330#ifdef PUGIXML_HAS_MOVE
12338 if (
this == &rhs)
return *
this;
12340 if (_begin != _storage)
12341 impl::xml_memory::deallocate(_begin);
12356 return _end - _begin;
12361 return _begin == _end;
12366 assert(index <
size());
12367 return _begin[index];
12382 _type = impl::xpath_sort(_begin, _end, _type,
reverse);
12387 return impl::xpath_first(_begin, _end, _type);
12413 return static_cast<const impl::xpath_variable_node_set*
>(
this)->
name;
12416 return static_cast<const impl::xpath_variable_number*
>(
this)->
name;
12419 return static_cast<const impl::xpath_variable_string*
>(
this)->
name;
12422 return static_cast<const impl::xpath_variable_boolean*
>(
this)->
name;
12425 assert(
false &&
"Invalid variable type");
12437 return (
_type ==
xpath_type_boolean) ?
static_cast<const impl::xpath_variable_boolean*
>(
this)->value :
false;
12442 return (
_type ==
xpath_type_number) ?
static_cast<const impl::xpath_variable_number*
>(
this)->value : impl::gen_nan();
12453 return (
_type ==
xpath_type_node_set) ?
static_cast<const impl::xpath_variable_node_set*
>(
this)->value : impl::dummy_node_set;
12460 static_cast<impl::xpath_variable_boolean*
>(
this)->value = value;
12468 static_cast<impl::xpath_variable_number*
>(
this)->value = value;
12476 impl::xpath_variable_string* var =
static_cast<impl::xpath_variable_string*
>(
this);
12479 size_t size = (impl::strlength(value) + 1) *
sizeof(
char_t);
12481 char_t* copy =
static_cast<char_t*
>(impl::xml_memory::allocate(size));
12482 if (!copy)
return false;
12484 memcpy(copy, value, size);
12487 if (var->value) impl::xml_memory::deallocate(var->value);
12497 static_cast<impl::xpath_variable_node_set*
>(
this)->value = value;
12503 for (
size_t i = 0; i <
sizeof(_data) /
sizeof(_data[0]); ++i)
12509 for (
size_t i = 0; i <
sizeof(_data) /
sizeof(_data[0]); ++i)
12510 _destroy(_data[i]);
12515 for (
size_t i = 0; i <
sizeof(_data) /
sizeof(_data[0]); ++i)
12523 if (
this == &rhs)
return *
this;
12530#ifdef PUGIXML_HAS_MOVE
12533 for (
size_t i = 0; i <
sizeof(_data) /
sizeof(_data[0]); ++i)
12535 _data[i] = rhs._data[i];
12542 for (
size_t i = 0; i <
sizeof(_data) /
sizeof(_data[0]); ++i)
12544 _destroy(_data[i]);
12546 _data[i] = rhs._data[i];
12554 PUGI__FN void xpath_variable_set::_assign(
const xpath_variable_set& rhs)
12558 for (
size_t i = 0; i <
sizeof(_data) /
sizeof(_data[0]); ++i)
12559 if (rhs._data[i] && !_clone(rhs._data[i], &temp._data[i]))
12565 PUGI__FN void xpath_variable_set::_swap(xpath_variable_set& rhs)
12567 for (
size_t i = 0; i <
sizeof(_data) /
sizeof(_data[0]); ++i)
12569 xpath_variable* chain = _data[i];
12571 _data[i] = rhs._data[i];
12572 rhs._data[i] = chain;
12576 PUGI__FN xpath_variable* xpath_variable_set::_find(
const char_t* name)
const
12578 const size_t hash_size =
sizeof(_data) /
sizeof(_data[0]);
12579 size_t hash = impl::hash_string(name) % hash_size;
12582 for (xpath_variable* var = _data[hash]; var; var = var->_next)
12583 if (impl::strequal(var->name(), name))
12589 PUGI__FN bool xpath_variable_set::_clone(xpath_variable* var, xpath_variable** out_result)
12591 xpath_variable* last = 0;
12596 xpath_variable* nvar = impl::new_xpath_variable(var->_type, var->name());
12597 if (!nvar)
return false;
12601 last->_next = nvar;
12603 *out_result = nvar;
12608 if (!impl::copy_xpath_variable(nvar, var))
return false;
12616 PUGI__FN void xpath_variable_set::_destroy(xpath_variable* var)
12620 xpath_variable* next = var->_next;
12622 impl::delete_xpath_variable(var->_type, var);
12630 const size_t hash_size =
sizeof(_data) /
sizeof(_data[0]);
12631 size_t hash = impl::hash_string(name) % hash_size;
12635 if (impl::strequal(var->name(), name))
12636 return var->
type() == type ? var : 0;
12643 result->
_next = _data[hash];
12645 _data[hash] = result;
12654 return var ? var->
set(value) :
false;
12660 return var ? var->
set(value) :
false;
12666 return var ? var->
set(value) :
false;
12672 return var ? var->
set(value) :
false;
12677 return _find(name);
12682 return _find(name);
12687 impl::xpath_query_impl* qimpl = impl::xpath_query_impl::create();
12691 #ifdef PUGIXML_NO_EXCEPTIONS
12692 _result.
error =
"Out of memory";
12694 throw std::bad_alloc();
12699 using impl::auto_deleter;
12702 qimpl->root = impl::xpath_parser::parse(query, variables, &qimpl->alloc, &_result);
12706 qimpl->root->optimize(&qimpl->alloc);
12713 #ifdef PUGIXML_NO_EXCEPTIONS
12714 if (qimpl->oom) _result.
error =
"Out of memory";
12716 if (qimpl->oom)
throw std::bad_alloc();
12730 impl::xpath_query_impl::destroy(
static_cast<impl::xpath_query_impl*
>(_impl));
12733#ifdef PUGIXML_HAS_MOVE
12737 _result = rhs._result;
12744 if (
this == &rhs)
return *
this;
12747 impl::xpath_query_impl::destroy(
static_cast<impl::xpath_query_impl*
>(_impl));
12750 _result = rhs._result;
12752 rhs._result = xpath_parse_result();
12762 return static_cast<impl::xpath_query_impl*
>(_impl)->root->rettype();
12767 if (!_impl)
return false;
12769 impl::xpath_context c(n, 1, 1);
12770 impl::xpath_stack_data sd;
12772 bool r =
static_cast<impl::xpath_query_impl*
>(_impl)->root->eval_boolean(c, sd.stack);
12776 #ifdef PUGIXML_NO_EXCEPTIONS
12779 throw std::bad_alloc();
12788 if (!_impl)
return impl::gen_nan();
12790 impl::xpath_context c(n, 1, 1);
12791 impl::xpath_stack_data sd;
12793 double r =
static_cast<impl::xpath_query_impl*
>(_impl)->root->eval_number(c, sd.stack);
12797 #ifdef PUGIXML_NO_EXCEPTIONS
12798 return impl::gen_nan();
12800 throw std::bad_alloc();
12807#ifndef PUGIXML_NO_STL
12812 impl::xpath_context c(n, 1, 1);
12813 impl::xpath_stack_data sd;
12815 impl::xpath_string r =
static_cast<impl::xpath_query_impl*
>(_impl)->root->eval_string(c, sd.stack);
12819 #ifdef PUGIXML_NO_EXCEPTIONS
12822 throw std::bad_alloc();
12826 return string_t(r.c_str(), r.length());
12832 impl::xpath_context c(n, 1, 1);
12833 impl::xpath_stack_data sd;
12835 impl::xpath_string r = _impl ?
static_cast<impl::xpath_query_impl*
>(_impl)->root->eval_string(c, sd.stack) : impl::xpath_string();
12839 #ifdef PUGIXML_NO_EXCEPTIONS
12840 r = impl::xpath_string();
12842 throw std::bad_alloc();
12846 size_t full_size = r.length() + 1;
12850 size_t size = (full_size < capacity) ? full_size : capacity;
12853 memcpy(buffer, r.c_str(), (size - 1) *
sizeof(
char_t));
12854 buffer[size - 1] = 0;
12862 impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(
static_cast<impl::xpath_query_impl*
>(_impl));
12865 impl::xpath_context c(n, 1, 1);
12866 impl::xpath_stack_data sd;
12868 impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack, impl::nodeset_eval_all);
12872 #ifdef PUGIXML_NO_EXCEPTIONS
12875 throw std::bad_alloc();
12884 impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(
static_cast<impl::xpath_query_impl*
>(_impl));
12887 impl::xpath_context c(n, 1, 1);
12888 impl::xpath_stack_data sd;
12890 impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack, impl::nodeset_eval_first);
12894 #ifdef PUGIXML_NO_EXCEPTIONS
12897 throw std::bad_alloc();
12913 PUGI__FN xpath_query::operator xpath_query::unspecified_bool_type()
const
12965#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
12966# pragma warning(pop)
12969#if defined(_MSC_VER) && defined(__c2__)
12970# pragma clang diagnostic pop
12974#undef PUGI__NO_INLINE
12975#undef PUGI__UNLIKELY
12976#undef PUGI__STATIC_ASSERT
12977#undef PUGI__DMC_VOLATILE
12978#undef PUGI__UNSIGNED_OVERFLOW
12979#undef PUGI__MSVC_CRT_VERSION
12980#undef PUGI__SNPRINTF
12981#undef PUGI__NS_BEGIN
12984#undef PUGI__FN_NO_INLINE
12985#undef PUGI__GETHEADER_IMPL
12986#undef PUGI__GETPAGE_IMPL
12987#undef PUGI__GETPAGE
12988#undef PUGI__NODETYPE
12989#undef PUGI__IS_CHARTYPE_IMPL
12990#undef PUGI__IS_CHARTYPE
12991#undef PUGI__IS_CHARTYPEX
12992#undef PUGI__ENDSWITH
12995#undef PUGI__PUSHNODE
12996#undef PUGI__POPNODE
12997#undef PUGI__SCANFOR
12998#undef PUGI__SCANWHILE
12999#undef PUGI__SCANWHILE_UNROLL
13001#undef PUGI__THROW_ERROR
13002#undef PUGI__CHECK_ERROR
bool operator!=(const xml_attribute_iterator &rhs) const
xml_attribute_iterator & operator--()
xml_attribute * operator->() const
xml_attribute_iterator & operator++()
xml_attribute & operator*() const
bool operator==(const xml_attribute_iterator &rhs) const
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 next_attribute() const
bool operator<=(const xml_attribute &r) const
double as_double(double def=0) const
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_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
xml_named_node_iterator()
bool operator!=(const xml_named_node_iterator &rhs) const
xml_node * operator->() const
xml_named_node_iterator & operator--()
xml_named_node_iterator & operator++()
bool operator==(const xml_named_node_iterator &rhs) const
xml_node & operator*() const
bool operator==(const xml_node_iterator &rhs) const
xml_node_iterator & operator--()
xml_node_iterator & operator++()
xml_node * operator->() const
bool operator!=(const xml_node_iterator &rhs) const
xml_node & operator*() const
string_t path(char_t delimiter='/') const
size_t hash_value() 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
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)
PUGIXML_DEPRECATED xpath_node select_single_node(const char_t *query, xpath_variable_set *variables=PUGIXML_NULL) const
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 select_node(const char_t *query, xpath_variable_set *variables=PUGIXML_NULL) const
xml_node_iterator iterator
bool operator<=(const xml_node &r) const
xpath_node_set select_nodes(const char_t *query, xpath_variable_set *variables=PUGIXML_NULL) 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
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
const char_t * get() 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)
virtual void write(const void *data, size_t size) PUGIXML_OVERRIDE
virtual const char * what() const PUGIXML_OVERRIDE
const xpath_parse_result & result() const
xpath_exception(const xpath_parse_result &result)
xpath_node_set & operator=(const xpath_node_set &ns)
const_iterator end() const
void sort(bool reverse=false)
const_iterator begin() const
const xpath_node & operator[](size_t index) const
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
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
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)
bool set(const char_t *name, bool value)
xpath_variable * get(const char_t *name)
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)
xml_buffered_writer(xml_writer &writer_, xml_encoding user_encoding)
void write(char_t d0, char_t d1)
char_t data_char[bufcapacity]
char_t buffer[bufcapacity]
union xml_buffered_writer::@3 scratch
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)
xpath_value_type rettype() const
void optimize_self(xpath_allocator *alloc)
bool is_posinv_expr() const
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)
xpath_ast_node(ast_type_t type, xpath_ast_node *left, axis_t axis, nodetest_t test, const char_t *contents)
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)
bool is_posinv_step() const
xpath_string eval_string_concat(const xpath_context &c, const xpath_stack &stack)
bool eval_boolean(const xpath_context &c, const xpath_stack &stack)
xpath_ast_node(ast_type_t type, xpath_value_type rettype_, double value)
xpath_ast_node(ast_type_t type, xpath_ast_node *left, xpath_ast_node *right, predicate_t test)
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 * current_pos() const
const xpath_lexer_string & contents() const
xpath_lexer(const char_t *query)
const char_t * state() const
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)
void remove_duplicates(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
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
const char_t * c_str() const
LinguisticCode operator&(const LinguisticCode &lhs, const LinguisticCode &rhs) noexcept
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)
const int default_double_precision
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)
const int default_float_precision
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)
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)
PUGI__FN I unique(I begin, I end)
#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 void reverse(I begin, I end)
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)
PUGI__FN bool hash_insert(const void **table, size_t size, const void *key)
xml_document_struct & get_document(const Object *object)
PUGI__FN xml_encoding guess_buffer_encoding(const uint8_t *data, size_t size)
PUGI__FN void text_output_escaped(xml_buffered_writer &writer, const char_t *s, chartypex_t type, unsigned int flags)
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 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 bool set_value_convert(String &dest, Header &header, uintptr_t header_mask, float value, int precision)
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 void sort(I begin, I end, const Pred &pred)
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)
#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__FN FILE * open_file(const char *path, const char *mode)
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 void partition3(T *begin, T *end, T pivot, const Pred &pred, T **out_eqbeg, T **out_eqend)
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
PUGI__FN I min_element(I begin, I end, const Pred &pred)
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)
static const size_t xpath_ast_depth_limit
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 insertion_sort(T *begin, T *end, const Pred &pred)
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)
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)
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 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 * error_rec()
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()