Newer
Older
arseny.kapoulkine
committed
#endif
arseny.kapoulkine
committed
// check for I/O errors
if (length < 0) return status_io_error;
arseny.kapoulkine
committed
// check for overflow
size_t result = static_cast<size_t>(length);
if (static_cast<length_type>(result) != length) return status_out_of_memory;
// finalize
out_result = result;
return status_ok;
}
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
PUGI__FN size_t zero_terminate_buffer(void* buffer, size_t size, xml_encoding encoding)
{
// We only need to zero-terminate if encoding conversion does not do it for us
#ifdef PUGIXML_WCHAR_MODE
xml_encoding wchar_encoding = get_wchar_encoding();
if (encoding == wchar_encoding || need_endian_swap_utf(encoding, wchar_encoding))
{
size_t length = size / sizeof(char_t);
static_cast<char_t*>(buffer)[length] = 0;
return (length + 1) * sizeof(char_t);
}
#else
if (encoding == encoding_utf8)
{
static_cast<char*>(buffer)[size] = 0;
return size + 1;
}
#endif
return size;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_parse_result load_file_impl(xml_document& doc, FILE* file, unsigned int options, xml_encoding encoding)
{
if (!file) return make_parse_result(status_file_not_found);
// get file size (can result in I/O errors)
size_t size = 0;
xml_parse_status size_status = get_file_size(file, size);
if (size_status != status_ok)
arseny.kapoulkine
committed
{
fclose(file);
return make_parse_result(size_status);
arseny.kapoulkine
committed
}
size_t max_suffix_size = sizeof(char_t);
arseny.kapoulkine
committed
// allocate buffer for the whole file
char* contents = static_cast<char*>(xml_memory::allocate(size + max_suffix_size));
arseny.kapoulkine
committed
if (!contents)
{
fclose(file);
return make_parse_result(status_out_of_memory);
}
arseny.kapoulkine
committed
// read file in memory
size_t read_size = fread(contents, 1, size, file);
fclose(file);
arseny.kapoulkine
committed
if (read_size != size)
arseny.kapoulkine@gmail.com
committed
xml_memory::deallocate(contents);
return make_parse_result(status_io_error);
}
xml_encoding real_encoding = get_buffer_encoding(encoding, contents, size);
return doc.load_buffer_inplace_own(contents, zero_terminate_buffer(contents, size, real_encoding), options, real_encoding);
}
#ifndef PUGIXML_NO_STL
template <typename T> struct xml_stream_chunk
{
static xml_stream_chunk* create()
{
void* memory = xml_memory::allocate(sizeof(xml_stream_chunk));
return new (memory) xml_stream_chunk();
}
static void destroy(void* ptr)
{
xml_stream_chunk* chunk = static_cast<xml_stream_chunk*>(ptr);
// free chunk chain
while (chunk)
{
xml_memory::deallocate(chunk);
}
}
xml_stream_chunk(): next(0), size(0)
{
}
xml_stream_chunk* next;
size_t size;
T data[xml_memory_page_size / sizeof(T)];
};
arseny.kapoulkine@gmail.com
committed
template <typename T> PUGI__FN xml_parse_status load_stream_data_noseek(std::basic_istream<T>& stream, void** out_buffer, size_t* out_size)
{
buffer_holder chunks(0, xml_stream_chunk<T>::destroy);
// read file to a chunk list
size_t total = 0;
xml_stream_chunk<T>* last = 0;
while (!stream.eof())
{
// allocate new chunk
xml_stream_chunk<T>* chunk = xml_stream_chunk<T>::create();
if (!chunk) return status_out_of_memory;
// append chunk to list
if (last) last = last->next = chunk;
else chunks.data = last = chunk;
// read data to chunk
stream.read(chunk->data, static_cast<std::streamsize>(sizeof(chunk->data) / sizeof(T)));
chunk->size = static_cast<size_t>(stream.gcount()) * sizeof(T);
// read may set failbit | eofbit in case gcount() is less than read length, so check for other I/O errors
if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error;
// guard against huge files (chunk size is small enough to make this overflow check work)
if (total + chunk->size < total) return status_out_of_memory;
total += chunk->size;
}
size_t max_suffix_size = sizeof(char_t);
// copy chunk list to a contiguous buffer
char* buffer = static_cast<char*>(xml_memory::allocate(total + max_suffix_size));
if (!buffer) return status_out_of_memory;
char* write = buffer;
for (xml_stream_chunk<T>* chunk = static_cast<xml_stream_chunk<T>*>(chunks.data); chunk; chunk = chunk->next)
{
assert(write + chunk->size <= buffer + total);
memcpy(write, chunk->data, chunk->size);
write += chunk->size;
}
assert(write == buffer + total);
// return buffer
*out_buffer = buffer;
*out_size = total;
return status_ok;
}
arseny.kapoulkine@gmail.com
committed
template <typename T> PUGI__FN xml_parse_status load_stream_data_seek(std::basic_istream<T>& stream, void** out_buffer, size_t* out_size)
arseny.kapoulkine
committed
{
// get length of remaining data in stream
arseny.kapoulkine
committed
typename std::basic_istream<T>::pos_type pos = stream.tellg();
stream.seekg(0, std::ios::end);
std::streamoff length = stream.tellg() - pos;
arseny.kapoulkine
committed
stream.seekg(pos);
if (stream.fail() || pos < 0) return status_io_error;
arseny.kapoulkine
committed
// guard against huge files
size_t read_length = static_cast<size_t>(length);
if (static_cast<std::streamsize>(read_length) != length || length < 0) return status_out_of_memory;
size_t max_suffix_size = sizeof(char_t);
arseny.kapoulkine
committed
// read stream data into memory (guard against stream exceptions with buffer holder)
buffer_holder buffer(xml_memory::allocate(read_length * sizeof(T) + max_suffix_size), xml_memory::deallocate);
if (!buffer.data) return status_out_of_memory;
arseny.kapoulkine
committed
stream.read(static_cast<T*>(buffer.data), static_cast<std::streamsize>(read_length));
arseny.kapoulkine
committed
// read may set failbit | eofbit in case gcount() is less than read_length (i.e. line ending conversion), so check for other I/O errors
if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error;
arseny.kapoulkine
committed
size_t actual_length = static_cast<size_t>(stream.gcount());
assert(actual_length <= read_length);
*out_buffer = buffer.release();
*out_size = actual_length * sizeof(T);
return status_ok;
arseny.kapoulkine@gmail.com
committed
template <typename T> PUGI__FN xml_parse_result load_stream_impl(xml_document& doc, std::basic_istream<T>& stream, unsigned int options, xml_encoding encoding)
void* buffer = 0;
size_t size = 0;
Arseny Kapoulkine
committed
xml_parse_status status = status_ok;
// if stream has an error bit set, bail out (otherwise tellg() can fail and we'll clear error bits)
if (stream.fail()) return make_parse_result(status_io_error);
// load stream to memory (using seek-based implementation if possible, since it's faster and takes less memory)
Arseny Kapoulkine
committed
if (stream.tellg() < 0)
{
stream.clear(); // clear error flags that could be set by a failing tellg
status = load_stream_data_noseek(stream, &buffer, &size);
}
else
status = load_stream_data_seek(stream, &buffer, &size);
if (status != status_ok) return make_parse_result(status);
xml_encoding real_encoding = get_buffer_encoding(encoding, buffer, size);
return doc.load_buffer_inplace_own(buffer, zero_terminate_buffer(buffer, size, real_encoding), options, real_encoding);
arseny.kapoulkine@gmail.com
committed
#if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && !defined(__STRICT_ANSI__))
arseny.kapoulkine@gmail.com
committed
PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode)
{
return _wfopen(path, mode);
}
#else
arseny.kapoulkine@gmail.com
committed
PUGI__FN char* convert_path_heap(const wchar_t* str)
{
assert(str);
// first pass: get length in utf8 characters
arseny.kapoulkine@gmail.com
committed
size_t length = strlength_wide(str);
size_t size = as_utf8_begin(str, length);
// allocate resulting string
arseny.kapoulkine@gmail.com
committed
char* result = static_cast<char*>(xml_memory::allocate(size + 1));
if (!result) return 0;
// second pass: convert to utf8
as_utf8_end(result, size, str, length);
return result;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode)
{
// there is no standard function to open wide paths, so our best bet is to try utf8 path
char* path_utf8 = convert_path_heap(path);
if (!path_utf8) return 0;
// convert mode to ASCII (we mirror _wfopen interface)
char mode_ascii[4] = {0};
for (size_t i = 0; mode[i]; ++i) mode_ascii[i] = static_cast<char>(mode[i]);
// try to open the utf8 path
FILE* result = fopen(path_utf8, mode_ascii);
// free dummy buffer
arseny.kapoulkine@gmail.com
committed
xml_memory::deallocate(path_utf8);
return result;
}
#endif
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool save_file_impl(const xml_document& doc, FILE* file, const char_t* indent, unsigned int flags, xml_encoding encoding)
{
if (!file) return false;
xml_writer_file writer(file);
doc.save(writer, indent, flags, encoding);
int result = ferror(file);
arseny.kapoulkine@gmail.com
committed
arseny.kapoulkine@gmail.com
committed
fclose(file);
arseny.kapoulkine@gmail.com
committed
return result == 0;
arseny.kapoulkine@gmail.com
committed
}
arseny.kapoulkine@gmail.com
committed
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)
{
// check input buffer
assert(contents || size == 0);
// get actual encoding
xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size);
// get private buffer
char_t* buffer = 0;
size_t length = 0;
if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory);
// delete original buffer if we performed a conversion
if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents);
// store buffer for offset_debug
doc->buffer = buffer;
arseny.kapoulkine@gmail.com
committed
// parse
xml_parse_result res = impl::xml_parser::parse(buffer, length, doc, root, options);
// remember encoding
res.encoding = buffer_encoding;
// grab onto buffer if it's our buffer, user is responsible for deallocating contents himself
if (own || buffer != contents) *out_buffer = buffer;
return res;
}
arseny.kapoulkine@gmail.com
committed
PUGI__NS_END
namespace pugi
{
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_writer_file::xml_writer_file(void* file_): file(file_)
arseny.kapoulkine@gmail.com
committed
PUGI__FN void xml_writer_file::write(const void* data, size_t size)
arseny.kapoulkine@gmail.com
committed
size_t result = fwrite(data, 1, size, static_cast<FILE*>(file));
(void)!result; // unfortunately we can't do proper error handling here
}
#ifndef PUGIXML_NO_STL
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream<char, std::char_traits<char> >& stream): narrow_stream(&stream), wide_stream(0)
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& stream): narrow_stream(0), wide_stream(&stream)
arseny.kapoulkine@gmail.com
committed
PUGI__FN void xml_writer_stream::write(const void* data, size_t size)
{
if (narrow_stream)
{
assert(!wide_stream);
narrow_stream->write(reinterpret_cast<const char*>(data), static_cast<std::streamsize>(size));
}
else
{
assert(wide_stream);
assert(size % sizeof(wchar_t) == 0);
wide_stream->write(reinterpret_cast<const wchar_t*>(data), static_cast<std::streamsize>(size / sizeof(wchar_t)));
}
}
#endif
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_tree_walker::xml_tree_walker(): _depth(0)
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_tree_walker::~xml_tree_walker()
arseny.kapoulkine@gmail.com
committed
PUGI__FN int xml_tree_walker::depth() const
{
return _depth;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_tree_walker::begin(xml_node&)
{
return true;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_tree_walker::end(xml_node&)
{
return true;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute::xml_attribute(): _attr(0)
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute::xml_attribute(xml_attribute_struct* attr): _attr(attr)
PUGI__FN static void unspecified_bool_xml_attribute(xml_attribute***)
{
}
arseny.kapoulkine
committed
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute::operator xml_attribute::unspecified_bool_type() const
return _attr ? unspecified_bool_xml_attribute : 0;
}
PUGI__FN bool xml_attribute::operator!() const
{
return !_attr;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_attribute::operator==(const xml_attribute& r) const
{
return (_attr == r._attr);
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_attribute::operator!=(const xml_attribute& r) const
{
return (_attr != r._attr);
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_attribute::operator<(const xml_attribute& r) const
{
return (_attr < r._attr);
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_attribute::operator>(const xml_attribute& r) const
{
return (_attr > r._attr);
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_attribute::operator<=(const xml_attribute& r) const
{
return (_attr <= r._attr);
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_attribute::operator>=(const xml_attribute& r) const
{
return (_attr >= r._attr);
}
PUGI__FN xml_attribute xml_attribute::next_attribute() const
{
return _attr ? xml_attribute(_attr->next_attribute) : xml_attribute();
}
PUGI__FN xml_attribute xml_attribute::previous_attribute() const
{
return _attr && _attr->prev_attribute_c->next_attribute ? xml_attribute(_attr->prev_attribute_c) : xml_attribute();
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN const char_t* xml_attribute::as_string(const char_t* def) const
arseny.kapoulkine@gmail.com
committed
return (_attr && _attr->value) ? _attr->value : def;
arseny.kapoulkine@gmail.com
committed
PUGI__FN int xml_attribute::as_int(int def) const
return impl::get_value_int(_attr ? _attr->value : 0, def);
arseny.kapoulkine@gmail.com
committed
PUGI__FN unsigned int xml_attribute::as_uint(unsigned int def) const
return impl::get_value_uint(_attr ? _attr->value : 0, def);
arseny.kapoulkine@gmail.com
committed
PUGI__FN double xml_attribute::as_double(double def) const
return impl::get_value_double(_attr ? _attr->value : 0, def);
arseny.kapoulkine@gmail.com
committed
PUGI__FN float xml_attribute::as_float(float def) const
return impl::get_value_float(_attr ? _attr->value : 0, def);
arseny.kapoulkine@gmail.com
committed
}
PUGI__FN bool xml_attribute::as_bool(bool def) const
{
return impl::get_value_bool(_attr ? _attr->value : 0, def);
Arseny Kapoulkine
committed
#ifdef PUGIXML_HAS_LONG_LONG
PUGI__FN long long xml_attribute::as_llong(long long def) const
{
return impl::get_value_llong(_attr ? _attr->value : 0, def);
}
PUGI__FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const
{
return impl::get_value_ullong(_attr ? _attr->value : 0, def);
}
#endif
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_attribute::empty() const
{
return !_attr;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN const char_t* xml_attribute::name() const
{
return (_attr && _attr->name) ? _attr->name : PUGIXML_TEXT("");
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN const char_t* xml_attribute::value() const
{
return (_attr && _attr->value) ? _attr->value : PUGIXML_TEXT("");
}
PUGI__FN size_t xml_attribute::hash_value() const
{
return static_cast<size_t>(reinterpret_cast<uintptr_t>(_attr) / sizeof(xml_attribute_struct));
}
arseny.kapoulkine
committed
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute_struct* xml_attribute::internal_object() const
return _attr;
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute& xml_attribute::operator=(const char_t* rhs)
{
set_value(rhs);
return *this;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute& xml_attribute::operator=(int rhs)
{
set_value(rhs);
return *this;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute& xml_attribute::operator=(unsigned int rhs)
{
set_value(rhs);
return *this;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute& xml_attribute::operator=(double rhs)
{
set_value(rhs);
return *this;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute& xml_attribute::operator=(bool rhs)
{
set_value(rhs);
return *this;
}
Arseny Kapoulkine
committed
#ifdef PUGIXML_HAS_LONG_LONG
PUGI__FN xml_attribute& xml_attribute::operator=(long long rhs)
{
set_value(rhs);
return *this;
}
PUGI__FN xml_attribute& xml_attribute::operator=(unsigned long long rhs)
{
set_value(rhs);
return *this;
}
#endif
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_attribute::set_name(const char_t* rhs)
{
if (!_attr) return false;
arseny.kapoulkine@gmail.com
committed
return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs);
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_attribute::set_value(const char_t* rhs)
{
if (!_attr) return false;
arseny.kapoulkine@gmail.com
committed
return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs);
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_attribute::set_value(int rhs)
arseny.kapoulkine@gmail.com
committed
if (!_attr) return false;
return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs);
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_attribute::set_value(unsigned int rhs)
arseny.kapoulkine@gmail.com
committed
if (!_attr) return false;
return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs);
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_attribute::set_value(double rhs)
arseny.kapoulkine@gmail.com
committed
if (!_attr) return false;
return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs);
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_attribute::set_value(bool rhs)
arseny.kapoulkine@gmail.com
committed
if (!_attr) return false;
return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs);
Arseny Kapoulkine
committed
#ifdef PUGIXML_HAS_LONG_LONG
PUGI__FN bool xml_attribute::set_value(long long rhs)
{
if (!_attr) return false;
return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs);
}
PUGI__FN bool xml_attribute::set_value(unsigned long long rhs)
{
if (!_attr) return false;
return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs);
}
#endif
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool operator&&(const xml_attribute& lhs, bool rhs)
{
return (bool)lhs && rhs;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool operator||(const xml_attribute& lhs, bool rhs)
{
return (bool)lhs || rhs;
}
#endif
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node::xml_node(): _root(0)
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node::xml_node(xml_node_struct* p): _root(p)
PUGI__FN static void unspecified_bool_xml_node(xml_node***)
{
}
arseny.kapoulkine
committed
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node::operator xml_node::unspecified_bool_type() const
return _root ? unspecified_bool_xml_node : 0;
}
PUGI__FN bool xml_node::operator!() const
{
return !_root;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node::iterator xml_node::begin() const
{
return iterator(_root ? _root->first_child : 0, _root);
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node::iterator xml_node::end() const
{
return iterator(0, _root);
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node::attribute_iterator xml_node::attributes_begin() const
{
return attribute_iterator(_root ? _root->first_attribute : 0, _root);
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node::attribute_iterator xml_node::attributes_end() const
{
return attribute_iterator(0, _root);
}
PUGI__FN xml_object_range<xml_node_iterator> xml_node::children() const
{
return xml_object_range<xml_node_iterator>(begin(), end());
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_object_range<xml_named_node_iterator> xml_node::children(const char_t* name_) const
{
return xml_object_range<xml_named_node_iterator>(xml_named_node_iterator(child(name_)._root, _root, name_), xml_named_node_iterator(0, _root, name_));
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_object_range<xml_attribute_iterator> xml_node::attributes() const
{
return xml_object_range<xml_attribute_iterator>(attributes_begin(), attributes_end());
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_node::operator==(const xml_node& r) const
{
return (_root == r._root);
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_node::operator!=(const xml_node& r) const
{
return (_root != r._root);
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_node::operator<(const xml_node& r) const
{
return (_root < r._root);
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_node::operator>(const xml_node& r) const
{
return (_root > r._root);
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_node::operator<=(const xml_node& r) const
{
return (_root <= r._root);
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_node::operator>=(const xml_node& r) const
{
return (_root >= r._root);
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_node::empty() const
{
return !_root;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN const char_t* xml_node::name() const
{
return (_root && _root->name) ? _root->name : PUGIXML_TEXT("");
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node_type xml_node::type() const
return _root ? PUGI__NODETYPE(_root) : node_null;
arseny.kapoulkine@gmail.com
committed
PUGI__FN const char_t* xml_node::value() const
{
return (_root && _root->value) ? _root->value : PUGIXML_TEXT("");
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node xml_node::child(const char_t* name_) const
{
if (!_root) return xml_node();
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
arseny.kapoulkine@gmail.com
committed
if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
return xml_node();
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute xml_node::attribute(const char_t* name_) const
{
if (!_root) return xml_attribute();
for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute)
arseny.kapoulkine@gmail.com
committed
if (i->name && impl::strequal(name_, i->name))
return xml_attribute(i);
return xml_attribute();
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node xml_node::next_sibling(const char_t* name_) const
{
if (!_root) return xml_node();
for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling)
arseny.kapoulkine@gmail.com
committed
if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
return xml_node();
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node xml_node::next_sibling() const
return _root ? xml_node(_root->next_sibling) : xml_node();
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node xml_node::previous_sibling(const char_t* name_) const
{
if (!_root) return xml_node();
for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c)
arseny.kapoulkine@gmail.com
committed
if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
return xml_node();
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node xml_node::previous_sibling() const
{
if (!_root) return xml_node();
if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c);
else return xml_node();
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node xml_node::parent() const
{
return _root ? xml_node(_root->parent) : xml_node();
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node xml_node::root() const
return _root ? xml_node(&impl::get_document(_root)) : xml_node();
PUGI__FN xml_text xml_node::text() const
{
return xml_text(_root);
}
arseny.kapoulkine@gmail.com
committed
arseny.kapoulkine@gmail.com
committed
PUGI__FN const char_t* xml_node::child_value() const
{
if (!_root) return PUGIXML_TEXT("");
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
if (i->value && impl::is_text_node(i))
return i->value;
return PUGIXML_TEXT("");
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN const char_t* xml_node::child_value(const char_t* name_) const
return child(name_).child_value();
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute xml_node::first_attribute() const
{
return _root ? xml_attribute(_root->first_attribute) : xml_attribute();
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute xml_node::last_attribute() const
{
return _root && _root->first_attribute ? xml_attribute(_root->first_attribute->prev_attribute_c) : xml_attribute();
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node xml_node::first_child() const
{
return _root ? xml_node(_root->first_child) : xml_node();
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node xml_node::last_child() const
{
return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node();
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_node::set_name(const char_t* rhs)
{
switch (type())
{
case node_pi:
case node_declaration:
case node_element:
arseny.kapoulkine@gmail.com
committed
return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs);
default:
return false;
}
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN bool xml_node::set_value(const char_t* rhs)
{
switch (type())
{
case node_pi:
case node_cdata:
case node_pcdata:
case node_comment:
case node_doctype:
arseny.kapoulkine@gmail.com
committed
return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs);
default:
return false;
}
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_)
{
if (type() != node_element && type() != node_declaration) return xml_attribute();
xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root)));
if (!a) return xml_attribute();
impl::append_attribute(a._attr, _root);
Arseny Kapoulkine
committed
a.set_name(name_);
return a;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute xml_node::prepend_attribute(const char_t* name_)
arseny.kapoulkine@gmail.com
committed
{
if (type() != node_element && type() != node_declaration) return xml_attribute();
arseny.kapoulkine@gmail.com
committed
xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root)));
arseny.kapoulkine@gmail.com
committed
if (!a) return xml_attribute();
impl::prepend_attribute(a._attr, _root);
Arseny Kapoulkine
committed
a.set_name(name_);
arseny.kapoulkine@gmail.com
committed
return a;
}
PUGI__FN xml_attribute xml_node::insert_attribute_after(const char_t* name_, const xml_attribute& attr)
if (type() != node_element && type() != node_declaration) return xml_attribute();
if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute();
arseny.kapoulkine@gmail.com
committed
xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root)));
if (!a) return xml_attribute();
impl::insert_attribute_after(a._attr, attr._attr, _root);
Arseny Kapoulkine
committed
a.set_name(name_);
return a;
}
PUGI__FN xml_attribute xml_node::insert_attribute_before(const char_t* name_, const xml_attribute& attr)
if (type() != node_element && type() != node_declaration) return xml_attribute();
if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute();
arseny.kapoulkine@gmail.com
committed
xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root)));
if (!a) return xml_attribute();
impl::insert_attribute_before(a._attr, attr._attr, _root);
Arseny Kapoulkine
committed
a.set_name(name_);
return a;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute xml_node::append_copy(const xml_attribute& proto)
{
if (!proto) return xml_attribute();
xml_attribute result = append_attribute(proto.name());
result.set_value(proto.value());
return result;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute xml_node::prepend_copy(const xml_attribute& proto)
arseny.kapoulkine@gmail.com
committed
{
if (!proto) return xml_attribute();
xml_attribute result = prepend_attribute(proto.name());
result.set_value(proto.value());
return result;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute xml_node::insert_copy_after(const xml_attribute& proto, const xml_attribute& attr)
{
if (!proto) return xml_attribute();
xml_attribute result = insert_attribute_after(proto.name(), attr);
result.set_value(proto.value());
return result;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_attribute xml_node::insert_copy_before(const xml_attribute& proto, const xml_attribute& attr)
{
if (!proto) return xml_attribute();
xml_attribute result = insert_attribute_before(proto.name(), attr);
result.set_value(proto.value());
return result;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node xml_node::append_child(xml_node_type type_)
arseny.kapoulkine@gmail.com
committed
if (!impl::allow_insert_child(this->type(), type_)) return xml_node();
xml_node n(impl::allocate_node(impl::get_allocator(_root), type_));
if (!n) return xml_node();
impl::append_node(n._root, _root);
if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml"));
return n;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node xml_node::prepend_child(xml_node_type type_)
arseny.kapoulkine@gmail.com
committed
{
arseny.kapoulkine@gmail.com
committed
if (!impl::allow_insert_child(this->type(), type_)) return xml_node();
arseny.kapoulkine@gmail.com
committed
arseny.kapoulkine@gmail.com
committed
xml_node n(impl::allocate_node(impl::get_allocator(_root), type_));
arseny.kapoulkine@gmail.com
committed
if (!n) return xml_node();
impl::prepend_node(n._root, _root);
arseny.kapoulkine@gmail.com
committed
if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml"));
arseny.kapoulkine@gmail.com
committed
return n;
}
arseny.kapoulkine@gmail.com
committed
PUGI__FN xml_node xml_node::insert_child_before(xml_node_type type_, const xml_node& node)
arseny.kapoulkine@gmail.com
committed
if (!impl::allow_insert_child(this->type(), type_)) return xml_node();
if (!node._root || node._root->parent != _root) return xml_node();
arseny.kapoulkine@gmail.com
committed
xml_node n(impl::allocate_node(impl::get_allocator(_root), type_));