Mercurial > minori
view dep/pugixml/docs/samples/save_custom_writer.cpp @ 187:9613d72b097e
*: multiple performance improvements
like marking `static const` when it makes sense...
date: change old stupid heap-based method to a structure which should
make copying the thing actually make a copy.
also many performance-based changes, like removing the std::tie
dependency and forward-declaring nlohmann json
*: replace every instance of QString::fromUtf8 to Strings::ToQString.
the main difference is that our function will always convert exactly
what is in the string, while some other times it would only convert
up to the nearest NUL byte
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Wed, 06 Dec 2023 13:43:54 -0500 |
parents | d10b6c6b432e |
children |
line wrap: on
line source
#include "pugixml.hpp" #include <string> #include <iostream> #include <cstring> // tag::code[] struct xml_string_writer: pugi::xml_writer { std::string result; virtual void write(const void* data, size_t size) { result.append(static_cast<const char*>(data), size); } }; // end::code[] struct xml_memory_writer: pugi::xml_writer { char* buffer; size_t capacity; size_t result; xml_memory_writer(): buffer(0), capacity(0), result(0) { } xml_memory_writer(char* buffer, size_t capacity): buffer(buffer), capacity(capacity), result(0) { } size_t written_size() const { return result < capacity ? result : capacity; } virtual void write(const void* data, size_t size) { if (result < capacity) { size_t chunk = (capacity - result < size) ? capacity - result : size; memcpy(buffer + result, data, chunk); } result += size; } }; std::string node_to_string(pugi::xml_node node) { xml_string_writer writer; node.print(writer); return writer.result; } char* node_to_buffer(pugi::xml_node node, char* buffer, size_t size) { if (size == 0) return buffer; // leave one character for null terminator xml_memory_writer writer(buffer, size - 1); node.print(writer); // null terminate buffer[writer.written_size()] = 0; return buffer; } char* node_to_buffer_heap(pugi::xml_node node) { // first pass: get required memory size xml_memory_writer counter; node.print(counter); // allocate necessary size (+1 for null termination) char* buffer = new char[counter.result + 1]; // second pass: actual printing xml_memory_writer writer(buffer, counter.result); node.print(writer); // null terminate buffer[writer.written_size()] = 0; return buffer; } int main() { // get a test document pugi::xml_document doc; doc.load_string("<foo bar='baz'>hey</foo>"); // get contents as std::string (single pass) std::cout << "contents: [" << node_to_string(doc) << "]\n"; // get contents into fixed-size buffer (single pass) char large_buf[128]; std::cout << "contents: [" << node_to_buffer(doc, large_buf, sizeof(large_buf)) << "]\n"; // get contents into fixed-size buffer (single pass, shows truncating behavior) char small_buf[22]; std::cout << "contents: [" << node_to_buffer(doc, small_buf, sizeof(small_buf)) << "]\n"; // get contents into heap-allocated buffer (two passes) char* heap_buf = node_to_buffer_heap(doc); std::cout << "contents: [" << heap_buf << "]\n"; delete[] heap_buf; } // vim:et