14 #ifndef SOURCE_PUGIXML_CPP
15 #define SOURCE_PUGIXML_CPP
25 #ifdef PUGIXML_WCHAR_MODE
29 #ifndef PUGIXML_NO_XPATH
34 #ifndef PUGIXML_NO_STL
44 # pragma warning(push)
45 # pragma warning(disable: 4127) // conditional expression is constant
46 # pragma warning(disable: 4324) // structure was padded due to __declspec(align())
47 # pragma warning(disable: 4702) // unreachable code
48 # pragma warning(disable: 4996) // this function or variable may be unsafe
51 #if defined(_MSC_VER) && defined(__c2__)
52 # pragma clang diagnostic push
53 # pragma clang diagnostic ignored "-Wdeprecated" // this function or variable may be unsafe
56 #ifdef __INTEL_COMPILER
57 # pragma warning(disable: 177) // function was declared but never referenced
58 # pragma warning(disable: 279) // controlling expression is constant
59 # pragma warning(disable: 1478 1786) // function was declared "deprecated"
60 # pragma warning(disable: 1684) // conversion from pointer to same-sized integral type
63 #if defined(__BORLANDC__) && defined(PUGIXML_HEADER_ONLY)
64 # pragma warn -8080 // symbol is declared but never used; disabling this inside push/pop bracket does not make the warning go away
69 # pragma warn -8008 // condition is always false
70 # pragma warn -8066 // unreachable code
75 # pragma diag_suppress=178 // function was declared but never referenced
76 # pragma diag_suppress=237 // controlling expression is constant
79 #ifdef __TI_COMPILER_VERSION__
80 # pragma diag_suppress 179 // function was declared but never referenced
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 // MSVC6 seems to have an amusing bug with anonymous namespaces inside namespaces
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) // unused
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)
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);
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)
1694 uint16_t lead = opt_swap::value ?
endian_swap(*data) : *data;
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)
1713 uint16_t next = opt_swap::value ?
endian_swap(data[1]) : data[1];
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)
1746 uint32_t lead = opt_swap::value ?
endian_swap(*data) : *data;
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++; }
1924 if (size < 6 || !((data[0] ==
'<') & (data[1] ==
'?') & (data[2] ==
'x') & (data[3] ==
'm') & (data[4] ==
'l') &&
PUGI__IS_CHARTYPE(data[5],
ct_space)))
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
1977 uint8_t d0 = data[0], d1 = data[1], d2 = data[2], d3 = data[3];
1984 if (d0 == 0xef && d1 == 0xbb && d2 == 0xbf)
return encoding_utf8;
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')
2011 && (enc[0] |
' ') ==
'l' && (enc[1] |
' ') ==
'a' && (enc[2] |
' ') ==
't'
2012 && (enc[3] |
' ') ==
'i' && (enc[4] |
' ') ==
'n'
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);
2061 out_buffer = buffer;
2062 out_length = length + 1;
2068 #ifdef PUGIXML_WCHAR_MODE
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)
2077 const char_t* data =
static_cast<const char_t*
>(contents);
2078 size_t length = size /
sizeof(
char_t);
2084 convert_wchar_endian_swap(buffer, data, length);
2086 out_buffer = buffer;
2087 out_length = length;
2092 if (!buffer)
return false;
2094 convert_wchar_endian_swap(buffer, data, length);
2097 out_buffer = buffer;
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);
2110 size_t length = D::process(data, data_length, 0,
wchar_counter());
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);
2123 out_buffer = buffer;
2124 out_length = length + 1;
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);
2151 return (native_encoding == encoding) ?
2161 return (native_encoding == encoding) ?
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);
2180 size_t length = D::process(data, data_length, 0,
utf8_counter());
2184 if (!buffer)
return false;
2187 uint8_t* obegin =
reinterpret_cast<uint8_t*
>(buffer);
2188 uint8_t* oend = D::process(data, data_length, obegin,
utf8_writer());
2190 assert(oend == obegin + length);
2193 out_buffer = buffer;
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;
2231 memcpy(buffer, data, prefix_length);
2233 uint8_t* obegin =
reinterpret_cast<uint8_t*
>(buffer);
2236 assert(oend == obegin + length);
2239 out_buffer = buffer;
2240 out_length = length + 1;
2256 return (native_encoding == encoding) ?
2266 return (native_encoding == encoding) ?
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);
2308 if (size > 0)
as_utf8_end(&result[0], size, str, length);
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>
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;
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));
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);
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));
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],
'>'))
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 ==
'&')
2695 if (opt_trim::value)
2712 switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4))
2722 default: assert(
false);
return 0;
2749 if (*s == end_quote)
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 ==
'&')
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'))
3129 assert((*s == 0 && endch ==
'>') || *s ==
'>');
3138 cursor->value = mark;
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;
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 ==
'>')
3424 if (*s ==
'<' || !*s)
3435 if (s[0] !=
'<' || s[1] !=
'/' || cursor->first_child)
continue;
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];
3519 buffer[length - 1] = 0;
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
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;
3619 convert_wchar_endian_swap(r_char, data, length);
3621 return length *
sizeof(
char_t);
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;
3687 assert(
false &&
"Invalid encoding");
3712 if (size == 0)
return;
3721 assert(result <=
sizeof(
scratch));
3752 flush(data, chunk_size);
3756 length -= chunk_size;
3773 memcpy(
buffer + offset, data, length *
sizeof(
char_t));
3788 buffer[offset++] = *data++;
3798 size_t length = offset -
bufsize;
3882 #ifdef PUGIXML_MEMORY_OUTPUT_STACK
3883 PUGIXML_MEMORY_OUTPUT_STACK
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',
';');
3936 writer.
write(
'&',
'q',
'u',
'o',
't',
';');
3941 writer.
write(
'&',
'a',
'p',
'o',
's',
';');
3948 unsigned int ch =
static_cast<unsigned int>(*s++);
3952 writer.
write(
'&',
'#',
static_cast<char_t>((ch / 10) +
'0'),
static_cast<char_t>((ch % 10) +
'0'),
';');
3970 writer.
write(
'<',
'!',
'[',
'C',
'D');
3971 writer.
write(
'A',
'T',
'A',
'[');
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(
'<',
'!',
'-',
'-');
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(
'-',
'-',
'>');
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(
'?',
' ',
'>');
4079 for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute)
4092 writer.
write_string(a->name ? a->name + 0 : default_name);
4093 writer.
write(
'=', enquotation_char);
4098 writer.
write(enquotation_char);
4105 const char_t*
name = node->name ? node->name + 0 : default_name;
4110 if (node->first_attribute)
4116 if (!node->first_child)
4120 writer.
write(
'>',
'<',
'/');
4131 writer.
write(
'/',
'>');
4149 if (!node->first_child)
4151 writer.
write(
'<',
'/');
4167 const char_t*
name = node->name ? node->name + 0 : default_name;
4169 writer.
write(
'<',
'/');
4193 writer.
write(
'<',
'?');
4194 writer.
write_string(node->name ? node->name + 0 : default_name);
4202 writer.
write(
'?',
'>');
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");
4241 xml_node_struct* node = root;
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;
4323 while (node != root);
4331 for (xml_node_struct* child = node->first_child; child; child = child->next_sibling)
4344 for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute)
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;
4497 bool negative = (*s ==
'-');
4499 s += (*s ==
'+' || *s ==
'-');
4501 bool overflow =
false;
4503 if (s[0] ==
'0' && (s[1] |
' ') ==
'x')
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;
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));
4605 return (first ==
'1' || first ==
't' || first ==
'T' || first ==
'y' || first ==
'Y');
4608 #ifdef PUGIXML_HAS_LONG_LONG
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>
4707 if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents);
4710 if (own || buffer != contents) *out_buffer = buffer;
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);
4754 size_t result =
static_cast<size_t>(length);
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);
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())
4872 if (last) last = last->
next = chunk;
4873 else chunks.
data = last = chunk;
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;
4887 size_t max_suffix_size =
sizeof(
char_t);
4893 char*
write = buffer;
4897 assert(
write + chunk->size <= buffer +
total);
4898 memcpy(
write, chunk->data, chunk->size);
4899 write += chunk->size;
4905 *out_buffer = buffer;
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;
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);
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);
4941 *out_buffer = buffer.
release();
4942 *out_size = actual_length *
sizeof(T);
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;
5308 if (!
_attr)
return false;
5315 if (!
_attr)
return false;
5322 if (!
_attr)
return false;
5329 if (!
_attr)
return false;
5336 if (!
_attr)
return false;
5343 if (!
_attr)
return false;
5350 if (!
_attr)
return false;
5357 if (!
_attr)
return false;
5362 #ifdef PUGIXML_HAS_LONG_LONG
5365 if (!
_attr)
return false;
5372 if (!
_attr)
return 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;
5568 hint_.
_attr =
j->next_attribute;
5804 if (!alloc.reserve())
return xml_node();
5821 if (!alloc.reserve())
return xml_node();
5839 if (!alloc.reserve())
return xml_node();
5857 if (!alloc.reserve())
return xml_node();
5911 if (!alloc.reserve())
return xml_node();
5928 if (!alloc.reserve())
return xml_node();
5946 if (!alloc.reserve())
return xml_node();
5964 if (!alloc.reserve())
return xml_node();
5980 if (!alloc.reserve())
return xml_node();
5996 if (!alloc.reserve())
return xml_node();
6014 if (!alloc.reserve())
return xml_node();
6032 if (!alloc.reserve())
return xml_node();
6054 if (!alloc.reserve())
return false;
6072 if (!alloc.reserve())
return false;
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);
6142 #ifndef PUGIXML_NO_STL
6151 offset += (i !=
_root);
6156 result.resize(offset);
6161 result[--offset] = delimiter;
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);
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;
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;
6399 return _data() == 0;
6406 return (d && d->value) ? d->value + 0 :
PUGIXML_TEXT(
"");
6413 return (d && d->value) ? d->value + 0 : 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;
6523 #ifdef PUGIXML_HAS_LONG_LONG
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);
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;
7020 doc->_hash = &doc->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
7101 #ifdef PUGIXML_WCHAR_MODE
7119 using impl::auto_deleter;
7129 using impl::auto_deleter;
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');
7181 buffered_writer.flush();
7184 #ifndef PUGIXML_NO_STL
7189 save(writer, indent, flags, encoding);
7202 using impl::auto_deleter;
7210 using impl::auto_deleter;
7227 #ifndef PUGIXML_NO_STL
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))
7421 swap(middle, first);
7422 if (pred(*last, *middle))
7424 if (pred(*middle, *first))
7425 swap(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)
7733 if (!result)
return 0;
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;
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;
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)
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();
8040 xml_attribute_struct* attr = xnode.attribute().internal_object();
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);
8194 *out_mantissa = buffer;
8195 *out_exponent = exponent;
8204 char* exponent_string = strchr(buffer,
'e');
8205 assert(exponent_string);
8207 int exponent = atoi(exponent_string + 1);
8210 char* mantissa = buffer[0] ==
'-' ? buffer + 1 : buffer;
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;
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;
8342 if (length >=
sizeof(buffer) /
sizeof(buffer[0]))
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; )
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];
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));
8657 return new_xpath_variable<xpath_variable_node_set>(
name);
8660 return new_xpath_variable<xpath_variable_number>(
name);
8663 return new_xpath_variable<xpath_variable_string>(
name);
8666 return new_xpath_variable<xpath_variable_boolean>(
name);
8700 assert(
false &&
"Invalid variable type");
8706 switch (rhs->type())
8721 assert(
false &&
"Invalid variable type");
8728 size_t length =
static_cast<size_t>(end - begin);
8729 char_t* scratch = buffer;
8731 if (length >=
sizeof(buffer) /
sizeof(buffer[0]))
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;
8769 PUGI__FN xpath_node_set::type_t
xpath_sort(xpath_node* begin, xpath_node* end, xpath_node_set::type_t type,
bool rev)
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;
8787 if (type != order)
reverse(begin, end);
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)));
8877 _end = data + size_;
8878 _eos = data + size_ + count;
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**));
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)));
8959 _end = data + capacity;
8960 _eos = data + new_capacity;
9020 size_t length =
static_cast<size_t>(
end -
begin);
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) ==
':')
9501 return comp(ls, rs);
9511 for (
const xpath_node* li = ls.
begin(); li != ls.
end(); ++li)
9512 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9539 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9556 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9568 assert(
false &&
"Wrong types");
9590 for (
const xpath_node* li = ls.
begin(); li != ls.
end(); ++li)
9596 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9614 for (
const xpath_node* ri = rs.
begin(); ri != rs.
end(); ++ri)
9631 for (
const xpath_node* li = ls.
begin(); li != ls.
end(); ++li)
9643 assert(
false &&
"Wrong types");
9650 assert(ns.
size() >= first);
9654 size_t size = ns.
size() - first;
9656 xpath_node* last = ns.
begin() + first;
9659 for (xpath_node* it = last; it != ns.
end(); ++it, ++i)
9676 assert(ns.
size() >= first);
9680 size_t size = ns.
size() - first;
9682 xpath_node* last = ns.
begin() + first;
9685 for (xpath_node* it = last; it != ns.
end(); ++it, ++i)
9702 assert(ns.
size() >= first);
9705 size_t size = ns.
size() - first;
9707 xpath_node* last = ns.
begin() + first;
9713 if (er >= 1.0 && er <= size)
9715 size_t eri =
static_cast<size_t>(er);
9719 xpath_node r = last[eri - 1];
9730 if (ns.
size() == first)
return;
9744 if (ns.
size() == first)
return;
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);
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 ==
'-';
10353 return _data.variable->get_boolean();
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;
10488 return _data.variable->get_number();
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();
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();
10670 size_t s_length = s.
length();
10675 else if (first >= s_length + 1)
return xpath_string();
10677 size_t pos = first < 1 ? 1 : static_cast<size_t>(first);
10678 assert(1 <= pos && pos <= s_length + 1);
10693 size_t s_length = s.
length();
10699 else if (first >= s_length + 1)
return xpath_string();
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);
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);
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;
11099 return memory ?
new (memory)
xpath_ast_node(type, rettype, value) : 0;
11105 return memory ?
new (memory)
xpath_ast_node(type, rettype, value) : 0;
11111 return memory ?
new (memory)
xpath_ast_node(type, rettype, value) : 0;
11117 return memory ?
new (memory)
xpath_ast_node(type, rettype, left, right) : 0;
11123 return memory ?
new (memory)
xpath_ast_node(type, left, axis, test, contents) : 0;
11129 return memory ?
new (memory)
xpath_ast_node(type, left, right, test) : 0;
11137 size_t length =
static_cast<size_t>(value.
end - value.
begin);
11150 switch (
name.begin[0])
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");
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");
11488 return error(
"Predicate has to be applied to node set");
11491 if (!expr)
return 0;
11497 return error(
"Expected ']' to match an opening '['");
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 '['");
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;
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
12080 #ifdef __BORLANDC__
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;
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);
12317 char_t* copy =
static_cast<char_t*
>(impl::xml_memory::allocate(size));
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]);
12433 if (!nvar)
return false;
12437 last->
_next = nvar;
12439 *out_result = nvar;
12466 const size_t hash_size =
sizeof(
_data) /
sizeof(
_data[0]);
12472 return var->type() == type ? var : 0;
12481 _data[hash] = result;
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();
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
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));
12690 buffer[size - 1] = 0;
12701 impl::xpath_context
c(n, 1, 1);
12702 impl::xpath_stack_data sd;
12708 #ifdef PUGIXML_NO_EXCEPTIONS
12711 throw std::bad_alloc();
12723 impl::xpath_context
c(n, 1, 1);
12724 impl::xpath_stack_data sd;
12730 #ifdef PUGIXML_NO_EXCEPTIONS
12733 throw std::bad_alloc();
12795 #ifdef __BORLANDC__
12796 # pragma option pop
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
12818 #undef PUGI__NS_END
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
12829 #undef PUGI__SKIPWS
12830 #undef PUGI__OPTSET
12831 #undef PUGI__PUSHNODE
12832 #undef PUGI__POPNODE
12833 #undef PUGI__SCANFOR
12834 #undef PUGI__SCANWHILE
12835 #undef PUGI__SCANWHILE_UNROLL
12836 #undef PUGI__ENDSEG
12837 #undef PUGI__THROW_ERROR
12838 #undef PUGI__CHECK_ERROR