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__)
136# define PUGI__MSVC_CRT_VERSION _MSC_VER
140#if __cplusplus >= 201103
141# define PUGI__SNPRINTF(buf, ...) snprintf(buf, sizeof(buf), __VA_ARGS__)
142#elif defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400
143# define PUGI__SNPRINTF(buf, ...) _snprintf_s(buf, _countof(buf), _TRUNCATE, __VA_ARGS__)
145# define PUGI__SNPRINTF sprintf
149#ifdef PUGIXML_HEADER_ONLY
150# define PUGI__NS_BEGIN namespace pugi { namespace impl {
151# define PUGI__NS_END } }
152# define PUGI__FN inline
153# define PUGI__FN_NO_INLINE inline
155# if defined(_MSC_VER) && _MSC_VER < 1300
156# define PUGI__NS_BEGIN namespace pugi { namespace impl {
157# define PUGI__NS_END } }
159# define PUGI__NS_BEGIN namespace pugi { namespace impl { namespace {
160# define PUGI__NS_END } } }
163# define PUGI__FN_NO_INLINE PUGI__NO_INLINE
167#if (defined(_MSC_VER) && _MSC_VER < 1600) || (defined(__BORLANDC__) && __BORLANDC__ < 0x561)
170# ifndef _UINTPTR_T_DEFINED
171 typedef size_t uintptr_t;
174 typedef unsigned __int8 uint8_t;
175 typedef unsigned __int16 uint16_t;
176 typedef unsigned __int32 uint32_t;
194 template <
typename T>
216 #ifdef PUGIXML_WCHAR_MODE
228 #ifdef PUGIXML_WCHAR_MODE
229 return wcscmp(src, dst) == 0;
231 return strcmp(src, dst) == 0;
238 for (
size_t i = 0; i < count; ++i)
239 if (lhs[i] != rhs[i])
242 return lhs[count] == 0;
250 #ifdef PUGIXML_WCHAR_MODE
253 const wchar_t* end = s;
255 return static_cast<size_t>(end - s);
264 typedef void (*
D)(T*);
287#ifdef PUGIXML_COMPACT
289 class compact_hash_table
292 compact_hash_table(): _items(0), _capacity(0), _count(0)
307 void* find(
const void* key)
309 if (_capacity == 0)
return 0;
311 item_t* item = get_item(key);
313 assert(item->key == key || (item->key == 0 && item->value == 0));
318 void insert(
const void* key,
void* value)
320 assert(_capacity != 0 && _count < _capacity - _capacity / 4);
322 item_t* item = get_item(key);
334 bool reserve(
size_t extra = 16)
336 if (_count + extra >= _capacity - _capacity / 4)
337 return rehash(_count + extra);
354 bool rehash(
size_t count);
356 item_t* get_item(
const void* key)
359 assert(_capacity > 0);
361 size_t hashmod = _capacity - 1;
362 size_t bucket =
hash(key) & hashmod;
364 for (
size_t probe = 0; probe <= hashmod; ++probe)
366 item_t& probe_item = _items[bucket];
368 if (probe_item.key == key || probe_item.key == 0)
372 bucket = (bucket + probe + 1) & hashmod;
375 assert(
false &&
"Hash table is full");
381 unsigned int h =
static_cast<unsigned int>(
reinterpret_cast<uintptr_t
>(key));
396 size_t capacity = 32;
397 while (count >= capacity - capacity / 4)
400 compact_hash_table rt;
401 rt._capacity = capacity;
407 memset(rt._items, 0,
sizeof(item_t) * capacity);
409 for (
size_t i = 0;
i < _capacity; ++
i)
411 rt.insert(_items[i].key, _items[i].value);
416 _capacity = capacity;
419 assert(_count == rt._count);
428#ifdef PUGIXML_COMPACT
444#ifdef PUGIXML_COMPACT
445 #define PUGI__GETHEADER_IMPL(object, page, flags)
446 #define PUGI__GETPAGE_IMPL(header) (header).get_page()
448 #define PUGI__GETHEADER_IMPL(object, page, flags) (((reinterpret_cast<char*>(object) - reinterpret_cast<char*>(page)) << 8) | (flags))
450 #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))))
453 #define PUGI__GETPAGE(n) PUGI__GETPAGE_IMPL((n)->header)
454 #define PUGI__NODETYPE(n) static_cast<xml_node_type>((n)->header & impl::xml_memory_page_type_mask)
464 result->allocator = 0;
467 result->busy_size = 0;
468 result->freed_size = 0;
470 #ifdef PUGIXML_COMPACT
471 result->compact_string_base = 0;
472 result->compact_shared_parent = 0;
473 result->compact_page_marker = 0;
487 #ifdef PUGIXML_COMPACT
488 char_t* compact_string_base;
489 void* compact_shared_parent;
490 uint32_t* compact_page_marker;
495 #ifdef PUGIXML_MEMORY_PAGE_SIZE
496 (PUGIXML_MEMORY_PAGE_SIZE)
512 #ifdef PUGIXML_COMPACT
523 if (!memory)
return 0;
555 #ifdef PUGIXML_COMPACT
559 if (!result)
return 0;
562 ptrdiff_t offset =
static_cast<char*
>(result) -
reinterpret_cast<char*
>(out_page->compact_page_marker);
567 uint32_t* marker =
static_cast<uint32_t*
>(result);
569 *marker =
static_cast<uint32_t
>(
reinterpret_cast<char*
>(marker) -
reinterpret_cast<char*
>(out_page));
570 out_page->compact_page_marker = marker;
607 assert(
_root == page);
613 #ifdef PUGIXML_COMPACT
615 page->compact_string_base = 0;
616 page->compact_shared_parent = 0;
617 page->compact_page_marker = 0;
624 assert(
_root != page);
652 if (!header)
return 0;
655 ptrdiff_t page_offset =
reinterpret_cast<char*
>(header) -
reinterpret_cast<char*
>(page) -
sizeof(
xml_memory_page);
658 assert(page_offset >= 0 &&
static_cast<size_t>(page_offset) < max_encoded_offset);
663 assert(full_size < max_encoded_offset || (page->
busy_size == full_size && page_offset == 0));
668 return static_cast<char_t*
>(
static_cast<void*
>(header + 1));
692 #ifdef PUGIXML_COMPACT
693 return _hash->reserve();
702 #ifdef PUGIXML_COMPACT
703 compact_hash_table* _hash;
716 if (size <= large_allocation_threshold)
746#ifdef PUGIXML_COMPACT
748 static const uintptr_t compact_alignment_log2 = 2;
749 static const uintptr_t compact_alignment = 1 << compact_alignment_log2;
758 ptrdiff_t offset = (
reinterpret_cast<char*
>(
this) -
reinterpret_cast<char*
>(page->compact_page_marker));
759 assert(offset % compact_alignment == 0 &&
static_cast<uintptr_t
>(offset) < 256 * compact_alignment);
761 _page =
static_cast<unsigned char>(offset >> compact_alignment_log2);
762 _flags =
static_cast<unsigned char>(flags);
765 void operator&=(uintptr_t mod)
767 _flags &=
static_cast<unsigned char>(mod);
770 void operator|=(uintptr_t mod)
772 _flags |=
static_cast<unsigned char>(mod);
775 uintptr_t operator&(uintptr_t mod)
const
783 const char* page_marker =
reinterpret_cast<const char*
>(
this) - (_page << compact_alignment_log2);
784 const char* page = page_marker - *
reinterpret_cast<const uint32_t*
>(
static_cast<const void*
>(page_marker));
791 unsigned char _flags;
796 const compact_header* header =
reinterpret_cast<const compact_header*
>(
static_cast<const char*
>(
object) - header_offset);
798 return header->get_page();
801 template <
int header_offset,
typename T>
PUGI__FN_NO_INLINE T* compact_get_value(
const void*
object)
803 return static_cast<T*
>(compact_get_page(
object, header_offset)->allocator->_hash->find(
object));
806 template <
int header_offset,
typename T>
PUGI__FN_NO_INLINE void compact_set_value(
const void*
object, T* value)
808 compact_get_page(
object, header_offset)->allocator->_hash->insert(
object, value);
811 template <
typename T,
int header_offset,
int start = -126>
class compact_pointer
814 compact_pointer(): _data(0)
818 void operator=(
const compact_pointer& rhs)
823 void operator=(T* value)
831 ptrdiff_t diff =
reinterpret_cast<char*
>(
value) -
reinterpret_cast<char*
>(
this);
832 ptrdiff_t offset = ((diff + int(compact_alignment - 1)) >> compact_alignment_log2) - start;
834 if (
static_cast<uintptr_t
>(offset) <= 253)
835 _data =
static_cast<unsigned char>(offset + 1);
838 compact_set_value<header_offset>(
this, value);
853 uintptr_t
base =
reinterpret_cast<uintptr_t
>(
this) & ~(compact_alignment - 1);
855 return reinterpret_cast<T*
>(
base + (_data - 1 + start) * compact_alignment);
858 return compact_get_value<header_offset, T>(
this);
864 T* operator->()
const
873 template <
typename T,
int header_offset>
class compact_pointer_parent
876 compact_pointer_parent(): _data(0)
880 void operator=(
const compact_pointer_parent& rhs)
885 void operator=(T* value)
893 ptrdiff_t diff =
reinterpret_cast<char*
>(
value) -
reinterpret_cast<char*
>(
this);
894 ptrdiff_t offset = ((diff + int(compact_alignment - 1)) >> compact_alignment_log2) + 65533;
896 if (
static_cast<uintptr_t
>(offset) <= 65533)
898 _data =
static_cast<unsigned short>(offset + 1);
905 page->compact_shared_parent =
value;
907 if (page->compact_shared_parent == value)
913 compact_set_value<header_offset>(
this, value);
931 uintptr_t
base =
reinterpret_cast<uintptr_t
>(
this) & ~(compact_alignment - 1);
933 return reinterpret_cast<T*
>(
base + (_data - 1 - 65533) * compact_alignment);
935 else if (_data == 65534)
936 return static_cast<T*
>(compact_get_page(
this, header_offset)->compact_shared_parent);
938 return compact_get_value<header_offset, T>(
this);
944 T* operator->()
const
953 template <
int header_offset,
int base_offset>
class compact_string
956 compact_string(): _data(0)
960 void operator=(
const compact_string& rhs)
965 void operator=(char_t* value)
972 page->compact_string_base =
value;
974 ptrdiff_t offset =
value - page->compact_string_base;
976 if (
static_cast<uintptr_t
>(offset) < (65535 << 7))
979 uint16_t*
base =
reinterpret_cast<uint16_t*
>(
static_cast<void*
>(
reinterpret_cast<char*
>(
this) - base_offset));
983 *
base =
static_cast<uint16_t
>((offset >> 7) + 1);
984 _data =
static_cast<unsigned char>((offset & 127) + 1);
988 ptrdiff_t remainder = offset - ((*
base - 1) << 7);
990 if (
static_cast<uintptr_t
>(remainder) <= 253)
992 _data =
static_cast<unsigned char>(remainder + 1);
996 compact_set_value<header_offset>(
this, value);
1004 compact_set_value<header_offset>(
this, value);
1024 const uint16_t*
base =
reinterpret_cast<const uint16_t*
>(
static_cast<const void*
>(
reinterpret_cast<const char*
>(
this) - base_offset));
1027 ptrdiff_t offset = ((*
base - 1) << 7) + (_data - 1);
1029 return page->compact_string_base + offset;
1033 return compact_get_value<header_offset, char_t>(
this);
1041 unsigned char _data;
1046#ifdef PUGIXML_COMPACT
1049 struct xml_attribute_struct
1056 impl::compact_header
header;
1058 uint16_t namevalue_base;
1060 impl::compact_string<4, 2>
name;
1061 impl::compact_string<5, 3>
value;
1064 impl::compact_pointer<xml_attribute_struct, 7, 0>
next_attribute;
1067 struct xml_node_struct
1074 impl::compact_header
header;
1076 uint16_t namevalue_base;
1078 impl::compact_string<4, 2>
name;
1079 impl::compact_string<5, 3>
value;
1081 impl::compact_pointer_parent<xml_node_struct, 6>
parent;
1083 impl::compact_pointer<xml_node_struct, 8, 0>
first_child;
1086 impl::compact_pointer<xml_node_struct, 10, 0>
next_sibling;
1151 #ifdef PUGIXML_COMPACT
1152 compact_hash_table
hash;
1176 void* memory = alloc.
allocate_object(
sizeof(xml_attribute_struct), page);
1177 if (!memory)
return 0;
1179 return new (memory) xml_attribute_struct(page);
1186 if (!memory)
return 0;
1188 return new (memory) xml_node_struct(page,
type);
1193 if (a->header & impl::xml_memory_page_name_allocated_mask)
1196 if (a->header & impl::xml_memory_page_value_allocated_mask)
1204 if (n->header & impl::xml_memory_page_name_allocated_mask)
1207 if (n->header & impl::xml_memory_page_value_allocated_mask)
1210 for (xml_attribute_struct* attr = n->first_attribute; attr; )
1212 xml_attribute_struct* next = attr->next_attribute;
1219 for (xml_node_struct* child = n->first_child; child; )
1221 xml_node_struct* next = child->next_sibling;
1231 inline void append_node(xml_node_struct* child, xml_node_struct* node)
1233 child->parent = node;
1235 xml_node_struct* head = node->first_child;
1239 xml_node_struct* tail = head->prev_sibling_c;
1241 tail->next_sibling = child;
1242 child->prev_sibling_c = tail;
1243 head->prev_sibling_c = child;
1247 node->first_child = child;
1248 child->prev_sibling_c = child;
1254 child->parent = node;
1256 xml_node_struct* head = node->first_child;
1260 child->prev_sibling_c = head->prev_sibling_c;
1261 head->prev_sibling_c = child;
1264 child->prev_sibling_c = child;
1266 child->next_sibling = head;
1267 node->first_child = child;
1272 xml_node_struct* parent = node->parent;
1274 child->parent = parent;
1276 if (node->next_sibling)
1277 node->next_sibling->prev_sibling_c = child;
1279 parent->first_child->prev_sibling_c = child;
1281 child->next_sibling = node->next_sibling;
1282 child->prev_sibling_c = node;
1284 node->next_sibling = child;
1289 xml_node_struct* parent = node->parent;
1291 child->parent = parent;
1293 if (node->prev_sibling_c->next_sibling)
1294 node->prev_sibling_c->next_sibling = child;
1296 parent->first_child = child;
1298 child->prev_sibling_c = node->prev_sibling_c;
1299 child->next_sibling = node;
1301 node->prev_sibling_c = child;
1306 xml_node_struct* parent = node->parent;
1308 if (node->next_sibling)
1309 node->next_sibling->prev_sibling_c = node->prev_sibling_c;
1311 parent->first_child->prev_sibling_c = node->prev_sibling_c;
1313 if (node->prev_sibling_c->next_sibling)
1314 node->prev_sibling_c->next_sibling = node->next_sibling;
1316 parent->first_child = node->next_sibling;
1319 node->prev_sibling_c = 0;
1320 node->next_sibling = 0;
1325 xml_attribute_struct* head = node->first_attribute;
1329 xml_attribute_struct* tail = head->prev_attribute_c;
1331 tail->next_attribute = attr;
1332 attr->prev_attribute_c = tail;
1333 head->prev_attribute_c = attr;
1337 node->first_attribute = attr;
1338 attr->prev_attribute_c = attr;
1344 xml_attribute_struct* head = node->first_attribute;
1348 attr->prev_attribute_c = head->prev_attribute_c;
1349 head->prev_attribute_c = attr;
1352 attr->prev_attribute_c = attr;
1354 attr->next_attribute = head;
1355 node->first_attribute = attr;
1360 if (place->next_attribute)
1361 place->next_attribute->prev_attribute_c = attr;
1363 node->first_attribute->prev_attribute_c = attr;
1365 attr->next_attribute = place->next_attribute;
1366 attr->prev_attribute_c = place;
1367 place->next_attribute = attr;
1372 if (place->prev_attribute_c->next_attribute)
1373 place->prev_attribute_c->next_attribute = attr;
1375 node->first_attribute = attr;
1377 attr->prev_attribute_c = place->prev_attribute_c;
1378 attr->next_attribute = place;
1379 place->prev_attribute_c = attr;
1384 if (attr->next_attribute)
1385 attr->next_attribute->prev_attribute_c = attr->prev_attribute_c;
1387 node->first_attribute->prev_attribute_c = attr->prev_attribute_c;
1389 if (attr->prev_attribute_c->next_attribute)
1390 attr->prev_attribute_c->next_attribute = attr->next_attribute;
1392 node->first_attribute = attr->next_attribute;
1394 attr->prev_attribute_c = 0;
1395 attr->next_attribute = 0;
1400 if (!alloc.
reserve())
return 0;
1403 if (!child)
return 0;
1412 if (!alloc.
reserve())
return 0;
1415 if (!attr)
return 0;
1440 return static_cast<uint16_t
>(((value & 0xff) << 8) | (value >> 8));
1445 return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value & 0xff0000) >> 8) | (value >> 24);
1455 if (ch < 0x80)
return result + 1;
1457 else if (ch < 0x800)
return result + 2;
1459 else return result + 3;
1478 *result =
static_cast<uint8_t
>(ch);
1482 else if (ch < 0x800)
1484 result[0] =
static_cast<uint8_t
>(0xC0 | (ch >> 6));
1485 result[1] =
static_cast<uint8_t
>(0x80 | (ch & 0x3F));
1491 result[0] =
static_cast<uint8_t
>(0xE0 | (ch >> 12));
1492 result[1] =
static_cast<uint8_t
>(0x80 | ((ch >> 6) & 0x3F));
1493 result[2] =
static_cast<uint8_t
>(0x80 | (ch & 0x3F));
1501 result[0] =
static_cast<uint8_t
>(0xF0 | (ch >> 18));
1502 result[1] =
static_cast<uint8_t
>(0x80 | ((ch >> 12) & 0x3F));
1503 result[2] =
static_cast<uint8_t
>(0x80 | ((ch >> 6) & 0x3F));
1504 result[3] =
static_cast<uint8_t
>(0x80 | (ch & 0x3F));
1510 return (ch < 0x10000) ?
low(result, ch) :
high(result, ch);
1535 *result =
static_cast<uint16_t
>(ch);
1542 uint32_t msh =
static_cast<uint32_t
>(ch - 0x10000) >> 10;
1543 uint32_t lsh =
static_cast<uint32_t
>(ch - 0x10000) & 0x3ff;
1545 result[0] =
static_cast<uint16_t
>(0xD800 + msh);
1546 result[1] =
static_cast<uint16_t
>(0xDC00 + lsh);
1553 return (ch < 0x10000) ?
low(result, ch) :
high(result, ch);
1604 *result =
static_cast<uint8_t
>(ch > 255 ?
'?' : ch);
1623 template <
typename Traits>
static inline typename Traits::value_type
process(
const uint8_t*
data,
size_t size,
typename Traits::value_type result, Traits)
1625 const uint8_t utf8_byte_mask = 0x3f;
1629 uint8_t lead = *
data;
1634 result = Traits::low(result, lead);
1639 if ((
reinterpret_cast<uintptr_t
>(
data) & 3) == 0)
1642 while (size >= 4 && (*
static_cast<const uint32_t*
>(
static_cast<const void*
>(
data)) & 0x80808080) == 0)
1644 result = Traits::low(result,
data[0]);
1645 result = Traits::low(result,
data[1]);
1646 result = Traits::low(result,
data[2]);
1647 result = Traits::low(result,
data[3]);
1654 else if (
static_cast<unsigned int>(lead - 0xC0) < 0x20 && size >= 2 && (
data[1] & 0xc0) == 0x80)
1656 result = Traits::low(result, ((lead & ~0xC0) << 6) | (
data[1] & utf8_byte_mask));
1661 else if (
static_cast<unsigned int>(lead - 0xE0) < 0x10 && size >= 3 && (
data[1] & 0xc0) == 0x80 && (
data[2] & 0xc0) == 0x80)
1663 result = Traits::low(result, ((lead & ~0xE0) << 12) | ((
data[1] & utf8_byte_mask) << 6) | (
data[2] & utf8_byte_mask));
1668 else if (
static_cast<unsigned int>(lead - 0xF0) < 0x08 && size >= 4 && (
data[1] & 0xc0) == 0x80 && (
data[2] & 0xc0) == 0x80 && (
data[3] & 0xc0) == 0x80)
1670 result = Traits::high(result, ((lead & ~0xF0) << 18) | ((
data[1] & utf8_byte_mask) << 12) | ((
data[2] & utf8_byte_mask) << 6) | (
data[3] & utf8_byte_mask));
1690 template <
typename Traits>
static inline typename Traits::value_type
process(
const uint16_t*
data,
size_t size,
typename Traits::value_type result, Traits)
1699 result = Traits::low(result, lead);
1704 else if (
static_cast<unsigned int>(lead - 0xE000) < 0x2000)
1706 result = Traits::low(result, lead);
1711 else if (
static_cast<unsigned int>(lead - 0xD800) < 0x400 && size >= 2)
1715 if (
static_cast<unsigned int>(next - 0xDC00) < 0x400)
1717 result = Traits::high(result, 0x10000 + ((lead & 0x3ff) << 10) + (next & 0x3ff));
1742 template <
typename Traits>
static inline typename Traits::value_type
process(
const uint32_t*
data,
size_t size,
typename Traits::value_type result, Traits)
1751 result = Traits::low(result, lead);
1758 result = Traits::high(result, lead);
1772 template <
typename Traits>
static inline typename Traits::value_type
process(
const uint8_t*
data,
size_t size,
typename Traits::value_type result, Traits)
1776 result = Traits::low(result, *
data);
1810 template <
typename Traits>
static inline typename Traits::value_type
process(
const wchar_t*
data,
size_t size,
typename Traits::value_type result, Traits traits)
1814 return decoder::process(
reinterpret_cast<const typename decoder::type*
>(
data), size, result, traits);
1818#ifdef PUGIXML_WCHAR_MODE
1819 PUGI__FN void convert_wchar_endian_swap(
wchar_t* result,
const wchar_t*
data,
size_t length)
1821 for (
size_t i = 0;
i < length; ++
i)
1842 55, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 63, 0, 0,
1843 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1844 8, 0, 6, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 96, 64, 0,
1845 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 0, 1, 0, 48, 0,
1846 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1847 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 16, 0, 192,
1848 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
1849 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 0, 0, 0,
1851 192, 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, 192, 192, 192, 192, 192,
1853 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
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
1872 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 2, 3, 3,
1873 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1874 0, 0, 2, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 16, 16, 0,
1875 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 3, 0, 1, 0,
1877 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1878 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 20,
1879 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1880 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0,
1882 20, 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, 20, 20, 20, 20, 20,
1884 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
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
1892#ifdef PUGIXML_WCHAR_MODE
1893 #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) ((static_cast<unsigned int>(c) < 128 ? table[static_cast<unsigned int>(c)] : table[128]) & (ct))
1895 #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast<unsigned char>(c)] & (ct))
1898 #define PUGI__IS_CHARTYPE(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartype_table)
1899 #define PUGI__IS_CHARTYPEX(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartypex_table)
1903 unsigned int ui = 1;
1905 return *
reinterpret_cast<unsigned char*
>(&ui) == 1;
1912 if (
sizeof(
wchar_t) == 2)
1920 #define PUGI__SCANCHAR(ch) { if (offset >= size || data[offset] != ch) return false; offset++; }
1921 #define PUGI__SCANCHARTYPE(ct) { while (offset < size && PUGI__IS_CHARTYPE(data[offset], ct)) offset++; }
1928 for (
size_t i = 6; i + 1 < size; ++i)
1934 if (
data[i] ==
'e' &&
data[i + 1] ==
'n')
1948 uint8_t delimiter = (offset < size &&
data[offset] ==
'"') ?
'"' :
'\'';
1952 size_t start = offset;
1954 out_encoding =
data + offset;
1958 out_length = offset - start;
1968 #undef PUGI__SCANCHAR
1969 #undef PUGI__SCANCHARTYPE
1975 if (size < 4)
return encoding_utf8;
1980 if (d0 == 0 && d1 == 0 && d2 == 0xfe && d3 == 0xff)
return encoding_utf32_be;
1981 if (d0 == 0xff && d1 == 0xfe && d2 == 0 && d3 == 0)
return encoding_utf32_le;
1982 if (d0 == 0xfe && d1 == 0xff)
return encoding_utf16_be;
1983 if (d0 == 0xff && d1 == 0xfe)
return encoding_utf16_le;
1984 if (d0 == 0xef && d1 == 0xbb && d2 == 0xbf)
return encoding_utf8;
1987 if (d0 == 0 && d1 == 0 && d2 == 0 && d3 == 0x3c)
return encoding_utf32_be;
1988 if (d0 == 0x3c && d1 == 0 && d2 == 0 && d3 == 0)
return encoding_utf32_le;
1989 if (d0 == 0 && d1 == 0x3c && d2 == 0 && d3 == 0x3f)
return encoding_utf16_be;
1990 if (d0 == 0x3c && d1 == 0 && d2 == 0x3f && d3 == 0)
return encoding_utf16_le;
1993 if (d0 == 0 && d1 == 0x3c)
return encoding_utf16_be;
1994 if (d0 == 0x3c && d1 == 0)
return encoding_utf16_le;
1997 const uint8_t* enc = 0;
1998 size_t enc_length = 0;
2003 if (enc_length == 10
2004 && (enc[0] |
' ') ==
'i' && (enc[1] |
' ') ==
's' && (enc[2] |
' ') ==
'o'
2005 && enc[3] ==
'-' && enc[4] ==
'8' && enc[5] ==
'8' && enc[6] ==
'5' && enc[7] ==
'9'
2006 && enc[8] ==
'-' && enc[9] ==
'1')
2007 return encoding_latin1;
2011 && (enc[0] |
' ') ==
'l' && (enc[1] |
' ') ==
'a' && (enc[2] |
' ') ==
't'
2012 && (enc[3] |
' ') ==
'i' && (enc[4] |
' ') ==
'n'
2014 return encoding_latin1;
2017 return encoding_utf8;
2026 if (encoding == encoding_utf16)
return is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
2029 if (encoding == encoding_utf32)
return is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
2032 if (encoding != encoding_auto)
return encoding;
2035 const uint8_t*
data =
static_cast<const uint8_t*
>(contents);
2042 size_t length = size /
sizeof(char_t);
2046 out_buffer =
static_cast<char_t*
>(
const_cast<void*
>(contents));
2047 out_length = length;
2052 if (!
buffer)
return false;
2055 memcpy(
buffer, contents, length *
sizeof(char_t));
2057 assert(length == 0);
2062 out_length = length + 1;
2068#ifdef PUGIXML_WCHAR_MODE
2069 PUGI__FN bool need_endian_swap_utf(xml_encoding le, xml_encoding re)
2075 PUGI__FN bool convert_buffer_endian_swap(char_t*& out_buffer,
size_t& out_length,
const void* contents,
size_t size,
bool is_mutable)
2084 convert_wchar_endian_swap(
buffer,
data, length);
2087 out_length = length;
2092 if (!
buffer)
return false;
2094 convert_wchar_endian_swap(
buffer,
data, length);
2098 out_length = length + 1;
2106 const typename D::type*
data =
static_cast<const typename D::type*
>(contents);
2107 size_t data_length =
size /
sizeof(
typename D::type);
2114 if (!
buffer)
return false;
2117 wchar_writer::value_type obegin =
reinterpret_cast<wchar_writer::value_type
>(
buffer);
2118 wchar_writer::value_type oend = D::process(
data, data_length, obegin,
wchar_writer());
2120 assert(oend == obegin + length);
2124 out_length = length + 1;
2129 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)
2135 if (encoding == wchar_encoding)
2139 if (need_endian_swap_utf(encoding, wchar_encoding))
2140 return convert_buffer_endian_swap(out_buffer, out_length, contents, size, is_mutable);
2143 if (encoding == encoding_utf8)
2147 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
2151 return (native_encoding == encoding) ?
2157 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
2161 return (native_encoding == encoding) ?
2167 if (encoding == encoding_latin1)
2170 assert(
false &&
"Invalid encoding");
2176 const typename D::type*
data =
static_cast<const typename D::type*
>(contents);
2177 size_t data_length = size /
sizeof(
typename D::type);
2184 if (!
buffer)
return false;
2187 uint8_t* obegin =
reinterpret_cast<uint8_t*
>(
buffer);
2190 assert(oend == obegin + length);
2194 out_length = length + 1;
2201 for (
size_t i = 0; i < size; ++i)
2210 const uint8_t*
data =
static_cast<const uint8_t*
>(contents);
2211 size_t data_length = size;
2215 assert(prefix_length <= data_length);
2217 const uint8_t* postfix =
data + prefix_length;
2218 size_t postfix_length = data_length - prefix_length;
2221 if (postfix_length == 0)
return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable);
2228 if (!
buffer)
return false;
2233 uint8_t* obegin =
reinterpret_cast<uint8_t*
>(
buffer);
2236 assert(oend == obegin + length);
2240 out_length = length + 1;
2245 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)
2248 if (encoding == encoding_utf8)
2252 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
2254 xml_encoding native_encoding =
is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
2256 return (native_encoding == encoding) ?
2262 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
2264 xml_encoding native_encoding =
is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
2266 return (native_encoding == encoding) ?
2272 if (encoding == encoding_latin1)
2275 assert(
false &&
"Invalid encoding");
2289 uint8_t* begin =
reinterpret_cast<uint8_t*
>(
buffer);
2292 assert(begin + size == end);
2297#ifndef PUGIXML_NO_STL
2305 result.resize(size);
2315 const uint8_t*
data =
reinterpret_cast<const uint8_t*
>(
str);
2321 std::basic_string<wchar_t> result;
2322 result.resize(length);
2327 wchar_writer::value_type begin =
reinterpret_cast<wchar_writer::value_type
>(&result[0]);
2330 assert(begin + length == end);
2338 template <
typename Header>
2344 size_t target_length =
strlength(target);
2347 if ((header & header_mask) == 0)
return target_length >= length;
2350 const size_t reuse_threshold = 32;
2352 return target_length >= length && (target_length < reuse_threshold || target_length - length < target_length / 2);
2355 template <
typename String,
typename Header>
2356 PUGI__FN bool strcpy_insitu(String& dest, Header& header, uintptr_t header_mask,
const char_t* source,
size_t source_length)
2358 if (source_length == 0)
2367 header &= ~header_mask;
2374 memcpy(dest, source, source_length *
sizeof(char_t));
2375 dest[source_length] = 0;
2383 if (!alloc->
reserve())
return false;
2387 if (!buf)
return false;
2390 memcpy(buf, source, source_length *
sizeof(char_t));
2391 buf[source_length] = 0;
2398 header |= header_mask;
2415 void push(char_t*& s,
size_t count)
2421 memmove(
end -
size,
end,
reinterpret_cast<char*
>(s) -
reinterpret_cast<char*
>(
end));
2438 memmove(
end -
size,
end,
reinterpret_cast<char*
>(s) -
reinterpret_cast<char*
>(
end));
2448 char_t* stre = s + 1;
2454 unsigned int ucsc = 0;
2462 if (ch ==
';')
return stre;
2466 if (
static_cast<unsigned int>(ch -
'0') <= 9)
2467 ucsc = 16 * ucsc + (ch -
'0');
2468 else if (
static_cast<unsigned int>((ch |
' ') -
'a') <= 5)
2469 ucsc = 16 * ucsc + ((ch |
' ') -
'a' + 10);
2482 char_t ch = *++stre;
2484 if (ch ==
';')
return stre;
2488 if (
static_cast<unsigned int>(ch -
'0') <= 9)
2489 ucsc = 10 * ucsc + (ch -
'0');
2501 #ifdef PUGIXML_WCHAR_MODE
2502 s =
reinterpret_cast<char_t*
>(wchar_writer::any(
reinterpret_cast<wchar_writer::value_type
>(s), ucsc));
2504 s =
reinterpret_cast<char_t*
>(
utf8_writer::any(
reinterpret_cast<uint8_t*
>(s), ucsc));
2507 g.
push(s, stre - s);
2517 if (*++stre ==
'p' && *++stre ==
';')
2522 g.
push(s, stre - s);
2526 else if (*stre ==
'p')
2528 if (*++stre ==
'o' && *++stre ==
's' && *++stre ==
';')
2533 g.
push(s, stre - s);
2542 if (*++stre ==
't' && *++stre ==
';')
2547 g.
push(s, stre - s);
2555 if (*++stre ==
't' && *++stre ==
';')
2560 g.
push(s, stre - s);
2568 if (*++stre ==
'u' && *++stre ==
'o' && *++stre ==
't' && *++stre ==
';')
2573 g.
push(s, stre - s);
2587 #define PUGI__ENDSWITH(c, e) ((c) == (e) || ((c) == 0 && endch == (e)))
2588 #define PUGI__SKIPWS() { while (PUGI__IS_CHARTYPE(*s, ct_space)) ++s; }
2589 #define PUGI__OPTSET(OPT) ( optmsk & (OPT) )
2590 #define PUGI__PUSHNODE(TYPE) { cursor = append_new_node(cursor, *alloc, TYPE); if (!cursor) PUGI__THROW_ERROR(status_out_of_memory, s); }
2591 #define PUGI__POPNODE() { cursor = cursor->parent; }
2592 #define PUGI__SCANFOR(X) { while (*s != 0 && !(X)) ++s; }
2593 #define PUGI__SCANWHILE(X) { while (X) ++s; }
2594 #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; } }
2595 #define PUGI__ENDSEG() { ch = *s; *s = 0; ++s; }
2596 #define PUGI__THROW_ERROR(err, m) return error_offset = m, error_status = err, static_cast<char_t*>(0)
2597 #define PUGI__CHECK_ERROR(err, m) { if (*s == 0) PUGI__THROW_ERROR(err, m); }
2611 if (*s ==
'\n') g.
push(s, 1);
2613 else if (s[0] ==
'-' && s[1] ==
'-' &&
PUGI__ENDSWITH(s[2],
'>'))
2617 return s + (s[2] ==
'>' ? 3 : 2);
2639 if (*s ==
'\n') g.
push(s, 1);
2641 else if (s[0] ==
']' && s[1] ==
']' &&
PUGI__ENDSWITH(s[2],
'>'))
2655 typedef char_t* (*strconv_pcdata_t)(char_t*);
2671 char_t* end = g.
flush(s);
2673 if (opt_trim::value)
2681 else if (opt_eol::value && *s ==
'\r')
2685 if (*s ==
'\n') g.
push(s, 1);
2687 else if (opt_escape::value && *s ==
'&')
2693 char_t* end = g.
flush(s);
2695 if (opt_trim::value)
2710 PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_trim_pcdata == 0x0800);
2712 switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4))
2722 default: assert(
false);
return 0;
2726 typedef char_t* (*strconv_attribute_t)(char_t*, char_t);
2749 if (*s == end_quote)
2764 char_t*
str = s + 1;
2770 else if (opt_escape::value && *s ==
'&')
2790 if (*s == end_quote)
2802 if (*s ==
'\n') g.
push(s, 1);
2806 else if (opt_escape::value && *s ==
'&')
2826 if (*s == end_quote)
2832 else if (*s ==
'\r')
2836 if (*s ==
'\n') g.
push(s, 1);
2838 else if (opt_escape::value && *s ==
'&')
2858 if (*s == end_quote)
2864 else if (opt_escape::value && *s ==
'&')
2879 PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80);
2881 switch ((optmask >> 4) & 15)
2899 default: assert(
false);
return 0;
2905 xml_parse_result result;
2906 result.status = status;
2907 result.offset = offset;
2931 if (*s ==
'"' || *s ==
'\'')
2940 else if (s[0] ==
'<' && s[1] ==
'?')
2949 else if (s[0] ==
'<' && s[1] ==
'!' && s[2] ==
'-' && s[3] ==
'-')
2966 assert(s[0] ==
'<' && s[1] ==
'!' && s[2] ==
'[');
2971 if (s[0] ==
'<' && s[1] ==
'!' && s[2] ==
'[')
2977 else if (s[0] ==
']' && s[1] ==
']' && s[2] ==
'>')
2997 assert((s[0] ==
'<' || s[0] == 0) && s[1] ==
'!');
3002 if (s[0] ==
'<' && s[1] ==
'!' && s[2] !=
'-')
3017 else if (s[0] ==
'<' || s[0] ==
'"' || s[0] ==
'\'')
3073 s += (s[2] ==
'>' ? 3 : 2);
3081 if (*++s==
'C' && *++s==
'D' && *++s==
'A' && *++s==
'T' && *++s==
'A' && *++s ==
'[')
3114 s += (s[1] ==
'>' ? 2 : 1);
3118 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'))
3124 char_t* mark = s + 9;
3129 assert((*s == 0 && endch ==
'>') || *s ==
'>');
3138 cursor->value = mark;
3148 char_t*
parse_question(char_t* s, xml_node_struct*& ref_cursor,
unsigned int optmsk, char_t endch)
3151 xml_node_struct* cursor = ref_cursor;
3166 bool declaration = (target[0] |
' ') ==
'x' && (target[1] |
' ') ==
'm' && (target[2] |
' ') ==
'l' && target + 3 == s;
3182 cursor->name = target;
3216 cursor->value = value;
3233 s += (s[1] ==
'>' ? 2 : 1);
3237 ref_cursor = cursor;
3242 char_t*
parse_tree(char_t* s, xml_node_struct* root,
unsigned int optmsk, char_t endch)
3248 xml_node_struct* cursor = root;
3300 if (*s ==
'"' || *s ==
'\'')
3306 s = strconv_attribute(s, ch);
3329 else if (*s == 0 && endch ==
'>')
3342 else if (*s == 0 && endch ==
'>')
3408 if (
PUGI__NODETYPE(cursor) == node_declaration)
goto LOC_ATTRIBUTES;
3424 if (*s ==
'<' || !*s)
3435 if (s[0] !=
'<' || s[1] !=
'/' || cursor->first_child)
continue;
3444 if (
PUGI__OPTSET(parse_embed_pcdata) && cursor->parent && !cursor->first_child && !cursor->value)
3457 s = strconv_pcdata(s);
3480 #ifdef PUGIXML_WCHAR_MODE
3483 unsigned int bom = 0xfeff;
3484 return (s[0] ==
static_cast<wchar_t>(bom)) ? s + 1 : s;
3489 return (s[0] ==
'\xef' && s[1] ==
'\xbb' && s[2] ==
'\xbf') ? s + 3 : s;
3499 node = node->next_sibling;
3512 xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c + 0 : 0;
3518 char_t endch =
buffer[length - 1];
3525 parser.
parse_tree(buffer_data, root, optmsk, endch);
3528 assert(result.offset >= 0 &&
static_cast<size_t>(result.offset) <= length);
3537 xml_node_struct* first_root_child_parsed = last_root_child ? last_root_child->next_sibling + 0 : root->first_child+ 0;
3545 if (result.offset > 0 &&
static_cast<size_t>(result.offset) == length - 1 && endch == 0)
3556 #ifdef PUGIXML_WCHAR_MODE
3559 return encoding_utf8;
3569 if (encoding == encoding_utf16)
return is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
3572 if (encoding == encoding_utf32)
return is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
3575 if (encoding != encoding_auto)
return encoding;
3578 return encoding_utf8;
3585 typename T::value_type end = D::process(
reinterpret_cast<const typename D::type*
>(
data), length, dest, T());
3587 return static_cast<size_t>(end - dest) *
sizeof(*dest);
3594 typename T::value_type end = D::process(
reinterpret_cast<const typename D::type*
>(
data), length, dest, T());
3598 for (
typename T::value_type i = dest; i != end; ++i)
3602 return static_cast<size_t>(end - dest) *
sizeof(*dest);
3605#ifdef PUGIXML_WCHAR_MODE
3608 if (length < 1)
return 0;
3611 return (
sizeof(
wchar_t) == 2 &&
static_cast<unsigned int>(
static_cast<uint16_t
>(
data[length - 1]) - 0xD800) < 0x400) ? length - 1 : length;
3614 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)
3619 convert_wchar_endian_swap(r_char,
data, length);
3621 return length *
sizeof(
char_t);
3625 if (encoding == encoding_utf8)
3629 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
3637 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
3645 if (encoding == encoding_latin1)
3648 assert(
false &&
"Invalid encoding");
3654 if (length < 5)
return 0;
3656 for (
size_t i = 1; i <= 4; ++i)
3658 uint8_t ch =
static_cast<uint8_t
>(
data[length - i]);
3661 if ((ch & 0xc0) != 0x80)
return length - i;
3670 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
3672 xml_encoding native_encoding =
is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
3677 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
3679 xml_encoding native_encoding =
is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
3684 if (encoding == encoding_latin1)
3687 assert(
false &&
"Invalid encoding");
3712 if (size == 0)
return;
3721 assert(result <=
sizeof(
scratch));
3756 length -= chunk_size;
3773 memcpy(
buffer + offset,
data, length *
sizeof(char_t));
3798 size_t length = offset -
bufsize;
3826 void write(char_t d0, char_t d1, char_t d2)
3837 void write(char_t d0, char_t d1, char_t d2, char_t d3)
3849 void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4)
3862 void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4, char_t d5)
3882 #ifdef PUGIXML_MEMORY_OUTPUT_STACK
3883 PUGIXML_MEMORY_OUTPUT_STACK
3910 const char_t* prev = s;
3915 writer.
write_buffer(prev,
static_cast<size_t>(s - prev));
3921 writer.
write(
'&',
'a',
'm',
'p',
';');
3925 writer.
write(
'&',
'l',
't',
';');
3929 writer.
write(
'&',
'g',
't',
';');
3933 if (flags & format_attribute_single_quote)
3936 writer.
write(
'&',
'q',
'u',
'o',
't',
';');
3940 if (flags & format_attribute_single_quote)
3941 writer.
write(
'&',
'a',
'p',
'o',
's',
';');
3948 unsigned int ch =
static_cast<unsigned int>(*s++);
3951 if (!(flags & format_skip_control_chars))
3952 writer.
write(
'&',
'#',
static_cast<char_t
>((ch / 10) +
'0'),
static_cast<char_t
>((ch % 10) +
'0'),
';');
3960 if (flags & format_no_escapes)
3970 writer.
write(
'<',
'!',
'[',
'C',
'D');
3971 writer.
write(
'A',
'T',
'A',
'[');
3973 const char_t* prev = s;
3976 while (*s && !(s[0] ==
']' && s[1] ==
']' && s[2] ==
'>')) ++s;
3981 writer.
write_buffer(prev,
static_cast<size_t>(s - prev));
3983 writer.
write(
']',
']',
'>');
3990 switch (indent_length)
3994 for (
unsigned int i = 0; i < depth; ++i)
3995 writer.
write(indent[0]);
4001 for (
unsigned int i = 0; i < depth; ++i)
4002 writer.
write(indent[0], indent[1]);
4008 for (
unsigned int i = 0; i < depth; ++i)
4009 writer.
write(indent[0], indent[1], indent[2]);
4015 for (
unsigned int i = 0; i < depth; ++i)
4016 writer.
write(indent[0], indent[1], indent[2], indent[3]);
4022 for (
unsigned int i = 0; i < depth; ++i)
4030 writer.
write(
'<',
'!',
'-',
'-');
4034 const char_t* prev = s;
4037 while (*s && !(s[0] ==
'-' && (s[1] ==
'-' || s[1] == 0))) ++s;
4039 writer.
write_buffer(prev,
static_cast<size_t>(s - prev));
4045 writer.
write(
'-',
' ');
4050 writer.
write(
'-',
'-',
'>');
4057 const char_t* prev = s;
4060 while (*s && !(s[0] ==
'?' && s[1] ==
'>')) ++s;
4062 writer.
write_buffer(prev,
static_cast<size_t>(s - prev));
4066 assert(s[0] ==
'?' && s[1] ==
'>');
4068 writer.
write(
'?',
' ',
'>');
4076 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4077 const char_t enquotation_char = (flags & format_attribute_single_quote) ?
'\'' :
'"';
4079 for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute)
4081 if ((flags & (format_indent_attributes | format_raw)) == format_indent_attributes)
4092 writer.
write_string(a->name ? a->name + 0 : default_name);
4093 writer.
write(
'=', enquotation_char);
4098 writer.
write(enquotation_char);
4104 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4105 const char_t*
name = node->
name ? node->name + 0 : default_name;
4110 if (node->first_attribute)
4116 if (!node->first_child)
4118 if (flags & format_no_empty_element_tags)
4120 writer.
write(
'>',
'<',
'/');
4128 if ((flags & format_raw) == 0)
4131 writer.
write(
'/',
'>');
4149 if (!node->first_child)
4151 writer.
write(
'<',
'/');
4166 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4167 const char_t*
name = node->
name ? node->name + 0 : default_name;
4169 writer.
write(
'<',
'/');
4176 const char_t* default_name =
PUGIXML_TEXT(
":anonymous");
4193 writer.
write(
'<',
'?');
4194 writer.
write_string(node->name ? node->name + 0 : default_name);
4202 writer.
write(
'?',
'>');
4205 case node_declaration:
4206 writer.
write(
'<',
'?');
4207 writer.
write_string(node->name ? node->name + 0 : default_name);
4209 writer.
write(
'?',
'>');
4213 writer.
write(
'<',
'!',
'D',
'O',
'C');
4214 writer.
write(
'T',
'Y',
'P',
'E');
4226 assert(
false &&
"Invalid node type");
4238 size_t indent_length = ((flags & (format_indent | format_indent_attributes)) && (flags & format_raw) == 0) ?
strlength(indent) : 0;
4241 xml_node_struct* node = root;
4256 if ((indent_flags &
indent_newline) && (flags & format_raw) == 0)
4272 node = node->first_child;
4281 if (node->first_child)
4283 node = node->first_child;
4296 while (node != root)
4298 if (node->next_sibling)
4300 node = node->next_sibling;
4304 node = node->parent;
4311 if ((indent_flags &
indent_newline) && (flags & format_raw) == 0)
4323 while (node != root);
4325 if ((indent_flags &
indent_newline) && (flags & format_raw) == 0)
4331 for (xml_node_struct* child = node->first_child; child; child = child->next_sibling)
4335 if (
type == node_declaration)
return true;
4336 if (
type == node_element)
return false;
4344 for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute)
4353 return parent == node_element || parent == node_declaration;
4358 if (parent != node_document && parent != node_element)
return false;
4359 if (child == node_document || child == node_null)
return false;
4360 if (parent != node_document && (child == node_declaration || child == node_doctype))
return false;
4372 if (parent.root() != child.root())
4376 xml_node cur = parent;
4389 template <
typename String,
typename Header>
4392 assert(!dest && (header & header_mask) == 0);
4396 if (alloc && (source_header & header_mask) == 0)
4414 for (xml_attribute_struct* sa = sn->first_attribute; sa; sa = sa->next_attribute)
4433 xml_node_struct* dit = dn;
4434 xml_node_struct* sit = sn->first_child;
4436 while (sit && sit != sn)
4447 if (sit->first_child)
4450 sit = sit->first_child;
4459 if (sit->next_sibling)
4461 sit = sit->next_sibling;
4485 return type == node_pcdata ||
type == node_cdata;
4492 const char_t* s = value;
4497 bool negative = (*s ==
'-');
4499 s += (*s ==
'+' || *s ==
'-');
4501 bool overflow =
false;
4503 if (s[0] ==
'0' && (s[1] |
' ') ==
'x')
4511 const char_t* start = s;
4515 if (
static_cast<unsigned>(*s -
'0') < 10)
4516 result = result * 16 + (*s -
'0');
4517 else if (
static_cast<unsigned>((*s |
' ') -
'a') < 6)
4518 result = result * 16 + ((*s |
' ') -
'a' + 10);
4525 size_t digits =
static_cast<size_t>(s - start);
4527 overflow = digits >
sizeof(U) * 2;
4535 const char_t* start = s;
4539 if (
static_cast<unsigned>(*s -
'0') < 10)
4540 result = result * 10 + (*s -
'0');
4547 size_t digits =
static_cast<size_t>(s - start);
4551 const size_t max_digits10 =
sizeof(U) == 8 ? 20 :
sizeof(U) == 4 ? 10 : 5;
4552 const char_t max_lead =
sizeof(U) == 8 ?
'1' :
sizeof(U) == 4 ?
'4' :
'6';
4553 const size_t high_bit =
sizeof(U) * 8 - 1;
4555 overflow = digits >= max_digits10 && !(digits == max_digits10 && (*start < max_lead || (*start == max_lead && result >> high_bit)));
4562 return (overflow || result > ~minv + 1) ? minv : ~result + 1;
4564 return (overflow || result > 0 - minv) ? minv : 0 - result;
4568 return (overflow || result > maxv) ? maxv : result;
4573 return string_to_integer<unsigned int>(value,
static_cast<unsigned int>(INT_MIN), INT_MAX);
4578 return string_to_integer<unsigned int>(value, 0, UINT_MAX);
4583 #ifdef PUGIXML_WCHAR_MODE
4584 return wcstod(value, 0);
4586 return strtod(value, 0);
4592 #ifdef PUGIXML_WCHAR_MODE
4593 return static_cast<float>(wcstod(value, 0));
4595 return static_cast<float>(strtod(value, 0));
4602 char_t
first = *value;
4608#ifdef PUGIXML_HAS_LONG_LONG
4609 PUGI__FN long long get_value_llong(
const char_t* value)
4611 return string_to_integer<unsigned long long>(value,
static_cast<unsigned long long>(LLONG_MIN), LLONG_MAX);
4614 PUGI__FN unsigned long long get_value_ullong(
const char_t* value)
4616 return string_to_integer<unsigned long long>(value, 0, ULLONG_MAX);
4622 char_t* result = end - 1;
4623 U rest = negative ? 0 - value : value;
4627 *result-- =
static_cast<char_t
>(
'0' + (rest % 10));
4632 assert(result >= begin);
4637 return result + !negative;
4641 template <
typename String,
typename Header>
4644 #ifdef PUGIXML_WCHAR_MODE
4646 assert(strlen(buf) <
sizeof(wbuf) /
sizeof(wbuf[0]));
4649 for (; buf[offset]; ++offset) wbuf[offset] = buf[offset];
4651 return strcpy_insitu(dest, header, header_mask, wbuf, offset);
4653 return strcpy_insitu(dest, header, header_mask, buf, strlen(buf));
4657 template <
typename U,
typename String,
typename Header>
4661 char_t* end = buf +
sizeof(buf) /
sizeof(buf[0]);
4664 return strcpy_insitu(dest, header, header_mask, begin, end - begin);
4667 template <
typename String,
typename Header>
4676 template <
typename String,
typename Header>
4685 template <
typename String,
typename Header>
4697 xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size);
4704 if (!impl::convert_buffer(
buffer, length, buffer_encoding, contents, size, is_mutable))
return impl::make_parse_result(status_out_of_memory);
4707 if (own &&
buffer != contents && contents) impl::xml_memory::deallocate(contents);
4716 xml_parse_result res = impl::xml_parser::parse(
buffer, length,
doc, root,
options);
4719 res.encoding = buffer_encoding;
4727 #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE)
4729 typedef __int64 length_type;
4731 _fseeki64(file, 0, SEEK_END);
4732 length_type length = _ftelli64(file);
4733 _fseeki64(file, 0, SEEK_SET);
4734 #elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))
4736 typedef off64_t length_type;
4738 fseeko64(file, 0, SEEK_END);
4739 length_type length = ftello64(file);
4740 fseeko64(file, 0, SEEK_SET);
4743 typedef long length_type;
4745 fseek(file, 0, SEEK_END);
4746 length_type length = ftell(file);
4747 fseek(file, 0, SEEK_SET);
4751 if (length < 0)
return status_io_error;
4754 size_t result =
static_cast<size_t>(length);
4756 if (
static_cast<length_type
>(result) != length)
return status_out_of_memory;
4759 out_result = result;
4768 #ifdef PUGIXML_WCHAR_MODE
4771 if (encoding == wchar_encoding || need_endian_swap_utf(encoding, wchar_encoding))
4773 size_t length = size /
sizeof(char_t);
4775 static_cast<char_t*
>(
buffer)[length] = 0;
4776 return (length + 1) *
sizeof(char_t);
4779 if (encoding == encoding_utf8)
4781 static_cast<char*
>(
buffer)[size] = 0;
4798 size_t max_suffix_size =
sizeof(char_t);
4805 size_t read_size = fread(contents, 1, size, file);
4807 if (read_size != size)
4815 return load_buffer_impl(
doc,
doc, contents,
zero_terminate_buffer(contents, size, real_encoding),
options, real_encoding,
true,
true, out_buffer);
4823#ifndef PUGIXML_NO_STL
4829 if (!memory)
return 0;
4865 while (!stream.eof())
4869 if (!chunk)
return status_out_of_memory;
4876 stream.read(chunk->
data,
static_cast<std::streamsize
>(
sizeof(chunk->
data) /
sizeof(T)));
4877 chunk->
size =
static_cast<size_t>(stream.gcount()) *
sizeof(T);
4880 if (stream.bad() || (!stream.eof() && stream.fail()))
return status_io_error;
4883 if (total + chunk->
size < total)
return status_out_of_memory;
4884 total += chunk->
size;
4887 size_t max_suffix_size =
sizeof(char_t);
4891 if (!
buffer)
return status_out_of_memory;
4897 assert(write + chunk->size <=
buffer + total);
4898 memcpy(write, chunk->data, chunk->size);
4899 write += chunk->size;
4902 assert(write ==
buffer + total);
4914 typename std::basic_istream<T>::pos_type pos = stream.tellg();
4915 stream.seekg(0, std::ios::end);
4916 std::streamoff length = stream.tellg() - pos;
4919 if (stream.fail() || pos < 0)
return status_io_error;
4922 size_t read_length =
static_cast<size_t>(length);
4924 if (
static_cast<std::streamsize
>(read_length) != length || length < 0)
return status_out_of_memory;
4926 size_t max_suffix_size =
sizeof(char_t);
4930 if (!
buffer.data)
return status_out_of_memory;
4932 stream.read(
static_cast<T*
>(
buffer.data),
static_cast<std::streamsize
>(read_length));
4935 if (stream.bad() || (!stream.eof() && stream.fail()))
return status_io_error;
4938 size_t actual_length =
static_cast<size_t>(stream.gcount());
4939 assert(actual_length <= read_length);
4942 *out_size = actual_length *
sizeof(T);
4951 xml_parse_status status = status_ok;
4957 if (stream.tellg() < 0)
4969 return load_buffer_impl(
doc,
doc,
buffer,
zero_terminate_buffer(
buffer, size, real_encoding),
options, real_encoding,
true,
true, out_buffer);
4973#if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR)))
4976 return _wfopen(path, mode);
4989 if (!result)
return 0;
5004 if (!path_utf8)
return 0;
5007 char mode_ascii[4] = {0};
5008 for (
size_t i = 0; mode[i]; ++i) mode_ascii[i] =
static_cast<char>(mode[i]);
5011 FILE* result = fopen(path_utf8, mode_ascii);
5022 if (!file)
return false;
5024 xml_writer_file writer(file);
5025 doc.save(writer, indent, flags, encoding);
5027 return ferror(file) == 0;
5055 size_t result = fwrite(
data, 1, size,
static_cast<FILE*
>(
file));
5059#ifndef PUGIXML_NO_STL
5073 narrow_stream->write(
reinterpret_cast<const char*
>(
data),
static_cast<std::streamsize
>(size));
5078 assert(size %
sizeof(
wchar_t) == 0);
5080 wide_stream->write(
reinterpret_cast<const wchar_t*
>(
data),
static_cast<std::streamsize
>(size /
sizeof(
wchar_t)));
5200#ifdef PUGIXML_HAS_LONG_LONG
5201 PUGI__FN long long xml_attribute::as_llong(
long long def)
const
5206 PUGI__FN unsigned long long xml_attribute::as_ullong(
unsigned long long def)
const
5285#ifdef PUGIXML_HAS_LONG_LONG
5301 if (!
_attr)
return false;
5303 return impl::strcpy_insitu(
_attr->
name,
_attr->
header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
5308 if (!
_attr)
return false;
5310 return impl::strcpy_insitu(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs));
5315 if (!
_attr)
return false;
5317 return impl::set_value_integer<unsigned int>(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5322 if (!
_attr)
return false;
5324 return impl::set_value_integer<unsigned int>(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs,
false);
5329 if (!
_attr)
return false;
5331 return impl::set_value_integer<unsigned long>(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5336 if (!
_attr)
return false;
5338 return impl::set_value_integer<unsigned long>(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs,
false);
5343 if (!
_attr)
return false;
5345 return impl::set_value_convert(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs);
5350 if (!
_attr)
return false;
5352 return impl::set_value_convert(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs);
5357 if (!
_attr)
return false;
5359 return impl::set_value_bool(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs);
5362#ifdef PUGIXML_HAS_LONG_LONG
5365 if (!
_attr)
return false;
5367 return impl::set_value_integer<unsigned long long>(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5372 if (!
_attr)
return false;
5374 return impl::set_value_integer<unsigned long long>(
_attr->
value,
_attr->
header, impl::xml_memory_page_value_allocated_mask, rhs,
false);
5379 PUGI__FN bool operator&&(
const xml_attribute& lhs,
bool rhs)
5381 return (
bool)lhs && rhs;
5384 PUGI__FN bool operator||(
const xml_attribute& lhs,
bool rhs)
5386 return (
bool)lhs || rhs;
5502 if (i->name && impl::strequal(name_, i->name))
return xml_node(i);
5512 if (i->name && impl::strequal(name_, i->name))
5523 if (i->name && impl::strequal(name_, i->name))
return xml_node(i);
5538 if (i->name && impl::strequal(name_, i->name))
return xml_node(i);
5548 assert(!hint || (
_root && impl::is_attribute_of(hint,
_root)));
5554 if (i->name && impl::strequal(name_, i->name))
5557 hint_.
_attr = i->next_attribute;
5565 if (j->name && impl::strequal(name_, j->name))
5568 hint_.
_attr = j->next_attribute;
5608 if (impl::is_text_node(i) && i->value)
5646 return impl::strcpy_insitu(
_root->
name,
_root->
header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
5656 return impl::strcpy_insitu(
_root->
value,
_root->
header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs));
5663 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5680 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5698 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5716 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5734 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5741 impl::node_copy_attribute(a.
_attr, proto.
_attr);
5751 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5758 impl::node_copy_attribute(a.
_attr, proto.
_attr);
5769 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5776 impl::node_copy_attribute(a.
_attr, proto.
_attr);
5787 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5794 impl::node_copy_attribute(a.
_attr, proto.
_attr);
5801 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5803 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5804 if (!alloc.reserve())
return xml_node();
5806 xml_node n(impl::allocate_node(alloc, type_));
5818 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5820 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5821 if (!alloc.reserve())
return xml_node();
5823 xml_node n(impl::allocate_node(alloc, type_));
5835 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5838 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5839 if (!alloc.reserve())
return xml_node();
5841 xml_node n(impl::allocate_node(alloc, type_));
5844 impl::insert_node_before(n.
_root, node.
_root);
5853 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5856 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5857 if (!alloc.reserve())
return xml_node();
5859 xml_node n(impl::allocate_node(alloc, type_));
5862 impl::insert_node_after(n.
_root, node.
_root);
5873 result.set_name(name_);
5882 result.set_name(name_);
5891 result.set_name(name_);
5900 result.set_name(name_);
5908 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5910 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5911 if (!alloc.reserve())
return xml_node();
5913 xml_node n(impl::allocate_node(alloc, type_));
5925 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5927 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5928 if (!alloc.reserve())
return xml_node();
5930 xml_node n(impl::allocate_node(alloc, type_));
5942 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5945 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5946 if (!alloc.reserve())
return xml_node();
5948 xml_node n(impl::allocate_node(alloc, type_));
5951 impl::insert_node_after(n.
_root, node.
_root);
5960 if (!impl::allow_insert_child(
type(), type_))
return xml_node();
5963 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5964 if (!alloc.reserve())
return xml_node();
5966 xml_node n(impl::allocate_node(alloc, type_));
5969 impl::insert_node_before(n.
_root, node.
_root);
5977 if (!impl::allow_move(*
this, moved))
return xml_node();
5979 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5980 if (!alloc.reserve())
return xml_node();
5983 impl::get_document(
_root).header |= impl::xml_memory_page_contents_shared_mask;
5985 impl::remove_node(moved.
_root);
5993 if (!impl::allow_move(*
this, moved))
return xml_node();
5995 impl::xml_allocator& alloc = impl::get_allocator(
_root);
5996 if (!alloc.reserve())
return xml_node();
5999 impl::get_document(
_root).header |= impl::xml_memory_page_contents_shared_mask;
6001 impl::remove_node(moved.
_root);
6009 if (!impl::allow_move(*
this, moved))
return xml_node();
6013 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6014 if (!alloc.reserve())
return xml_node();
6017 impl::get_document(
_root).header |= impl::xml_memory_page_contents_shared_mask;
6019 impl::remove_node(moved.
_root);
6020 impl::insert_node_after(moved.
_root, node.
_root);
6027 if (!impl::allow_move(*
this, moved))
return xml_node();
6031 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6032 if (!alloc.reserve())
return xml_node();
6035 impl::get_document(
_root).header |= impl::xml_memory_page_contents_shared_mask;
6037 impl::remove_node(moved.
_root);
6038 impl::insert_node_before(moved.
_root, node.
_root);
6051 if (!impl::is_attribute_of(a.
_attr,
_root))
return false;
6053 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6054 if (!alloc.reserve())
return false;
6057 impl::destroy_attribute(a.
_attr, alloc);
6071 impl::xml_allocator& alloc = impl::get_allocator(
_root);
6072 if (!alloc.reserve())
return false;
6074 impl::remove_node(n.
_root);
6075 impl::destroy_node(n.
_root, alloc);
6086 impl::xml_document_struct*
doc = &impl::get_document(
_root);
6089 doc->header |= impl::xml_memory_page_contents_shared_mask;
6092 impl::xml_memory_page* page = 0;
6093 impl::xml_extra_buffer* extra =
static_cast<impl::xml_extra_buffer*
>(
doc->allocate_memory(
sizeof(impl::xml_extra_buffer) +
sizeof(
void*), page));
6098 #ifdef PUGIXML_COMPACT
6101 extra =
reinterpret_cast<impl::xml_extra_buffer*
>((
reinterpret_cast<uintptr_t
>(extra) + (
sizeof(
void*) - 1)) & ~(
sizeof(
void*) - 1));
6106 extra->next =
doc->extra_buffers;
6107 doc->extra_buffers = extra;
6110 impl::name_null_sentry sentry(
_root);
6112 return impl::load_buffer_impl(
doc,
_root,
const_cast<void*
>(contents), size,
options, encoding,
false,
false, &extra->buffer);
6120 if (i->name && impl::strequal(name_, i->name))
6123 if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 :
PUGIXML_TEXT(
"")))
6136 if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 :
PUGIXML_TEXT(
"")))
6142#ifndef PUGIXML_NO_STL
6151 offset += (i !=
_root);
6152 offset += i->name ? impl::strlength(i->name) : 0;
6156 result.resize(offset);
6161 result[--offset] = delimiter;
6165 size_t length = impl::strlength(j->name);
6168 memcpy(&result[offset], j->name, length *
sizeof(
char_t));
6172 assert(offset == 0);
6182 if (!
_root || !path_[0])
return found;
6184 if (path_[0] == delimiter)
6187 found = found.
root();
6191 const char_t* path_segment = path_;
6193 while (*path_segment == delimiter) ++path_segment;
6195 const char_t* path_segment_end = path_segment;
6197 while (*path_segment_end && *path_segment_end != delimiter) ++path_segment_end;
6199 if (path_segment == path_segment_end)
return found;
6201 const char_t* next_segment = path_segment_end;
6203 while (*next_segment == delimiter) ++next_segment;
6205 if (*path_segment ==
'.' && path_segment + 1 == path_segment_end)
6207 else if (*path_segment ==
'.' && *(path_segment+1) ==
'.' && path_segment + 2 == path_segment_end)
6213 if (j->name && impl::strequalrange(j->name, path_segment,
static_cast<size_t>(path_segment_end - path_segment)))
6215 xml_node subsearch =
xml_node(j).first_element_by_path(next_segment, delimiter);
6217 if (subsearch)
return subsearch;
6230 if (!walker.
begin(arg_begin))
return false;
6241 if (!walker.
for_each(arg_for_each))
6244 if (cur->first_child)
6247 cur = cur->first_child;
6249 else if (cur->next_sibling)
6250 cur = cur->next_sibling;
6253 while (!cur->next_sibling && cur !=
_root && cur->
parent)
6260 cur = cur->next_sibling;
6263 while (cur && cur !=
_root);
6266 assert(walker.
_depth == -1);
6269 return walker.
end(arg_end);
6286 impl::xml_buffered_writer buffered_writer(writer, encoding);
6288 impl::node_output(buffered_writer,
_root, indent, flags, depth);
6290 buffered_writer.flush();
6293#ifndef PUGIXML_NO_STL
6298 print(writer, indent, flags, encoding, depth);
6301 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
6311 if (!
_root)
return -1;
6313 impl::xml_document_struct&
doc = impl::get_document(
_root);
6316 if (!
doc.buffer ||
doc.extra_buffers)
return -1;
6335 assert(
false &&
"Invalid node type");
6343 return (
bool)lhs && rhs;
6346 PUGI__FN bool operator||(
const xml_node& lhs,
bool rhs)
6348 return (
bool)lhs || rhs;
6365 if (impl::is_text_node(node))
6399 return _data() == 0;
6406 return (d && d->value) ? d->value + 0 :
PUGIXML_TEXT(
"");
6413 return (d && d->value) ? d->value + 0 : def;
6420 return (d && d->value) ? impl::get_value_int(d->value) : def;
6427 return (d && d->value) ? impl::get_value_uint(d->value) : def;
6434 return (d && d->value) ? impl::get_value_double(d->value) : def;
6441 return (d && d->value) ? impl::get_value_float(d->value) : def;
6448 return (d && d->value) ? impl::get_value_bool(d->value) : def;
6451#ifdef PUGIXML_HAS_LONG_LONG
6452 PUGI__FN long long xml_text::as_llong(
long long def)
const
6456 return (d && d->value) ? impl::get_value_llong(d->value) : def;
6459 PUGI__FN unsigned long long xml_text::as_ullong(
unsigned long long def)
const
6461 xml_node_struct* d =
_data();
6463 return (d && d->value) ? impl::get_value_ullong(d->value) : def;
6471 return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)) :
false;
6478 return dn ? impl::set_value_integer<unsigned int>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) :
false;
6485 return dn ? impl::set_value_integer<unsigned int>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs,
false) :
false;
6492 return dn ? impl::set_value_integer<unsigned long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) :
false;
6499 return dn ? impl::set_value_integer<unsigned long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs,
false) :
false;
6506 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) :
false;
6513 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) :
false;
6520 return dn ? impl::set_value_bool(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) :
false;
6523#ifdef PUGIXML_HAS_LONG_LONG
6528 return dn ? impl::set_value_integer<unsigned long long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false;
6535 return dn ? impl::set_value_integer<unsigned long long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs,
false) : false;
6587#ifdef PUGIXML_HAS_LONG_LONG
6609 return (
bool)lhs && rhs;
6612 PUGI__FN bool operator||(
const xml_text& lhs,
bool rhs)
6614 return (
bool)lhs || rhs;
6832 case status_bad_pi:
return "Error parsing document declaration/processing instruction";
6846 default:
return "Unknown error";
6860#ifdef PUGIXML_HAS_MOVE
6869 if (
this == &rhs)
return *
this;
6897 #ifdef PUGIXML_COMPACT
6899 const size_t page_offset =
sizeof(
void*);
6901 const size_t page_offset = 0;
6908 impl::xml_memory_page* page = impl::xml_memory_page::construct(
_memory);
6911 page->busy_size = impl::xml_memory_page_size;
6914 #ifdef PUGIXML_COMPACT
6916 page->compact_page_marker =
reinterpret_cast<uint32_t*
>(
static_cast<void*
>(
reinterpret_cast<char*
>(page) +
sizeof(impl::xml_memory_page)));
6917 *page->compact_page_marker =
sizeof(impl::xml_memory_page);
6921 _root =
new (
reinterpret_cast<char*
>(page) +
sizeof(impl::xml_memory_page) + page_offset) impl::xml_document_struct(page);
6925 page->allocator =
static_cast<impl::xml_document_struct*
>(
_root);
6928 #ifdef PUGIXML_COMPACT
6929 page->allocator->_hash = &
static_cast<impl::xml_document_struct*
>(
_root)->
hash;
6933 assert(
reinterpret_cast<char*
>(
_root) +
sizeof(impl::xml_document_struct) <=
_memory +
sizeof(
_memory));
6943 impl::xml_memory::deallocate(
_buffer);
6948 for (impl::xml_extra_buffer* extra =
static_cast<impl::xml_document_struct*
>(
_root)->extra_buffers; extra; extra = extra->next)
6950 if (extra->buffer) impl::xml_memory::deallocate(extra->buffer);
6955 assert(root_page && !root_page->prev);
6956 assert(
reinterpret_cast<char*
>(root_page) >=
_memory &&
reinterpret_cast<char*
>(root_page) <
_memory +
sizeof(
_memory));
6958 for (impl::xml_memory_page* page = root_page->
next; page; )
6960 impl::xml_memory_page* next = page->
next;
6962 impl::xml_allocator::deallocate_page(page);
6967 #ifdef PUGIXML_COMPACT
6969 static_cast<impl::xml_document_struct*
>(
_root)->
hash.clear();
6975#ifdef PUGIXML_HAS_MOVE
6978 impl::xml_document_struct*
doc =
static_cast<impl::xml_document_struct*
>(_root);
6979 impl::xml_document_struct* other =
static_cast<impl::xml_document_struct*
>(rhs._root);
6984 #ifdef PUGIXML_COMPACT
6987 if (other_first_child)
6989 size_t other_children = 0;
6997 if (!other->_hash->reserve(other_children + 1))
6999 #ifdef PUGIXML_NO_EXCEPTIONS
7002 throw std::bad_alloc();
7009 doc->_root = other->_root;
7010 doc->_busy_size = other->_busy_size;
7013 doc->buffer = other->buffer;
7014 doc->extra_buffers = other->extra_buffers;
7015 _buffer = rhs._buffer;
7017 #ifdef PUGIXML_COMPACT
7019 doc->hash = other->hash;
7028 assert(doc_page && !doc_page->prev && !doc_page->next);
7031 assert(other_page && !other_page->prev);
7034 if (impl::xml_memory_page* page = other_page->next)
7036 assert(page->
prev == other_page);
7038 page->
prev = doc_page;
7040 doc_page->
next = page;
7041 other_page->
next = 0;
7045 for (impl::xml_memory_page* page = doc_page->next; page; page = page->
next)
7051 #ifdef PUGIXML_COMPACT
7053 if (page->compact_shared_parent == other)
7054 page->compact_shared_parent =
doc;
7059 assert(!
doc->first_child);
7061 doc->first_child = other_first_child;
7063 for (xml_node_struct* node = other_first_child; node; node = node->next_sibling)
7065 #ifdef PUGIXML_COMPACT
7067 assert(node->parent == other || node->parent ==
doc);
7071 assert(node->parent == other);
7077 new (other) impl::xml_document_struct(
PUGI__GETPAGE(other));
7082#ifndef PUGIXML_NO_STL
7087 return impl::load_stream_impl(
static_cast<impl::xml_document_struct*
>(
_root), stream,
options, encoding, &
_buffer);
7101 #ifdef PUGIXML_WCHAR_MODE
7119 using impl::auto_deleter;
7122 return impl::load_file_impl(
static_cast<impl::xml_document_struct*
>(
_root), file.
data,
options, encoding, &
_buffer);
7129 using impl::auto_deleter;
7132 return impl::load_file_impl(
static_cast<impl::xml_document_struct*
>(
_root), file.
data,
options, encoding, &
_buffer);
7139 return impl::load_buffer_impl(
static_cast<impl::xml_document_struct*
>(
_root),
_root,
const_cast<void*
>(contents), size,
options, encoding,
false,
false, &
_buffer);
7146 return impl::load_buffer_impl(
static_cast<impl::xml_document_struct*
>(
_root),
_root, contents, size,
options, encoding,
true,
false, &
_buffer);
7153 return impl::load_buffer_impl(
static_cast<impl::xml_document_struct*
>(
_root),
_root, contents, size,
options, encoding,
true,
true, &
_buffer);
7158 impl::xml_buffered_writer buffered_writer(writer, encoding);
7163 #ifdef PUGIXML_WCHAR_MODE
7164 unsigned int bom = 0xfeff;
7165 buffered_writer.write(
static_cast<wchar_t>(bom));
7167 buffered_writer.write(
'\xef',
'\xbb',
'\xbf');
7173 buffered_writer.write_string(
PUGIXML_TEXT(
"<?xml version=\"1.0\""));
7175 buffered_writer.write(
'?',
'>');
7176 if (!(flags &
format_raw)) buffered_writer.write(
'\n');
7179 impl::node_output(buffered_writer,
_root, indent, flags, 0);
7181 buffered_writer.flush();
7184#ifndef PUGIXML_NO_STL
7189 save(writer, indent, flags, encoding);
7202 using impl::auto_deleter;
7205 return impl::save_file_impl(*
this, file.
data, indent, flags, encoding);
7210 using impl::auto_deleter;
7213 return impl::save_file_impl(*
this, file.
data, indent, flags, encoding);
7227#ifndef PUGIXML_NO_STL
7232 return impl::as_utf8_impl(
str, impl::strlength_wide(
str));
7237 return impl::as_utf8_impl(
str.c_str(),
str.size());
7244 return impl::as_wide_impl(
str, strlen(
str));
7249 return impl::as_wide_impl(
str.c_str(),
str.size());
7255 impl::xml_memory::allocate = allocate;
7256 impl::xml_memory::deallocate = deallocate;
7261 return impl::xml_memory::allocate;
7266 return impl::xml_memory::deallocate;
7270#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC))
7276 return std::bidirectional_iterator_tag();
7281 return std::bidirectional_iterator_tag();
7286 return std::bidirectional_iterator_tag();
7291#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC)
7297 return std::bidirectional_iterator_tag();
7302 return std::bidirectional_iterator_tag();
7307 return std::bidirectional_iterator_tag();
7312#ifndef PUGIXML_NO_XPATH
7317 template <
typename T>
bool operator()(
const T& lhs,
const T& rhs)
const
7325 template <
typename T>
bool operator()(
const T& lhs,
const T& rhs)
const
7333 template <
typename T>
bool operator()(
const T& lhs,
const T& rhs)
const
7341 template <
typename T>
bool operator()(
const T& lhs,
const T& rhs)
const
7347 template <
typename T>
inline void swap(T& lhs, T& rhs)
7358 for (I it = begin + 1; it != end; ++it)
7359 if (pred(*it, *result))
7367 while (end - begin > 1)
7368 swap(*begin++, *--end);
7374 while (end - begin > 1 && *begin != *(begin + 1))
7384 while (begin != end)
7386 if (*begin != *write)
7387 *++write = *begin++;
7401 for (T* it = begin + 1; it != end; ++it)
7407 while (hole > begin && pred(val, *(hole - 1)))
7409 *hole = *(hole - 1);
7418 template <
typename I,
typename Pred>
inline I
median3(I
first, I middle, I
last,
const Pred& pred)
7420 if (pred(*middle, *
first))
7422 if (pred(*
last, *middle))
7424 if (pred(*middle, *
first))
7430 template <
typename T,
typename Pred>
PUGI__FN void partition3(T* begin, T* end, T pivot,
const Pred& pred, T** out_eqbeg, T** out_eqend)
7439 if (pred(*lt, pivot))
7441 else if (*lt == pivot)
7450 for (T* it = begin; it != eq; ++it)
7451 swap(*it, *--eqbeg);
7457 template <
typename I,
typename Pred>
PUGI__FN void sort(I begin, I end,
const Pred& pred)
7460 while (end - begin > 16)
7463 I middle = begin + (end - begin) / 2;
7464 I median =
median3(begin, middle, end - 1, pred);
7468 partition3(begin, end, *median, pred, &eqbeg, &eqend);
7471 if (eqbeg - begin > end - eqend)
7473 sort(eqend, end, pred);
7478 sort(begin, eqbeg, pred);
7491 unsigned int h =
static_cast<unsigned int>(
reinterpret_cast<uintptr_t
>(key));
7500 size_t hashmod = size - 1;
7501 size_t bucket = h & hashmod;
7503 for (
size_t probe = 0; probe <= hashmod; ++probe)
7505 if (table[bucket] == 0)
7507 table[bucket] = key;
7511 if (table[bucket] == key)
7515 bucket = (bucket + probe + 1) & hashmod;
7518 assert(
false &&
"Hash table is full");
7526 #ifdef PUGIXML_MEMORY_XPATH_PAGE_SIZE
7527 PUGIXML_MEMORY_XPATH_PAGE_SIZE
7571 size_t block_capacity_base =
sizeof(
_root->
data);
7572 size_t block_capacity_req = size + block_capacity_base / 4;
7573 size_t block_capacity = (block_capacity_base > block_capacity_req) ? block_capacity_base : block_capacity_req;
7604 if (ptr &&
_root_size - old_size + new_size <= _root->capacity)
7612 if (!result)
return 0;
7618 assert(new_size >= old_size);
7619 memcpy(result, ptr, old_size);
7646 while (cur != state.
_root)
7732 char_t* result =
static_cast<char_t*
>(alloc->
allocate((
length + 1) *
sizeof(char_t)));
7733 if (!result)
return 0;
7735 memcpy(result,
string,
length *
sizeof(char_t));
7753 assert(begin <= end && *end == 0);
7755 return xpath_string(begin,
true,
static_cast<size_t>(end - begin));
7760 assert(begin <= end);
7765 size_t length =
static_cast<size_t>(end - begin);
7788 size_t target_length =
length();
7789 size_t source_length = o.
length();
7790 size_t result_length = target_length + source_length;
7793 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)));
7794 if (!result)
return;
7800 memcpy(result + target_length, o.
_buffer, source_length *
sizeof(char_t));
7801 result[result_length] = 0;
7828 if (!data_)
return 0;
7835 return const_cast<char_t*
>(
_buffer);
7863 while (*pattern && *
string == *pattern)
7869 return *pattern == 0;
7874 #ifdef PUGIXML_WCHAR_MODE
7875 return wcschr(s, c);
7877 return strchr(s, c);
7883 #ifdef PUGIXML_WCHAR_MODE
7885 return (*p == 0) ? s : wcsstr(s, p);
7887 return strstr(s, p);
7894 return static_cast<unsigned int>(ch -
'A') < 26 ?
static_cast<char_t
>(ch |
' ') : ch;
7903 xml_node n = na.node();
7922 xml_node cur = n.first_child();
7924 while (cur && cur != n)
7926 if (cur.type() == node_pcdata || cur.type() == node_cdata)
7929 if (cur.first_child())
7930 cur = cur.first_child();
7931 else if (cur.next_sibling())
7932 cur = cur.next_sibling();
7935 while (!cur.next_sibling() && cur != n)
7938 if (cur != n) cur = cur.next_sibling();
7953 assert(ln->parent == rn->parent);
7956 if (!ln->parent)
return ln < rn;
7959 xml_node_struct* ls = ln;
7960 xml_node_struct* rs = rn;
7964 if (ls == rn)
return true;
7965 if (rs == ln)
return false;
7967 ls = ls->next_sibling;
7968 rs = rs->next_sibling;
7978 xml_node_struct* lp = ln;
7979 xml_node_struct* rp = rn;
7981 while (lp && rp && lp->parent != rp->parent)
7991 bool left_higher = !lp;
8006 if (ln == rn)
return left_higher;
8009 while (ln->parent != rn->parent)
8020 while (node && node != parent) node = node->parent;
8022 return parent && node == parent;
8027 xml_node_struct* node = xnode.node().internal_object();
8033 if (node->name && (node->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0)
return node->name;
8034 if (node->value && (node->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0)
return node->value;
8040 xml_attribute_struct* attr = xnode.attribute().internal_object();
8046 if ((attr->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0)
return attr->name;
8047 if ((attr->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0)
return attr->value;
8058 bool operator()(
const xpath_node& lhs,
const xpath_node& rhs)
const
8064 if (lo && ro)
return lo < ro;
8067 xml_node ln = lhs.node(), rn = rhs.node();
8070 if (lhs.attribute() && rhs.attribute())
8073 if (lhs.parent() == rhs.parent())
8076 for (xml_attribute a = lhs.attribute(); a; a = a.next_attribute())
8077 if (a == rhs.attribute())
8087 else if (lhs.attribute())
8090 if (lhs.parent() == rhs.node())
return false;
8094 else if (rhs.attribute())
8097 if (rhs.parent() == lhs.node())
return true;
8102 if (ln == rn)
return false;
8104 if (!ln || !rn)
return ln < rn;
8106 return node_is_before(ln.internal_object(), rn.internal_object());
8112 #if defined(__STDC_IEC_559__) || ((FLT_RADIX - 0 == 2) && (FLT_MAX_EXP - 0 == 128) && (FLT_MANT_DIG - 0 == 24))
8114 typedef uint32_t UI;
8115 union {
float f; UI i; } u;
8120 const volatile double zero = 0.0;
8127 #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__)
8128 return !!_isnan(value);
8129 #elif defined(fpclassify) && defined(FP_NAN)
8130 return fpclassify(value) == FP_NAN;
8133 const volatile double v = value;
8140 #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__)
8141 if (_finite(value))
return (value == 0) ?
PUGIXML_TEXT(
"0") : 0;
8144 #elif defined(fpclassify) && defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO)
8145 switch (fpclassify(value))
8161 const volatile double v = value;
8172 return (value != 0 && !
is_nan(value));
8177 while (begin != end && end[-1] ==
'0') end--;
8183#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE)
8188 _ecvt_s(
buffer,
sizeof(
buffer), value, DBL_DIG + 1, &exponent, &sign);
8195 *out_exponent = exponent;
8204 char* exponent_string = strchr(
buffer,
'e');
8205 assert(exponent_string);
8207 int exponent = atoi(exponent_string + 1);
8211 assert(mantissa[0] !=
'0' && mantissa[1] ==
'.');
8214 mantissa[1] = mantissa[0];
8222 *out_mantissa = mantissa;
8223 *out_exponent = exponent;
8234 char mantissa_buffer[32];
8241 size_t result_size = strlen(mantissa_buffer) + (exponent > 0 ? exponent : -exponent) + 4;
8242 char_t* result =
static_cast<char_t*
>(alloc->
allocate(
sizeof(char_t) * result_size));
8249 if (value < 0) *s++ =
'-';
8258 while (exponent > 0)
8260 assert(*mantissa == 0 ||
static_cast<unsigned int>(*mantissa -
'0') <= 9);
8261 *s++ = *mantissa ? *mantissa++ :
'0';
8273 while (exponent < 0)
8282 assert(
static_cast<unsigned int>(*mantissa -
'0') <= 9);
8288 assert(s < result + result_size);
8300 if (*
string ==
'-') ++string;
8302 if (!*
string)
return false;
8321 return *
string == 0;
8330 #ifdef PUGIXML_WCHAR_MODE
8331 return wcstod(
string, 0);
8333 return strtod(
string, 0);
8339 size_t length =
static_cast<size_t>(end - begin);
8340 char_t* scratch =
buffer;
8346 if (!scratch)
return false;
8350 memcpy(scratch, begin, length *
sizeof(char_t));
8351 scratch[length] = 0;
8363 return floor(value + 0.5);
8370 return (value >= -0.5 && value <= 0) ? ceil(value) : floor(value + 0.5);
8375 return node.attribute() ? node.attribute().name() : node.node().name();
8383 return p ? p + 1 :
name;
8417 xml_attribute a = p.find_attribute(pred);
8419 if (a)
return a.value();
8434 xml_node p = parent;
8438 xml_attribute a = p.find_attribute(pred);
8440 if (a)
return a.value();
8457 for (char_t* it =
buffer; *it; )
8467 if (write !=
buffer) *write++ =
' ';
8489 const char_t* pos =
find_char(from, ch);
8493 else if (
static_cast<size_t>(pos - from) < to_length)
8494 *write++ = to[pos - from];
8505 unsigned char table[128] = {0};
8509 unsigned int fc =
static_cast<unsigned int>(*from);
8510 unsigned int tc =
static_cast<unsigned int>(*to);
8512 if (fc >= 128 || tc >= 128)
8517 table[fc] =
static_cast<unsigned char>(tc ? tc : 128);
8523 for (
int i = 0; i < 128; ++i)
8525 table[i] =
static_cast<unsigned char>(i);
8527 void* result = alloc->
allocate(
sizeof(table));
8528 if (!result)
return 0;
8530 memcpy(result, table,
sizeof(table));
8532 return static_cast<unsigned char*
>(result);
8542 unsigned int index =
static_cast<unsigned int>(ch);
8546 unsigned char code = table[index];
8550 *write =
static_cast<char_t
>(code);
8551 write += 1 - (code >> 7);
8620 unsigned int result = 0;
8624 result +=
static_cast<unsigned int>(*
str++);
8625 result += result << 10;
8626 result ^= result >> 6;
8629 result += result << 3;
8630 result ^= result >> 11;
8631 result += result << 15;
8639 if (length == 0)
return 0;
8643 if (!memory)
return 0;
8645 T* result =
new (memory) T();
8647 memcpy(result->name,
name, (length + 1) *
sizeof(char_t));
8656 case xpath_type_node_set:
8657 return new_xpath_variable<xpath_variable_node_set>(
name);
8659 case xpath_type_number:
8660 return new_xpath_variable<xpath_variable_number>(
name);
8662 case xpath_type_string:
8663 return new_xpath_variable<xpath_variable_string>(
name);
8665 case xpath_type_boolean:
8666 return new_xpath_variable<xpath_variable_boolean>(
name);
8683 case xpath_type_node_set:
8687 case xpath_type_number:
8691 case xpath_type_string:
8695 case xpath_type_boolean:
8700 assert(
false &&
"Invalid variable type");
8706 switch (rhs->type())
8708 case xpath_type_node_set:
8711 case xpath_type_number:
8714 case xpath_type_string:
8717 case xpath_type_boolean:
8721 assert(
false &&
"Invalid variable type");
8728 size_t length =
static_cast<size_t>(end - begin);
8729 char_t* scratch =
buffer;
8735 if (!scratch)
return false;
8739 memcpy(scratch, begin, length *
sizeof(char_t));
8740 scratch[length] = 0;
8742 *out_result =
set->get(scratch);
8755 if (end - begin < 2)
8756 return xpath_node_set::type_sorted;
8760 bool first = cmp(begin[0], begin[1]);
8762 for (
const xpath_node* it = begin + 1; it + 1 < end; ++it)
8763 if (cmp(it[0], it[1]) !=
first)
8764 return xpath_node_set::type_unsorted;
8766 return first ? xpath_node_set::type_sorted : xpath_node_set::type_sorted_reverse;
8771 xpath_node_set::type_t order = rev ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted;
8773 if (
type == xpath_node_set::type_unsorted)
8777 if (sorted == xpath_node_set::type_unsorted)
8781 type = xpath_node_set::type_sorted;
8794 if (begin == end)
return xpath_node();
8798 case xpath_node_set::type_sorted:
8801 case xpath_node_set::type_sorted_reverse:
8804 case xpath_node_set::type_unsorted:
8808 assert(
false &&
"Invalid node set type");
8809 return xpath_node();
8863 if (begin_ == end_)
return;
8865 size_t size_ =
static_cast<size_t>(
_end -
_begin);
8866 size_t capacity =
static_cast<size_t>(
_eos -
_begin);
8867 size_t count =
static_cast<size_t>(end_ - begin_);
8869 if (size_ + count > capacity)
8872 xpath_node*
data =
static_cast<xpath_node*
>(alloc->
reallocate(
_begin, capacity *
sizeof(xpath_node), (size_ + count) *
sizeof(xpath_node)));
8881 memcpy(
_end, begin_, count *
sizeof(xpath_node));
8903 size_t size_ =
static_cast<size_t>(
_end -
_begin);
8905 size_t hash_size = 1;
8906 while (hash_size < size_ + size_ / 2) hash_size *= 2;
8908 const void** hash_data =
static_cast<const void**
>(alloc->
allocate(hash_size *
sizeof(
void**)));
8909 if (!hash_data)
return;
8911 memset(hash_data, 0, hash_size *
sizeof(
const void**));
8913 xpath_node* write =
_begin;
8915 for (xpath_node* it =
_begin; it !=
_end; ++it)
8917 const void* attr = it->attribute().internal_object();
8918 const void* node = it->node().internal_object();
8919 const void* key = attr ? attr : node;
8921 if (key &&
hash_insert(hash_data, hash_size, key))
8935 xpath_node_set::type_t
type()
const
8948 size_t capacity =
static_cast<size_t>(
_eos -
_begin);
8951 size_t new_capacity = capacity + capacity / 2 + 1;
8954 xpath_node*
data =
static_cast<xpath_node*
>(alloc->
reallocate(
_begin, capacity *
sizeof(xpath_node), new_capacity *
sizeof(xpath_node)));
9020 size_t length =
static_cast<size_t>(
end -
begin);
9047 const char_t* cur =
_cur;
9061 if (*(cur+1) ==
'=')
9074 if (*(cur+1) ==
'=')
9087 if (*(cur+1) ==
'=')
9186 if (*(cur+1) ==
'/')
9199 if (*(cur+1) ==
'.')
9232 char_t terminator = *cur;
9237 while (*cur && *cur != terminator) cur++;
9252 if (*(cur+1) ==
':')
9488 if (lt != xpath_type_node_set && rt != xpath_type_node_set)
9490 if (lt == xpath_type_boolean || rt == xpath_type_boolean)
9492 else if (lt == xpath_type_number || rt == xpath_type_number)
9494 else if (lt == xpath_type_string || rt == xpath_type_string)
9501 return comp(ls, rs);
9504 else if (lt == xpath_type_node_set && rt == xpath_type_node_set)
9511 for (
const xpath_node* li = ls.
begin(); li != ls.
end(); ++li)
9512 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9524 if (lt == xpath_type_node_set)
9530 if (lt == xpath_type_boolean)
9532 else if (lt == xpath_type_number)
9539 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9549 else if (lt == xpath_type_string)
9556 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9568 assert(
false &&
"Wrong types");
9581 if (lt != xpath_type_node_set && rt != xpath_type_node_set)
9583 else if (lt == xpath_type_node_set && rt == xpath_type_node_set)
9590 for (
const xpath_node* li = ls.
begin(); li != ls.
end(); ++li)
9596 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9607 else if (lt != xpath_type_node_set && rt == xpath_type_node_set)
9614 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9624 else if (lt == xpath_type_node_set && rt != xpath_type_node_set)
9631 for (
const xpath_node* li = ls.
begin(); li != ls.
end(); ++li)
9643 assert(
false &&
"Wrong types");
9651 assert(expr->
rettype() != xpath_type_number);
9659 for (xpath_node* it =
last; it != ns.
end(); ++it, ++i)
9677 assert(expr->
rettype() == xpath_type_number);
9685 for (xpath_node* it =
last; it != ns.
end(); ++it, ++i)
9703 assert(expr->
rettype() == xpath_type_number);
9713 if (er >= 1.0 && er <= size)
9715 size_t eri =
static_cast<size_t>(er);
9719 xpath_node r =
last[eri - 1];
9749 pred->apply_predicate(ns,
first, stack, !pred->_next && last_once);
9763 ns.
push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9772 ns.
push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9780 ns.
push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9813 if (
type == node_comment)
9821 if (
type == node_pcdata ||
type == node_cdata)
9829 if (
type == node_pi)
9845 if (
type == node_element)
9861 assert(
false &&
"Unknown axis");
9869 const axis_t axis = T::axis;
9875 for (xml_attribute_struct* a = n->first_attribute; a; a = a->next_attribute)
9884 for (xml_node_struct* c = n->first_child; c; c = c->next_sibling)
9898 xml_node_struct* cur = n->first_child;
9905 if (cur->first_child)
9906 cur = cur->first_child;
9909 while (!cur->next_sibling)
9913 if (cur == n)
return;
9916 cur = cur->next_sibling;
9925 for (xml_node_struct* c = n->next_sibling; c; c = c->next_sibling)
9934 for (xml_node_struct* c = n->prev_sibling_c; c->next_sibling; c = c->prev_sibling_c)
9943 xml_node_struct* cur = n;
9946 while (!cur->next_sibling)
9953 cur = cur->next_sibling;
9960 if (cur->first_child)
9961 cur = cur->first_child;
9964 while (!cur->next_sibling)
9971 cur = cur->next_sibling;
9980 xml_node_struct* cur = n;
9983 while (!cur->prev_sibling_c->next_sibling)
9990 cur = cur->prev_sibling_c;
9994 if (cur->first_child)
9995 cur = cur->first_child->prev_sibling_c;
10002 while (!cur->prev_sibling_c->next_sibling)
10013 cur = cur->prev_sibling_c;
10027 xml_node_struct* cur = n->parent;
10056 assert(
false &&
"Unimplemented axis");
10062 const axis_t axis = T::axis;
10073 xml_node_struct* cur = p;
10097 xml_node_struct* cur = p;
10101 if (cur->first_child)
10102 cur = cur->first_child;
10105 while (!cur->next_sibling)
10112 cur = cur->next_sibling;
10137 assert(
false &&
"Unimplemented axis");
10143 const axis_t axis = T::axis;
10147 step_fill(ns, xn.node().internal_object(), alloc, once, v);
10148 else if (axis_has_attributes && xn.attribute() && xn.parent())
10149 step_fill(ns, xn.attribute().internal_object(), xn.parent().internal_object(), alloc, once, v);
10154 const axis_t axis = T::axis;
10156 const xpath_node_set::type_t axis_type = axis_reverse ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted;
10174 for (
const xpath_node* it = s.
begin(); it != s.
end(); ++it)
10176 size_t size = ns.
size();
10179 if (axis !=
axis_self && size != 0) ns.
set_type(xpath_node_set::type_unsorted);
10204 _data.string = value;
10211 _data.number = value;
10218 _data.variable = value;
10230 _data.nodetest = contents;
10311 if (c.n.attribute())
return false;
10317 for (xml_node n = c.n.node(); n; n = n.parent())
10319 xml_attribute a = n.attribute(
PUGIXML_TEXT(
"xml:lang"));
10323 const char_t* value = a.value();
10326 for (
const char_t* lit = lang.
c_str(); *lit; ++lit)
10332 return *value == 0 || *value ==
'-';
10352 if (
_rettype == xpath_type_boolean)
10353 return _data.variable->get_boolean();
10361 case xpath_type_number:
10364 case xpath_type_string:
10371 case xpath_type_node_set:
10379 assert(
false &&
"Wrong expression for return type boolean");
10409 return _data.number;
10412 return static_cast<double>(c.size);
10415 return static_cast<double>(c.position);
10456 for (
const xpath_node* it = ns.
begin(); it != ns.
end(); ++it)
10470 return r == r ? floor(r) : r;
10477 return r == r ? ceil(r) : r;
10487 if (
_rettype == xpath_type_number)
10488 return _data.variable->get_number();
10496 case xpath_type_boolean:
10499 case xpath_type_string:
10506 case xpath_type_node_set:
10514 assert(
false &&
"Wrong expression for return type number");
10543 assert(pos == count);
10547 for (
size_t i = 0; i < count; ++i) length +=
buffer[i].length();
10550 char_t* result =
static_cast<char_t*
>(stack.
result->
allocate((length + 1) *
sizeof(char_t)));
10553 char_t* ri = result;
10555 for (
size_t j = 0; j < count; ++j)
10556 for (
const char_t* bi =
buffer[j].
c_str(); *bi; ++bi)
10573 xpath_node na = c.n;
10583 xpath_node na = ns.
first();
10590 xpath_node na = c.n;
10600 xpath_node na = ns.
first();
10607 xpath_node na = c.n;
10617 xpath_node na = ns.
first();
10657 const char_t* rbegin = pos + p.
length();
10670 size_t s_length = s.
length();
10677 size_t pos = first < 1 ? 1 : static_cast<size_t>(
first);
10678 assert(1 <= pos && pos <= s_length + 1);
10680 const char_t* rbegin = s.
c_str() + (pos - 1);
10693 size_t s_length = s.
length();
10703 size_t pos = first < 1 ? 1 : static_cast<size_t>(
first);
10704 size_t end =
last >= s_length + 1 ? s_length + 1 :
static_cast<size_t>(
last);
10706 assert(1 <= pos && pos <= end && end <= s_length + 1);
10707 const char_t* rbegin = s.
c_str() + (pos - 1);
10708 const char_t* rend = s.
c_str() + (end - 1);
10771 if (
_rettype == xpath_type_string)
10780 case xpath_type_boolean:
10783 case xpath_type_number:
10786 case xpath_type_node_set:
10797 assert(
false &&
"Wrong expression for return type string");
10818 ls.
set_type(xpath_node_set::type_unsorted);
10888 assert(
false &&
"Unknown axis");
10899 ns.
set_type(xpath_node_set::type_sorted);
10902 else if (c.n.attribute()) ns.
push_back(c.n.parent().root(), stack.
result);
10911 if (
_rettype == xpath_type_node_set)
10913 const xpath_node_set& s =
_data.variable->get_node_set();
10926 assert(
false &&
"Wrong expression for return type node set");
11036 if (!n->is_posinv_expr())
return false;
11059 return static_cast<xpath_value_type
>(
_rettype);
11137 size_t length =
static_cast<size_t>(value.end - value.begin);
11139 char_t* c =
static_cast<char_t*
>(
_alloc->
allocate((length + 1) *
sizeof(char_t)));
11142 memcpy(c, value.begin, length *
sizeof(char_t));
11150 switch (
name.begin[0])
11161 if (
args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11194 if (argc == 1 &&
args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11203 if (argc == 1 &&
args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11208 if (argc == 1 &&
args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11247 if (
args[0]->rettype() != xpath_type_node_set)
return error(
"Function has to be applied to node set");
11265 return error(
"Unrecognized function or wrong parameter count");
11272 switch (
name.begin[0])
11338 switch (
name.begin[0])
11381 return error(
"Unknown variable: variable set is not provided");
11383 xpath_variable* var = 0;
11388 return error(
"Unknown variable: variable set does not contain the given name");
11403 return error(
"Expected ')' to match an opening '('");
11413 if (!value)
return 0;
11443 return error(
"Unrecognized function call");
11451 return error(
"No comma between function arguments");
11458 if (argc < 2)
args[argc] = n;
11471 return error(
"Unrecognizable primary expression");
11487 if (n->
rettype() != xpath_type_node_set)
11488 return error(
"Predicate has to be applied to node set");
11491 if (!expr)
return 0;
11497 return error(
"Expected ']' to match an opening '['");
11512 if (
set &&
set->rettype() != xpath_type_node_set)
11513 return error(
"Step has to be applied to node set");
11515 bool axis_specified =
false;
11521 axis_specified =
true;
11530 return error(
"Predicates are not allowed after an abbreviated step");
11539 return error(
"Predicates are not allowed after an abbreviated step");
11557 if (axis_specified)
11558 return error(
"Two axis specifiers in one step");
11562 if (!axis_specified)
11563 return error(
"Unknown axis");
11581 return error(
"Unrecognized node test");
11599 return error(
"Unrecognized node type");
11603 else if (nt_name ==
PUGIXML_TEXT(
"processing-instruction"))
11606 return error(
"Only literals are allowed as arguments to processing-instruction()");
11613 return error(
"Unmatched brace near processing-instruction()");
11618 return error(
"Unmatched brace near node type test");
11624 if (nt_name.
end - nt_name.
begin > 2 && nt_name.
end[-2] ==
':' && nt_name.
end[-1] ==
'*')
11644 return error(
"Unrecognized node test");
11648 if (!nt_name_copy)
return 0;
11660 if (!expr)
return 0;
11663 if (!pred)
return 0;
11666 return error(
"Expected ']' to match an opening '['");
11781 if (n->
rettype() != xpath_type_node_set)
11782 return error(
"Step has to be applied to node set");
11885 if (!rhs)
return 0;
11892 if (!rhs)
return 0;
11898 return error(
"Union operator has to be applied to node sets");
11901 if (!lhs)
return 0;
11946 return error(
"Incorrect query");
11955 return parser.
parse();
11964 if (!memory)
return 0;
11992 if (!impl)
return 0;
11994 if (impl->
root->
rettype() != xpath_type_node_set)
11996 #ifdef PUGIXML_NO_EXCEPTIONS
11999 xpath_parse_result res;
12000 res.error =
"Expression does not evaluate to node set";
12002 throw xpath_exception(res);
12012#ifndef PUGIXML_NO_EXCEPTIONS
12083 return (
bool)lhs && rhs;
12086 PUGI__FN bool operator||(
const xpath_node& lhs,
bool rhs)
12088 return (
bool)lhs || rhs;
12094 assert(begin_ <= end_);
12096 size_t size_ =
static_cast<size_t>(end_ - begin_);
12099 xpath_node* storage = (size_ <= 1) ? _storage : static_cast<xpath_node*>(impl::xml_memory::allocate(size_ *
sizeof(
xpath_node)));
12103 #ifdef PUGIXML_NO_EXCEPTIONS
12106 throw std::bad_alloc();
12112 impl::xml_memory::deallocate(
_begin);
12116 memcpy(storage, begin_, size_ *
sizeof(
xpath_node));
12119 _end = storage + size_;
12123#ifdef PUGIXML_HAS_MOVE
12127 _storage[0] = rhs._storage[0];
12128 _begin = (rhs._begin == rhs._storage) ? _storage : rhs._begin;
12129 _end = _begin + (rhs._end - rhs._begin);
12131 rhs._type = type_unsorted;
12132 rhs._begin = rhs._storage;
12133 rhs._end = rhs._storage;
12143 _assign(begin_, end_, type_);
12149 impl::xml_memory::deallocate(
_begin);
12159 if (
this == &ns)
return *
this;
12166#ifdef PUGIXML_HAS_MOVE
12174 if (
this == &rhs)
return *
this;
12176 if (_begin != _storage)
12177 impl::xml_memory::deallocate(_begin);
12202 assert(index <
size());
12249 return static_cast<const impl::xpath_variable_node_set*
>(
this)->
name;
12252 return static_cast<const impl::xpath_variable_number*
>(
this)->
name;
12255 return static_cast<const impl::xpath_variable_string*
>(
this)->
name;
12258 return static_cast<const impl::xpath_variable_boolean*
>(
this)->
name;
12261 assert(
false &&
"Invalid variable type");
12273 return (
_type ==
xpath_type_boolean) ?
static_cast<const impl::xpath_variable_boolean*
>(
this)->value :
false;
12278 return (
_type ==
xpath_type_number) ?
static_cast<const impl::xpath_variable_number*
>(
this)->value : impl::gen_nan();
12289 return (
_type ==
xpath_type_node_set) ?
static_cast<const impl::xpath_variable_node_set*
>(
this)->value : impl::dummy_node_set;
12296 static_cast<impl::xpath_variable_boolean*
>(
this)->value = value;
12304 static_cast<impl::xpath_variable_number*
>(
this)->value = value;
12312 impl::xpath_variable_string* var =
static_cast<impl::xpath_variable_string*
>(
this);
12315 size_t size = (impl::strlength(value) + 1) *
sizeof(
char_t);
12318 if (!
copy)
return false;
12320 memcpy(
copy, value, size);
12323 if (var->value) impl::xml_memory::deallocate(var->value);
12333 static_cast<impl::xpath_variable_node_set*
>(
this)->value = value;
12339 for (
size_t i = 0; i <
sizeof(
_data) /
sizeof(
_data[0]); ++i)
12345 for (
size_t i = 0; i <
sizeof(
_data) /
sizeof(
_data[0]); ++i)
12351 for (
size_t i = 0; i <
sizeof(
_data) /
sizeof(
_data[0]); ++i)
12359 if (
this == &rhs)
return *
this;
12366#ifdef PUGIXML_HAS_MOVE
12369 for (
size_t i = 0; i <
sizeof(_data) /
sizeof(_data[0]); ++i)
12371 _data[i] = rhs._data[i];
12378 for (
size_t i = 0;
i <
sizeof(_data) /
sizeof(_data[0]); ++
i)
12380 _destroy(_data[i]);
12382 _data[
i] = rhs._data[
i];
12394 for (
size_t i = 0; i <
sizeof(
_data) /
sizeof(
_data[0]); ++i)
12403 for (
size_t i = 0; i <
sizeof(
_data) /
sizeof(
_data[0]); ++i)
12408 rhs.
_data[i] = chain;
12414 const size_t hash_size =
sizeof(
_data) /
sizeof(
_data[0]);
12415 size_t hash = impl::hash_string(
name) % hash_size;
12419 if (impl::strequal(var->name(),
name))
12433 if (!nvar)
return false;
12437 last->_next = nvar;
12439 *out_result = nvar;
12444 if (!impl::copy_xpath_variable(nvar, var))
return false;
12458 impl::delete_xpath_variable(var->
_type, var);
12466 const size_t hash_size =
sizeof(
_data) /
sizeof(
_data[0]);
12467 size_t hash = impl::hash_string(
name) % hash_size;
12471 if (impl::strequal(var->name(),
name))
12472 return var->type() ==
type ? var : 0;
12490 return var ? var->
set(value) :
false;
12496 return var ? var->
set(value) :
false;
12502 return var ? var->
set(value) :
false;
12508 return var ? var->
set(value) :
false;
12523 impl::xpath_query_impl* qimpl = impl::xpath_query_impl::create();
12527 #ifdef PUGIXML_NO_EXCEPTIONS
12530 throw std::bad_alloc();
12535 using impl::auto_deleter;
12538 qimpl->root = impl::xpath_parser::parse(query, variables, &qimpl->alloc, &
_result);
12542 qimpl->root->optimize(&qimpl->alloc);
12549 #ifdef PUGIXML_NO_EXCEPTIONS
12552 if (qimpl->oom)
throw std::bad_alloc();
12566 impl::xpath_query_impl::destroy(
static_cast<impl::xpath_query_impl*
>(
_impl));
12569#ifdef PUGIXML_HAS_MOVE
12573 _result = rhs._result;
12580 if (
this == &rhs)
return *
this;
12583 impl::xpath_query_impl::destroy(
static_cast<impl::xpath_query_impl*
>(_impl));
12586 _result = rhs._result;
12588 rhs._result = xpath_parse_result();
12598 return static_cast<impl::xpath_query_impl*
>(
_impl)->root->rettype();
12603 if (!
_impl)
return false;
12605 impl::xpath_context c(n, 1, 1);
12606 impl::xpath_stack_data sd;
12608 bool r =
static_cast<impl::xpath_query_impl*
>(
_impl)->root->eval_boolean(c, sd.stack);
12612 #ifdef PUGIXML_NO_EXCEPTIONS
12615 throw std::bad_alloc();
12624 if (!
_impl)
return impl::gen_nan();
12626 impl::xpath_context c(n, 1, 1);
12627 impl::xpath_stack_data sd;
12629 double r =
static_cast<impl::xpath_query_impl*
>(
_impl)->root->eval_number(c, sd.stack);
12633 #ifdef PUGIXML_NO_EXCEPTIONS
12634 return impl::gen_nan();
12636 throw std::bad_alloc();
12643#ifndef PUGIXML_NO_STL
12648 impl::xpath_context c(n, 1, 1);
12649 impl::xpath_stack_data sd;
12651 impl::xpath_string r =
static_cast<impl::xpath_query_impl*
>(
_impl)->root->eval_string(c, sd.stack);
12655 #ifdef PUGIXML_NO_EXCEPTIONS
12658 throw std::bad_alloc();
12662 return string_t(r.c_str(), r.length());
12668 impl::xpath_context c(n, 1, 1);
12669 impl::xpath_stack_data sd;
12671 impl::xpath_string r =
_impl ?
static_cast<impl::xpath_query_impl*
>(
_impl)->root->eval_string(c, sd.stack) : impl::xpath_string();
12675 #ifdef PUGIXML_NO_EXCEPTIONS
12676 r = impl::xpath_string();
12678 throw std::bad_alloc();
12682 size_t full_size = r.length() + 1;
12686 size_t size = (full_size < capacity) ? full_size : capacity;
12689 memcpy(
buffer, r.c_str(), (size - 1) *
sizeof(
char_t));
12698 impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(
static_cast<impl::xpath_query_impl*
>(
_impl));
12701 impl::xpath_context c(n, 1, 1);
12702 impl::xpath_stack_data sd;
12704 impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack, impl::nodeset_eval_all);
12708 #ifdef PUGIXML_NO_EXCEPTIONS
12711 throw std::bad_alloc();
12720 impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(
static_cast<impl::xpath_query_impl*
>(
_impl));
12723 impl::xpath_context c(n, 1, 1);
12724 impl::xpath_stack_data sd;
12726 impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack, impl::nodeset_eval_first);
12730 #ifdef PUGIXML_NO_EXCEPTIONS
12733 throw std::bad_alloc();
12801#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
12802# pragma warning(pop)
12805#if defined(_MSC_VER) && defined(__c2__)
12806# pragma clang diagnostic pop
12810#undef PUGI__NO_INLINE
12811#undef PUGI__UNLIKELY
12812#undef PUGI__STATIC_ASSERT
12813#undef PUGI__DMC_VOLATILE
12814#undef PUGI__UNSIGNED_OVERFLOW
12815#undef PUGI__MSVC_CRT_VERSION
12816#undef PUGI__SNPRINTF
12817#undef PUGI__NS_BEGIN
12820#undef PUGI__FN_NO_INLINE
12821#undef PUGI__GETHEADER_IMPL
12822#undef PUGI__GETPAGE_IMPL
12823#undef PUGI__GETPAGE
12824#undef PUGI__NODETYPE
12825#undef PUGI__IS_CHARTYPE_IMPL
12826#undef PUGI__IS_CHARTYPE
12827#undef PUGI__IS_CHARTYPEX
12828#undef PUGI__ENDSWITH
12831#undef PUGI__PUSHNODE
12832#undef PUGI__POPNODE
12833#undef PUGI__SCANFOR
12834#undef PUGI__SCANWHILE
12835#undef PUGI__SCANWHILE_UNROLL
12837#undef PUGI__THROW_ERROR
12838#undef PUGI__CHECK_ERROR
Reference counted object base class.
\rst Holds a reference to a Python object (with reference counting)
handle release()
\rst Resets the internal pointer to nullptr without decreasing the object's reference count.
bool operator!=(const xml_attribute_iterator &rhs) const
const xml_attribute_iterator & operator--()
xml_attribute * operator->() const
xml_attribute & operator*() const
bool operator==(const xml_attribute_iterator &rhs) const
const xml_attribute_iterator & operator++()
const char_t * as_string(const char_t *def=PUGIXML_TEXT("")) const
bool operator>=(const xml_attribute &r) const
bool as_bool(bool def=false) const
bool operator!=(const xml_attribute &r) const
bool operator<(const xml_attribute &r) const
int as_int(int def=0) const
float as_float(float def=0) const
bool operator==(const xml_attribute &r) const
size_t hash_value() const
const char_t * name() const
xml_attribute & operator=(const char_t *rhs)
xml_attribute previous_attribute() const
xml_attribute_struct * _attr
xml_attribute next_attribute() const
bool operator<=(const xml_attribute &r) const
double as_double(double def=0) const
void(* unspecified_bool_type)(xml_attribute ***)
bool set_name(const char_t *rhs)
bool set_value(const char_t *rhs)
unsigned int as_uint(unsigned int def=0) const
xml_attribute_struct * internal_object() const
bool operator>(const xml_attribute &r) const
const char_t * value() const
xml_parse_result load_buffer_inplace(void *contents, size_t size, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
xml_node document_element() const
xml_parse_result load_string(const char_t *contents, unsigned int options=parse_default)
bool save_file(const char *path, const char_t *indent=PUGIXML_TEXT("\t"), unsigned int flags=format_default, xml_encoding encoding=encoding_auto) const
xml_parse_result load_buffer_inplace_own(void *contents, size_t size, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
xml_parse_result load_file(const char *path, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
xml_parse_result load_buffer(const void *contents, size_t size, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
xml_document & operator=(const xml_document &)
xml_parse_result load(std::basic_istream< char, std::char_traits< char > > &stream, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
void save(xml_writer &writer, const char_t *indent=PUGIXML_TEXT("\t"), unsigned int flags=format_default, xml_encoding encoding=encoding_auto) const
void _move(xml_document &rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT
xml_named_node_iterator()
bool operator!=(const xml_named_node_iterator &rhs) const
xml_node * operator->() const
const xml_named_node_iterator & operator--()
bool operator==(const xml_named_node_iterator &rhs) const
xml_node & operator*() const
const xml_named_node_iterator & operator++()
bool operator==(const xml_node_iterator &rhs) const
const xml_node_iterator & operator--()
xml_node * operator->() const
bool operator!=(const xml_node_iterator &rhs) const
const xml_node_iterator & operator++()
xml_node & operator*() const
string_t path(char_t delimiter='/') const
size_t hash_value() const
PUGIXML_DEPRECATED xpath_node select_single_node(const char_t *query, xpath_variable_set *variables=0) const
bool set_value(const char_t *rhs)
xml_node_type type() const
xml_node append_child(xml_node_type type=node_element)
xml_node child(const char_t *name) const
friend class xml_named_node_iterator
xml_node insert_move_after(const xml_node &moved, const xml_node &node)
xml_node last_child() const
xml_node append_move(const xml_node &moved)
xml_node first_child() const
bool operator>(const xml_node &r) const
xml_object_range< xml_node_iterator > children() const
xml_node prepend_move(const xml_node &moved)
xml_attribute append_attribute(const char_t *name)
xml_node next_sibling() const
xml_node_struct * internal_object() const
xml_object_range< xml_attribute_iterator > attributes() const
bool remove_child(const xml_node &n)
xml_attribute append_copy(const xml_attribute &proto)
xml_node insert_child_after(xml_node_type type, const xml_node &node)
xml_attribute last_attribute() const
attribute_iterator attributes_end() const
xml_node previous_sibling() const
xpath_node select_node(const char_t *query, xpath_variable_set *variables=0) const
ptrdiff_t offset_debug() const
xml_attribute insert_attribute_before(const char_t *name, const xml_attribute &attr)
xml_attribute insert_attribute_after(const char_t *name, const xml_attribute &attr)
bool operator!=(const xml_node &r) const
bool operator<(const xml_node &r) const
xml_attribute prepend_attribute(const char_t *name)
xml_parse_result append_buffer(const void *contents, size_t size, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
const char_t * value() const
void(* unspecified_bool_type)(xml_node ***)
xml_attribute_iterator attribute_iterator
bool traverse(xml_tree_walker &walker)
xml_node find_child_by_attribute(const char_t *name, const char_t *attr_name, const char_t *attr_value) const
const char_t * child_value() const
bool set_name(const char_t *rhs)
xml_node prepend_child(xml_node_type type=node_element)
xml_attribute first_attribute() const
bool operator>=(const xml_node &r) const
xml_attribute insert_copy_after(const xml_attribute &proto, const xml_attribute &attr)
xml_attribute prepend_copy(const xml_attribute &proto)
xml_node insert_move_before(const xml_node &moved, const xml_node &node)
xml_node first_element_by_path(const char_t *path, char_t delimiter='/') const
xml_attribute attribute(const char_t *name) const
const char_t * name() const
xml_attribute insert_copy_before(const xml_attribute &proto, const xml_attribute &attr)
attribute_iterator attributes_begin() const
xpath_node_set select_nodes(const char_t *query, xpath_variable_set *variables=0) const
xml_node_iterator iterator
bool operator<=(const xml_node &r) const
bool remove_attribute(const xml_attribute &a)
void print(xml_writer &writer, const char_t *indent=PUGIXML_TEXT("\t"), unsigned int flags=format_default, xml_encoding encoding=encoding_auto, unsigned int depth=0) const
xml_node insert_child_before(xml_node_type type, const xml_node &node)
bool operator==(const xml_node &r) const
const char_t * as_string(const char_t *def=PUGIXML_TEXT("")) const
double as_double(double def=0) const
xml_text & operator=(const char_t *rhs)
float as_float(float def=0) const
xml_node_struct * _data_new()
bool as_bool(bool def=false) const
bool set(const char_t *rhs)
int as_int(int def=0) const
unsigned int as_uint(unsigned int def=0) const
void(* unspecified_bool_type)(xml_text ***)
const char_t * get() const
xml_node_struct * _data() const
virtual bool end(xml_node &node)
virtual bool for_each(xml_node &node)=0
virtual bool begin(xml_node &node)
virtual ~xml_tree_walker()
xml_writer_file(void *file)
virtual void write(const void *data, size_t size) PUGIXML_OVERRIDE
xml_writer_stream(std::basic_ostream< char, std::char_traits< char > > &stream)
std::basic_ostream< wchar_t, std::char_traits< wchar_t > > * wide_stream
virtual void write(const void *data, size_t size) PUGIXML_OVERRIDE
std::basic_ostream< char, std::char_traits< char > > * narrow_stream
virtual const char * what() const PUGIXML_OVERRIDE
const xpath_parse_result & result() const
xpath_exception(const xpath_parse_result &result)
xpath_parse_result _result
xpath_node_set & operator=(const xpath_node_set &ns)
void _assign(const_iterator begin, const_iterator end, type_t type)
const_iterator end() const
void sort(bool reverse=false)
const_iterator begin() const
const xpath_node & operator[](size_t index) const
void _move(xpath_node_set &rhs) PUGIXML_NOEXCEPT
void(* unspecified_bool_type)(xpath_node ***)
xml_attribute attribute() const
bool operator!=(const xpath_node &n) const
bool operator==(const xpath_node &n) const
string_t evaluate_string(const xpath_node &n) const
void(* unspecified_bool_type)(xpath_query ***)
double evaluate_number(const xpath_node &n) const
xpath_node_set evaluate_node_set(const xpath_node &n) const
xpath_value_type return_type() const
xpath_parse_result _result
xpath_query & operator=(const xpath_query &)
const xpath_parse_result & result() const
bool evaluate_boolean(const xpath_node &n) const
xpath_node evaluate_node(const xpath_node &n) const
xpath_variable * add(const char_t *name, xpath_value_type type)
void _swap(xpath_variable_set &rhs)
bool set(const char_t *name, bool value)
void _assign(const xpath_variable_set &rhs)
static void _destroy(xpath_variable *var)
static bool _clone(xpath_variable *var, xpath_variable **out_result)
xpath_variable * get(const char_t *name)
xpath_variable * _data[64]
xpath_variable * _find(const char_t *name) const
xpath_variable_set & operator=(const xpath_variable_set &rhs)
xpath_variable(xpath_value_type type)
double get_number() const
const char_t * get_string() const
const xpath_node_set & get_node_set() const
xpath_value_type type() const
const char_t * name() const
Reference counting helper.
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)
xml_buffered_writer(const xml_buffered_writer &)
char_t data_char[bufcapacity]
xml_buffered_writer & operator=(const xml_buffered_writer &)
void flush(const char_t *data, size_t size)
uint16_t data_u16[2 *bufcapacity]
union xml_buffered_writer::@9 scratch
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]
union xpath_ast_node::@12 _data
const unsigned char * table
xpath_variable * variable
void set_next(xpath_ast_node *value)
bool step_push(xpath_node_set_raw &ns, xml_node_struct *n, xpath_allocator *alloc)
xpath_value_type rettype() const
xpath_node_set_raw step_do(const xpath_context &c, const xpath_stack &stack, nodeset_eval_t eval, T v)
static bool eval_once(xpath_node_set::type_t type, nodeset_eval_t eval)
void optimize_self(xpath_allocator *alloc)
bool is_posinv_expr() const
bool step_push(xpath_node_set_raw &ns, xml_attribute_struct *a, xml_node_struct *parent, xpath_allocator *alloc)
xpath_node_set_raw eval_node_set(const xpath_context &c, const xpath_stack &stack, nodeset_eval_t eval)
xpath_string eval_string(const xpath_context &c, const xpath_stack &stack)
xpath_ast_node(ast_type_t type, xpath_ast_node *left, axis_t axis, nodetest_t test, const char_t *contents)
void apply_predicate(xpath_node_set_raw &ns, size_t first, const xpath_stack &stack, bool once)
static void apply_predicate_number_const(xpath_node_set_raw &ns, size_t first, xpath_ast_node *expr, const xpath_stack &stack)
xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_variable *value)
double eval_number(const xpath_context &c, const xpath_stack &stack)
void optimize(xpath_allocator *alloc)
static bool compare_eq(xpath_ast_node *lhs, xpath_ast_node *rhs, const xpath_context &c, const xpath_stack &stack, const Comp &comp)
bool is_posinv_step() const
xpath_string eval_string_concat(const xpath_context &c, const xpath_stack &stack)
static void apply_predicate_boolean(xpath_node_set_raw &ns, size_t first, xpath_ast_node *expr, const xpath_stack &stack, bool once)
bool eval_boolean(const xpath_context &c, const xpath_stack &stack)
static bool compare_rel(xpath_ast_node *lhs, xpath_ast_node *rhs, const xpath_context &c, const xpath_stack &stack, const Comp &comp)
static void apply_predicate_number(xpath_node_set_raw &ns, size_t first, xpath_ast_node *expr, const xpath_stack &stack, bool once)
xpath_ast_node & operator=(const xpath_ast_node &)
void step_fill(xpath_node_set_raw &ns, xml_attribute_struct *a, xml_node_struct *p, xpath_allocator *alloc, bool once, T v)
void step_fill(xpath_node_set_raw &ns, xml_node_struct *n, xpath_allocator *alloc, bool once, T)
void step_fill(xpath_node_set_raw &ns, const xpath_node &xn, xpath_allocator *alloc, bool once, T v)
xpath_ast_node(ast_type_t type, xpath_value_type rettype_, double value)
xpath_ast_node(const xpath_ast_node &)
xpath_ast_node(ast_type_t type, xpath_ast_node *left, xpath_ast_node *right, predicate_t test)
void apply_predicates(xpath_node_set_raw &ns, size_t first, const xpath_stack &stack, nodeset_eval_t eval)
xpath_ast_node(ast_type_t type, xpath_value_type rettype_, const char_t *value)
xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_ast_node *left=0, xpath_ast_node *right=0)
void set_right(xpath_ast_node *value)
const char_t * _cur_lexeme_pos
const char_t * current_pos() const
xpath_lexer_string _cur_lexeme_contents
const xpath_lexer_string & contents() const
xpath_lexer(const char_t *query)
const char_t * state() const
xpath_node_set::type_t _type
void append(const xpath_node *begin_, const xpath_node *end_, xpath_allocator *alloc)
xpath_node_set::type_t type() const
void push_back(const xpath_node &node, xpath_allocator *alloc)
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
xpath_string(const char_t *buffer, bool uses_heap_, size_t length_heap)
void append(const xpath_string &o, xpath_allocator *alloc)
static xpath_string from_heap(const char_t *begin, const char_t *end, xpath_allocator *alloc)
char_t * data(xpath_allocator *alloc)
bool operator==(const xpath_string &o) const
static char_t * duplicate_string(const char_t *string, size_t length, xpath_allocator *alloc)
const char_t * c_str() const
std::basic_string< PUGIXML_CHAR, std::char_traits< PUGIXML_CHAR >, std::allocator< PUGIXML_CHAR > > string_t
const unsigned int format_no_declaration
const unsigned int format_raw
void(* deallocation_function)(void *ptr)
std::basic_string< char, std::char_traits< char >, std::allocator< char > > PUGIXML_FUNCTION as_utf8(const wchar_t *str)
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)
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
void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate)
deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function()
std::basic_string< wchar_t, std::char_traits< wchar_t >, std::allocator< wchar_t > > PUGIXML_FUNCTION as_wide(const char *str)
const unsigned int format_save_file_text
allocation_function PUGIXML_FUNCTION get_memory_allocation_function()
const unsigned int format_write_bom
static PUGI__FN void unspecified_bool_xpath_node(xpath_node ***)
static PUGI__FN void unspecified_bool_xml_text(xml_text ***)
void insert(std::ostream &aStr, const U &aU)
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 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__NS_END PUGI__NS_BEGIN xml_attribute_struct * allocate_attribute(xml_allocator &alloc)
#define PUGI__UNLIKELY(cond)
#define PUGI__THROW_ERROR(err, m)
PUGI__FN const char_t * namespace_uri(xml_node node)
xml_parse_result make_parse_result(xml_parse_status status, ptrdiff_t offset=0)
xml_allocator & get_allocator(const Object *object)
PUGI__FN bool set_value_convert(String &dest, Header &header, uintptr_t header_mask, float value)
PUGI__FN 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)
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
constexpr int last(int, int result)
constexpr int first(int i)
Implementation details for constexpr functions.
@ copy
Create a new copy of the returned object, which will be owned by Python.
const char * c_str(Args &&...args)
Constructs a std::string with the given arguments, stores it in internals, and returns its c_str().
object eval(const str &expr, object global=globals(), object local=object())
arr data(const arr &a, Ix... index)
auto_deleter(T *data_, D deleter_)
Annotation indicating that a class derives from another given type.
Annotation for documentation.
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_)
Annotation for function names.
namespace_uri_predicate(const char_t *name)
bool operator()(xml_attribute a) const
bool operator()(const T &lhs, const T &rhs) const
xml_attribute_struct * prev_attribute_c
xml_attribute_struct(impl::xml_memory_page *page)
xml_attribute_struct * next_attribute
xml_attribute_struct * first_attribute
xml_node_struct * prev_sibling_c
xml_node_struct * next_sibling
xml_node_struct * first_child
xml_node_struct(impl::xml_memory_page *page, xml_node_type type)
const char * description() const
const char * description() const
static char_t * parse_eol(char_t *s, char_t end_quote)
static char_t * parse_simple(char_t *s, char_t end_quote)
static char_t * parse_wnorm(char_t *s, char_t end_quote)
static char_t * parse_wconv(char_t *s, char_t end_quote)
static char_t * parse(char_t *s)
static value_type low(value_type result, uint32_t)
static value_type high(value_type result, uint32_t)
static Traits::value_type process(const uint16_t *data, size_t size, typename Traits::value_type result, Traits)
static value_type high(value_type result, uint32_t ch)
static value_type low(value_type result, uint32_t ch)
static value_type any(value_type result, uint32_t ch)
static value_type low(value_type result, uint32_t)
static value_type high(value_type result, uint32_t)
static Traits::value_type process(const uint32_t *data, size_t size, typename Traits::value_type result, Traits)
static value_type low(value_type result, uint32_t ch)
static value_type high(value_type result, uint32_t ch)
static value_type any(value_type result, uint32_t ch)
static value_type low(value_type result, uint32_t ch)
static value_type high(value_type result, uint32_t)
static Traits::value_type process(const uint8_t *data, size_t size, typename Traits::value_type result, Traits)
static value_type any(value_type result, uint32_t ch)
static value_type high(value_type result, uint32_t ch)
static value_type low(value_type result, uint32_t ch)
static Traits::value_type process(const wchar_t *data, size_t size, typename Traits::value_type result, Traits traits)
utf16_decoder< opt_false > decoder
utf32_decoder< opt_false > decoder
void * allocate_memory(size_t size, xml_memory_page *&out_page)
void * allocate_object(size_t size, xml_memory_page *&out_page)
char_t * allocate_string(size_t length)
static void deallocate_page(xml_memory_page *page)
void * allocate_memory_oob(size_t size, xml_memory_page *&out_page)
void deallocate_memory(void *ptr, size_t size, xml_memory_page *page)
xml_memory_page * allocate_page(size_t data_size)
xml_allocator(xml_memory_page *root)
void deallocate_string(char_t *string)
xml_document_struct(xml_memory_page *page)
xml_extra_buffer * extra_buffers
static deallocation_function deallocate
static allocation_function allocate
static xml_memory_page * construct(void *memory)
xml_allocator * allocator
static char_t * parse_skip_bom(char_t *s)
xml_parse_status error_status
xml_parser(xml_allocator *alloc_)
char_t * parse_doctype_primitive(char_t *s)
char_t * parse_tree(char_t *s, xml_node_struct *root, unsigned int optmsk, char_t endch)
static xml_parse_result parse(char_t *buffer, size_t length, xml_document_struct *xmldoc, xml_node_struct *root, unsigned int optmsk)
static bool has_element_node_siblings(xml_node_struct *node)
char_t * parse_doctype_group(char_t *s, char_t endch)
char_t * parse_question(char_t *s, xml_node_struct *&ref_cursor, unsigned int optmsk, char_t endch)
char_t * parse_doctype_ignore(char_t *s)
char_t * parse_exclamation(char_t *s, xml_node_struct *cursor, unsigned int optmsk, char_t endch)
static xml_stream_chunk * create()
T data[xml_memory_page_size/sizeof(T)]
static void destroy(xml_stream_chunk *chunk)
~xpath_allocator_capture()
xpath_allocator * _target
xpath_allocator_capture(xpath_allocator *alloc)
void * reallocate(void *ptr, size_t old_size, size_t new_size)
void * allocate(size_t size)
xpath_memory_block * _root
void revert(const xpath_allocator &state)
xpath_allocator(xpath_memory_block *root, bool *error=0)
xpath_context(const xpath_node &n_, size_t position_, size_t size_)
bool operator==(const char_t *other) const
char data[xpath_memory_page_size]
xpath_memory_block * next
binary_op_t(ast_type_t asttype_, xpath_value_type rettype_, int precedence_)
static binary_op_t parse(xpath_lexer &lexer)
xpath_ast_node * error(const char *message)
xpath_ast_node * parse_step(xpath_ast_node *set)
xpath_ast_node * error_oom()
xpath_variable_set * _variables
xpath_parser(const char_t *query, xpath_variable_set *variables, xpath_allocator *alloc, xpath_parse_result *result)
xpath_ast_node * alloc_node(ast_type_t type, xpath_ast_node *left, axis_t axis, nodetest_t test, const char_t *contents)
xpath_ast_node * parse_primary_expression()
xpath_ast_node * alloc_node(ast_type_t type, xpath_ast_node *left, xpath_ast_node *right, predicate_t test)
xpath_ast_node * alloc_node(ast_type_t type, xpath_value_type rettype, xpath_ast_node *left=0, xpath_ast_node *right=0)
xpath_ast_node * parse_filter_expression()
xpath_ast_node * parse_expression(int limit=0)
nodetest_t parse_node_test_type(const xpath_lexer_string &name)
const char_t * alloc_string(const xpath_lexer_string &value)
xpath_parse_result * _result
xpath_ast_node * parse_function(const xpath_lexer_string &name, size_t argc, xpath_ast_node *args[2])
xpath_ast_node * alloc_node(ast_type_t type, xpath_value_type rettype, xpath_variable *value)
xpath_ast_node * alloc_node(ast_type_t type, xpath_value_type rettype, double value)
static xpath_ast_node * parse(const char_t *query, xpath_variable_set *variables, xpath_allocator *alloc, xpath_parse_result *result)
xpath_ast_node * parse_path_or_unary_expression()
axis_t parse_axis_name(const xpath_lexer_string &name, bool &specified)
xpath_ast_node * parse_expression_rec(xpath_ast_node *lhs, int limit)
xpath_ast_node * parse_relative_location_path(xpath_ast_node *set)
xpath_ast_node * alloc_node(ast_type_t type, xpath_value_type rettype, const char_t *value)
xpath_ast_node * parse_location_path()
static void destroy(xpath_query_impl *impl)
static xpath_query_impl * create()
xpath_memory_block blocks[2]
xpath_variable_node_set()