diff --git a/.github/workflows/gtest.yml b/.github/workflows/gtest.yml index 60a9455..79e27c6 100644 --- a/.github/workflows/gtest.yml +++ b/.github/workflows/gtest.yml @@ -1,10 +1,8 @@ name: gtest on: - push: - branches: - - master - pull_request: + - push + - pull_request jobs: gtest: @@ -14,38 +12,50 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Checkout Sentry Native - uses: actions/checkout@v4 + - name: Figure out version + id: tag + run: | + TAG=$(git describe --tags --abbrev=0) + COMMITS_SINCE_TAG=$(git rev-list ${TAG}..HEAD --count) + if [ "${COMMITS_SINCE_TAG}" -eq 0 ]; then + echo "VERSION=${VERSION}" >> $GITHUB_ENV + else + echo "VERSION="$(git describe --tags --abbrev=8) >> $GITHUB_ENV + fi + - name: Cache Conan2 dependencies + uses: actions/cache@v3 with: - repository: getsentry/sentry-native - path: sentry-native - - name: Apt dance - run: sudo apt-get update - - name: Install libcurl - run: sudo apt-get install libcurl4-openssl-dev + path: ~/.conan2 + key: ${{ runner.os }}-conan2-${{ hashFiles('**/conanfile.py') }} + restore-keys: | + ${{ runner.os }}-conan2- - name: Set up Python 3.8 for gcovr uses: actions/setup-python@v4 - with: - python-version: 3.8 - - name: install gcovr 5.0 - run: | - pip install gcovr==5.0 # 5.1 is not supported - name: SonarQube install uses: SonarSource/sonarcloud-github-c-cpp@v3 - - name: Make build directory - run: mkdir gtest-build - - name: CMake - run: cmake -S . -B gtest-build -DCMAKE_BUILD_TYPE=Debug + - name: Install Conan + run: pip install conan + - name: Configure Conan Profile + run: | + conan profile detect -e + conan remote add conan-nexus https://nexus.cridland.io/repository/dwd-conan --force + conan remote login conan-nexus ci --password ${{ secrets.NEXUS_PASSWORD }} + - name: Conan Deps + run: conan install . --output-folder=gh-build -s build_type=Debug -s compiler.cppstd=gnu23 -b missing --version=${{ env.VERSION }} + - name: Create package + run: conan create . --version=${{ env.VERSION }} + - name: Conan deps for tests + run: cd test && conan install . --output-folder=. -s build_type=Debug -s compiler.cppstd=gnu23 -b missing --version=${{ env.VERSION }} + - name: CMake tests + run: cd test && cmake -B gh-build -DCMAKE_BUILD_TYPE=Debug - name: Build Wrapper - run: build-wrapper-linux-x86-64 --out-dir sonar-out cmake --build gtest-build - - name: Run Tests - run: cd ./gtest-build && ./rapidxml-test - - name: Show coverage - run: cd ./gtest-build && gcovr -r .. - - name: Collate coverage - run: cd ./gtest-build && gcovr -r .. --sonarqube >../coverage.xml + run: cd test && build-wrapper-linux-x86-64 --out-dir sonar-out cmake --build gh-build - name: Sonar Scanner - run: sonar-scanner --define sonar.cfamily.compile-commands=sonar-out/compile_commands.json --define sonar.coverageReportPaths=coverage.xml + run: cd test && sonar-scanner --define sonar.cfamily.compile-commands=sonar-out/compile_commands.json env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + - name: Run Tests + run: cd test/gh-build && ./rapidxml-test + - name: Upload + run: conan upload -r conan-nexus --confirm 'flxml/*' diff --git a/README.md b/README.md index 6c64828..7a1c7d0 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ -# RapidXML -## Dave's Version +# FLXML +## Or -- RapidXML, Dave's Version -Hey! This is RapidXML, an ancient C++ library for parsing XML quickly and flexibly. +Hey! This is a fork of RapidXML, an ancient C++ library for parsing XML quickly and flexibly. To distinguish, this version is called "FLXML", for "Fast/Light XML". Hey, it's a name. There's a lot of forks of this around, and I (Dave Cridland) didn't write the vast majority of this library - instead, it was written by someone called Marcin Kalicinski, and his copyright is dated 2009. ## Version 2, Breaking Changes -This is version 2.x. You might not want this. +This is version 2.x. You might not want this, since it introduces a number of breaking changes from rapidxml. The rapidxml-like library is available, with breaking changes, by including `rapidxml.hpp` as before, within the `rapidxml` namespace - however this is an alias to the `flxml` namespace defined in `flxml.h`. It has breaking changes, the largest of which are: * No more case insensitive option. Really, nobody should be using XML case insensitively anyway, but it was too difficult to keep around, sorry. @@ -28,12 +28,12 @@ Internal changes: New features: * Instead of the `doc->allocate_node` / `node->append_node` dance, you can now `node->append_element(name, value)`, where `name` can be either a `string` (or `string_view`, etc) or a tuple like {xmlns, local_name}, which will set an xmlns attribute if needed. -* There's a xpathish thing going on in `rapidxml_predicates`, which lets you search for (or iterate through) elements using a trivial subset of XPath. +* There's a xpathish thing going on in `flxml/predicates.h`, which lets you search for (or iterate through) elements using a trivial subset of XPath. * You can get access to containerish things in rapidxml_iterators by methods on nodes/documents, as `node.children()`, `node.attributes()` and a new `node.descendants()`. ### Fun -The rapidxml_iterators library is now included in rapidxml.hpp, and you can do amusing things like: +The rapidxml_iterators library is now included in `flxml.h`, and you can do amusing things like: ```c++ for (auto & child : node.children()) { @@ -46,7 +46,7 @@ More in [test/iterators.cpp](./test/iterators.cpp) Of course, in this case it might be simpler to: ```c++ -auto xpath = rapidxml::xpath::parse("/potato"); +auto xpath = flxml::xpath::parse("/potato"); for (auto & child : xp->all(node)) { scream_for(joy); } @@ -77,10 +77,10 @@ The other thing this fork added was a file of simple tests, which I've recently The original makes reference to an expansive test suite, but this was not included in the open source release. I'll expand these tests as and when I need to. -The tests use a driver which can optionally use Sentry for performance/error tracking; to enable, use the CMake option RAPIDXML_SENTRY, and clone the [sentry-native](https://github.com/getsentry/sentry-native) repository into the root, and when running `rapidxml-test`, set SENTRY_DSN in the environment. None of the submodules are needed, but it'll need libcurl, so `sudo apt install libcurl4-openssl-dev`. +The tests use a driver which can optionally use Sentry for performance/error tracking; to enable, use the CMake option RAPIDXML_SENTRY, and clone the [sentry-native](https://github.com/getsentry/sentry-native) repository into the root, and when running `rapidxml-test`, set SENTRY_DSN in the environment. -## Pull Requests +The tests are in a different Conan package, to keep things light and simple. -Erm. I didn't expect any, so never set up any of the infrastructure for them - this was really a fork-of-convenience for me. Not that they're unwelcome, of course, just entirely unexpected. +## Pull Requests -But yeah, go for it, just include an assurance you're happy with the licensing. \ No newline at end of file +Pull request are very welcome, but do ensure you're happy with the licensing first. \ No newline at end of file diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000..b420226 --- /dev/null +++ b/conanfile.py @@ -0,0 +1,16 @@ +from conan import ConanFile +from conan.tools.files import copy + +class FLXML(ConanFile): + name = "flxml" + exports_sources = "include/*" + no_copy_source = True + + def package(self): + copy(self, "include/*.hpp", self.source_folder, self.package_folder) + copy(self, "include/*.h", self.source_folder, self.package_folder) + + def package_info(self): + self.cpp_info.includedirs = ['include'] + self.cpp_info.libdirs = [] + self.cpp_info.bindirs = [] diff --git a/rapidxml.hpp b/include/flxml.h similarity index 96% rename from rapidxml.hpp rename to include/flxml.h index 365e929..56a3129 100644 --- a/rapidxml.hpp +++ b/include/flxml.h @@ -6,20 +6,17 @@ // Revision $DateTime: 2009/05/13 01:46:17 $ //! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation -#include "rapidxml_wrappers.hpp" -#include "rapidxml_tables.hpp" - -// If standard library is disabled, user must provide implementations of required functions and typedefs -#if !defined(RAPIDXML_NO_STDLIB) - #include // For std::size_t - #include // For assert - #include // For placement new - #include - #include - #include - #include - #include // For std::runtime_error -#endif +#include +#include + +#include // For std::size_t +#include // For assert +#include // For placement new +#include +#include +#include +#include +#include // For std::runtime_error // On MSVC, disable "conditional expression is constant" warning (level 4). // This warning is almost impossible to avoid with certain types of templated code @@ -31,12 +28,12 @@ /////////////////////////////////////////////////////////////////////////// // RAPIDXML_PARSE_ERROR -#if defined(RAPIDXML_NO_EXCEPTIONS) +#if defined(FLXML_NO_EXCEPTIONS) -#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); } -#define RAPIDXML_EOF_ERROR(what, where) { parse_error_handler(what, where); assert(0); } +#define FLXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); } +#define FLML_EOF_ERROR(what, where) { parse_error_handler(what, where); assert(0); } -namespace rapidxml +namespace flxml { //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, //! this function is called to notify user about the error. @@ -59,10 +56,10 @@ namespace rapidxml #else -#define RAPIDXML_PARSE_ERROR(what, where) {if (*where == Ch(0)) throw eof_error(what, nullptr); else throw parse_error(what, nullptr);} (void)0 -#define RAPIDXML_EOF_ERROR(what, where) throw eof_error(what, nullptr) +#define FLXML_PARSE_ERROR(what, where) {if (*where == Ch(0)) throw eof_error(what, nullptr); else throw parse_error(what, nullptr);} (void)0 +#define FLXML_EOF_ERROR(what, where) throw eof_error(what, nullptr) -namespace rapidxml +namespace flxml { //! Parse error exception. @@ -138,21 +135,21 @@ namespace rapidxml /////////////////////////////////////////////////////////////////////////// // Pool sizes -#ifndef RAPIDXML_STATIC_POOL_SIZE +#ifndef FLXML_STATIC_POOL_SIZE // Size of static memory block of memory_pool. // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. // No dynamic memory allocations are performed by memory_pool until static memory is exhausted. - #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024) + #define FLXML_STATIC_POOL_SIZE (64 * 1024) #endif -#ifndef RAPIDXML_DYNAMIC_POOL_SIZE +#ifndef FLXML_DYNAMIC_POOL_SIZE // Size of dynamic memory block of memory_pool. // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool. - #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) + #define FLXML_DYNAMIC_POOL_SIZE (64 * 1024) #endif -namespace rapidxml +namespace flxml { // Forward declarations template class xml_node; @@ -569,9 +566,9 @@ namespace rapidxml else { memory = new char[size]; -#ifdef RAPIDXML_NO_EXCEPTIONS +#ifdef FLXML_NO_EXCEPTIONS if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc - RAPIDXML_PARSE_ERROR("out of memory", 0); + FLXML_PARSE_ERROR("out of memory", 0); #endif } return memory; @@ -585,7 +582,7 @@ namespace rapidxml if (!std::align(alignof(T), sizeof(T) * n, m_ptr, m_space)) { // If not enough memory left in current pool, allocate a new pool // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE) - std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE; + std::size_t pool_size = FLXML_DYNAMIC_POOL_SIZE; if (pool_size < size) pool_size = size; @@ -616,8 +613,8 @@ namespace rapidxml void *m_begin = nullptr; // Start of raw memory making up current pool void *m_ptr = nullptr; // First free byte in current pool - std::size_t m_space = RAPIDXML_STATIC_POOL_SIZE; // Available space remaining - std::array m_static_memory = {}; // Static raw memory + std::size_t m_space = FLXML_STATIC_POOL_SIZE; // Available space remaining + std::array m_static_memory = {}; // Static raw memory alloc_func m_alloc_func = nullptr; // Allocator function, or 0 if default is to be used free_func m_free_func = nullptr; // Free function, or 0 if default is to be used view_type m_nullstr; @@ -1014,16 +1011,16 @@ namespace rapidxml return nullptr; } - rapidxml::children children() const { - return rapidxml::children{*this}; + flxml::children children() const { + return flxml::children{*this}; } - rapidxml::descendants descendants() const { - return rapidxml::descendants{optional_ptr>{const_cast *>(this)}}; + flxml::descendants descendants() const { + return flxml::descendants{optional_ptr>{const_cast *>(this)}}; } - rapidxml::attributes attributes() const { - return rapidxml::attributes{*this}; + flxml::attributes attributes() const { + return flxml::attributes{*this}; } //! Gets first child node, optionally matching node name. @@ -1662,9 +1659,9 @@ namespace rapidxml } } else - RAPIDXML_PARSE_ERROR("expected <", text); + FLXML_PARSE_ERROR("expected <", text); } - if (!this->first_node()) RAPIDXML_PARSE_ERROR("no root element", text); + if (!this->first_node()) FLXML_PARSE_ERROR("no root element", text); return text; } @@ -1904,7 +1901,7 @@ namespace rapidxml } else // Invalid, only codes up to 0x10FFFF are allowed in Unicode { - RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); + FLXML_PARSE_ERROR("invalid numeric character entity", text); } } } @@ -2033,7 +2030,7 @@ namespace rapidxml if (*src == Ch(';')) ++src; else - RAPIDXML_PARSE_ERROR("expected ;", src); + FLXML_PARSE_ERROR("expected ;", src); continue; // Something else @@ -2091,7 +2088,7 @@ namespace rapidxml // Skip until end of declaration while (text[0] != Ch('?') || text[1] != Ch('>')) { - if (!text[0]) RAPIDXML_PARSE_ERROR("unexpected end of data", text); + if (!text[0]) FLXML_PARSE_ERROR("unexpected end of data", text); ++text; } text += 2; // Skip '?>' @@ -2108,7 +2105,7 @@ namespace rapidxml parse_node_attributes(text, declaration); // Skip ?> - if (text[0] != Ch('?') || text[1] != Ch('>')) RAPIDXML_PARSE_ERROR("expected ?>", text); + if (text[0] != Ch('?') || text[1] != Ch('>')) FLXML_PARSE_ERROR("expected ?>", text); text += 2; return declaration; @@ -2124,7 +2121,7 @@ namespace rapidxml // Skip until end of comment while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) { - if (!text[0]) RAPIDXML_PARSE_ERROR("unexpected end of data", text); + if (!text[0]) FLXML_PARSE_ERROR("unexpected end of data", text); ++text; } text += 3; // Skip '-->' @@ -2137,7 +2134,7 @@ namespace rapidxml // Skip until end of comment while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) { - if (!text[0]) RAPIDXML_PARSE_ERROR("unexpected end of data", text); + if (!text[0]) FLXML_PARSE_ERROR("unexpected end of data", text); ++text; } @@ -2175,7 +2172,7 @@ namespace rapidxml { case Ch('['): ++depth; break; case Ch(']'): --depth; break; - case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text); + case 0: FLXML_PARSE_ERROR("unexpected end of data", text); default: break; } ++text; @@ -2185,7 +2182,7 @@ namespace rapidxml // Error on end of text case Ch('\0'): - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + FLXML_PARSE_ERROR("unexpected end of data", text); // Other character, skip it default: @@ -2225,7 +2222,7 @@ namespace rapidxml // Extract PI target name Chp name = text; skip(text); - if (text == name) RAPIDXML_PARSE_ERROR("expected PI target", text); + if (text == name) FLXML_PARSE_ERROR("expected PI target", text); pi->name({name, text}); // Skip whitespace between pi target and pi @@ -2238,7 +2235,7 @@ namespace rapidxml while (text[0] != Ch('?') || text[1] != Ch('>')) { if (*text == Ch('\0')) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + FLXML_PARSE_ERROR("unexpected end of data", text); ++text; } @@ -2254,7 +2251,7 @@ namespace rapidxml while (text[0] != Ch('?') || text[1] != Ch('>')) { if (*text == Ch('\0')) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + FLXML_PARSE_ERROR("unexpected end of data", text); ++text; } text += 2; // Skip '?>' @@ -2314,7 +2311,7 @@ namespace rapidxml while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + FLXML_PARSE_ERROR("unexpected end of data", text); ++text; } text += 3; // Skip ]]> @@ -2326,7 +2323,7 @@ namespace rapidxml while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + FLXML_PARSE_ERROR("unexpected end of data", text); ++text; } @@ -2350,14 +2347,14 @@ namespace rapidxml view_type qname; skip(text); if (text == prefix) - RAPIDXML_PARSE_ERROR("expected element name or prefix", text); + FLXML_PARSE_ERROR("expected element name or prefix", text); if (*text == Ch(':')) { element->prefix({prefix, text}); ++text; Chp name = text; skip(text); if (text == name) - RAPIDXML_PARSE_ERROR("expected element local name", text); + FLXML_PARSE_ERROR("expected element local name", text); element->name({name, text}); } else { element->name({prefix, text}); @@ -2385,13 +2382,13 @@ namespace rapidxml { ++text; if (*text != Ch('>')) - RAPIDXML_PARSE_ERROR("expected >", text); + FLXML_PARSE_ERROR("expected >", text); ++text; if (Flags & parse_open_only) - RAPIDXML_PARSE_ERROR("open_only, but closed", text); + FLXML_PARSE_ERROR("open_only, but closed", text); } else - RAPIDXML_PARSE_ERROR("expected >", text); + FLXML_PARSE_ERROR("expected >", text); // Return parsed element return element; @@ -2476,7 +2473,7 @@ namespace rapidxml while (*text != Ch('>')) { if (*text == 0) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + FLXML_PARSE_ERROR("unexpected end of data", text); ++text; } ++text; // Skip '>' @@ -2522,7 +2519,7 @@ namespace rapidxml Chp closing_name = text; skip(text); if (qname != view_type{closing_name, text}) - RAPIDXML_PARSE_ERROR("invalid closing tag name", text); + FLXML_PARSE_ERROR("invalid closing tag name", text); } else { @@ -2532,10 +2529,10 @@ namespace rapidxml // Skip remaining whitespace after node name skip(text); if (*text != Ch('>')) - RAPIDXML_PARSE_ERROR("expected >", text); + FLXML_PARSE_ERROR("expected >", text); ++text; // Skip '>' if (Flags & parse_open_only) - RAPIDXML_PARSE_ERROR("Unclosed element actually closed.", text); + FLXML_PARSE_ERROR("Unclosed element actually closed.", text); return retval; // Node closed, finished parsing contents } else @@ -2552,7 +2549,7 @@ namespace rapidxml if (Flags & parse_open_only) { return Chp(); } else { - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + FLXML_PARSE_ERROR("unexpected end of data", text); } // Data node @@ -2576,7 +2573,7 @@ namespace rapidxml ++text; // Skip first character of attribute name skip(text); if (text == name) - RAPIDXML_PARSE_ERROR("expected attribute name", name); + FLXML_PARSE_ERROR("expected attribute name", name); // Create new attribute xml_attribute *attribute = this->allocate_attribute(view_type{name, text}); @@ -2587,7 +2584,7 @@ namespace rapidxml // Skip = if (*text != Ch('=')) - RAPIDXML_PARSE_ERROR("expected =", text); + FLXML_PARSE_ERROR("expected =", text); ++text; // Skip whitespace after = @@ -2596,7 +2593,7 @@ namespace rapidxml // Skip quote and remember if it was ' or " Ch quote = *text; if (quote != Ch('\'') && quote != Ch('"')) - RAPIDXML_PARSE_ERROR("expected ' or \"", text); + FLXML_PARSE_ERROR("expected ' or \"", text); attribute->quote(quote); ++text; @@ -2615,7 +2612,7 @@ namespace rapidxml // Make sure that end quote is present if (*text != quote) - RAPIDXML_PARSE_ERROR("expected ' or \"", text); + FLXML_PARSE_ERROR("expected ' or \"", text); ++text; // Skip quote // Skip whitespace after attribute value @@ -2630,10 +2627,10 @@ namespace rapidxml } // Also include this now. -#include +#include // Undefine internal macros -#undef RAPIDXML_PARSE_ERROR +#undef FLXML_PARSE_ERROR // On MSVC, restore warnings state #ifdef _MSC_VER diff --git a/rapidxml_generator.hpp b/include/flxml/generator.h similarity index 98% rename from rapidxml_generator.hpp rename to include/flxml/generator.h index c20e17e..f2d74db 100644 --- a/rapidxml_generator.hpp +++ b/include/flxml/generator.h @@ -8,7 +8,7 @@ #include #include -namespace rapidxml { +namespace flxml { template class generator { public: diff --git a/rapidxml_iterators.hpp b/include/flxml/iterators.h similarity index 94% rename from rapidxml_iterators.hpp rename to include/flxml/iterators.h index e5a0ba3..5abc662 100644 --- a/rapidxml_iterators.hpp +++ b/include/flxml/iterators.h @@ -1,402 +1,402 @@ -#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED -#define RAPIDXML_ITERATORS_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml_iterators.hpp This file contains rapidxml iterators - -#include "rapidxml.hpp" - -namespace rapidxml -{ - //! Iterator of child nodes of xml_node - template -class node_iterator - { - public: - using value_type = xml_node; - using reference = xml_node &; - using pointer = xml_node *; - using iterator_category = std::bidirectional_iterator_tag; - using difference_type = long; - - node_iterator() - : m_node() - { - } - - explicit node_iterator(xml_node const &node) - : m_node(node.first_node()) - { - } - - node_iterator(node_iterator && other) noexcept : m_node(other.m_node) {} - node_iterator(node_iterator const & other) : m_node(other.m_node) {} - - reference operator *() const - { - return const_cast(*m_node); - } - - pointer operator->() const - { - return const_cast(m_node.get()); - } - - node_iterator& operator++() - { - m_node = m_node->next_sibling(); - return *this; - } - - node_iterator operator++(int) - { - node_iterator tmp = *this; - ++(*this); - return tmp; - } - - node_iterator& operator--() - { - m_node = m_node->previous_sibling(); - return *this; - } - - node_iterator operator--(int) - { - node_iterator tmp = *this; - --(*this); - return tmp; - } - - bool operator == (const node_iterator& rhs) const - { - return m_node == rhs.m_node; - } - - bool operator != (const node_iterator& rhs) const - { - return m_node != rhs.m_node; - } - - node_iterator & operator = (node_iterator && other) noexcept { - m_node = other.m_node; - return *this; - } - - node_iterator & operator = (node_iterator const & other) { - m_node = other.m_node; - return *this; - } - - bool valid() - { - return m_node.has_value(); - } - - private: - - optional_ptr> m_node; - - }; - - //! Iterator of child nodes of xml_node - template -class descendant_iterator - { - public: - using value_type = xml_node; - using reference = xml_node &; - using pointer = xml_node *; - using iterator_category = std::bidirectional_iterator_tag; - using difference_type = long; - - descendant_iterator() - : m_parent(), m_node() - { - } - - explicit descendant_iterator(xml_node::ptr node) - : m_parent(node), m_node(node->first_node()) - { - } - - descendant_iterator(descendant_iterator && other) noexcept : m_parent(other.m_parent), m_node(other.m_node) {} - descendant_iterator(descendant_iterator const & other) : m_parent(other.m_parent), m_node(other.m_node) {} - - reference operator *() const - { - return const_cast(*m_node); - } - - pointer operator->() const - { - return const_cast(m_node.get()); - } - - descendant_iterator& operator++() - { - if (m_node->first_node()) { - m_node = m_node->first_node(); - } else if (m_node->next_sibling()) { - m_node = m_node->next_sibling(); - } else { - // Run out of children, so move upward until we can find a sibling. - while (true) { - m_node = m_node->parent(); - if (m_node == m_parent) { - m_node = nullptr; - break; - } - if (m_node->next_sibling()) { - m_node = m_node->next_sibling(); - break; - } - } - } - return *this; - } - - descendant_iterator operator++(int) - { - node_iterator tmp = *this; - ++(*this); - return tmp; - } - - descendant_iterator& operator--() - { - if (!m_node->previous_sibling()) { - m_node = m_node->parent(); - if (m_node == m_parent) { - m_node = nullptr; - } - } else { - m_node = m_node->previous_sibling(); - while (m_node->last_node()) { - m_node = m_node->last_node(); - } - } - return *this; - } - - descendant_iterator operator--(int) - { - node_iterator tmp = *this; - --(*this); - return tmp; - } - - bool operator == (const descendant_iterator& rhs) const - { - return m_node == rhs.m_node; - } - - bool operator != (const descendant_iterator& rhs) const - { - return m_node != rhs.m_node; - } - - descendant_iterator & operator = (descendant_iterator && other) noexcept { - m_parent = other.m_parent; - m_node = other.m_node; - return *this; - } - - descendant_iterator & operator = (descendant_iterator const & other) { - m_parent = other.m_parent; - m_node = other.m_node; - return *this; - } - - bool valid() - { - return m_node.has_value(); - } - - private: - - optional_ptr> m_parent; - optional_ptr> m_node; - }; - - //! Iterator of child attributes of xml_node - template - class attribute_iterator - { - - public: - - using value_type = xml_attribute; - using reference = xml_attribute &; - using pointer = xml_attribute *; - using iterator_category = std::bidirectional_iterator_tag; - using difference_type = long; - - attribute_iterator() - : m_attribute() - { - } - - explicit attribute_iterator(xml_node const &node) - : m_attribute(node.first_attribute()) - { - } - - attribute_iterator(attribute_iterator && other) noexcept : m_attribute(other.m_attribute) {} - attribute_iterator(attribute_iterator const & other) : m_attribute(other.m_attribute) {} - - reference operator *() const - { - return const_cast(*m_attribute); - } - - pointer operator->() const - { - return const_cast(m_attribute.get()); - } - - attribute_iterator& operator++() - { - m_attribute = m_attribute->next_attribute(); - return *this; - } - - attribute_iterator operator++(int) - { - attribute_iterator tmp = *this; - ++*this; - return tmp; - } - - attribute_iterator& operator--() - { - m_attribute = m_attribute->previous_attribute(); - return *this; - } - - attribute_iterator operator--(int) - { - attribute_iterator tmp = *this; - --*this; - return tmp; - } - - bool operator ==(const attribute_iterator &rhs) const - { - return m_attribute == rhs.m_attribute; - } - - bool operator !=(const attribute_iterator &rhs) const - { - return m_attribute != rhs.m_attribute; - } - - attribute_iterator & operator = (attribute_iterator && other) noexcept { - m_attribute = other.m_attribute; - return *this; - } - - attribute_iterator & operator = (attribute_iterator const & other) { - m_attribute = other.m_attribute; - return *this; - } - - private: - - optional_ptr> m_attribute; - - }; - - //! Container adaptor for child nodes - template - class children - { - xml_node const & m_node; - public: - explicit children(xml_node const & node) : m_node(node) {} - explicit children(optional_ptr> const ptr) : m_node(ptr.value()) {} - children(children && other) noexcept : m_node(other.m_node) {} - children(children const & other) : m_node(other.m_node) {} - - using const_iterator = node_iterator; - using iterator = node_iterator; - - iterator begin() { - return iterator(m_node); - } - iterator end() { - return {}; - } - const_iterator begin() const { - return const_iterator(m_node); - } - const_iterator end() const { - return {}; - } - }; - - //! Container adaptor for child nodes - template - class descendants - { - xml_node & m_node; - public: - explicit descendants(xml_node & node) : m_node(node) {} - explicit descendants(optional_ptr> ptr) : m_node(ptr.value()) {} - descendants(descendants && other) noexcept : m_node(other.m_node) {} - descendants(descendants const & other) : m_node(other.m_node) {} - - using const_iterator = descendant_iterator; - using iterator = descendant_iterator; - - iterator begin() { - return iterator(&m_node); - } - iterator end() { - return {}; - } - const_iterator begin() const { - return const_iterator(&m_node); - } - const_iterator end() const { - return {}; - } - }; - - //! Container adaptor for attributes - template - class attributes - { - xml_node const & m_node; - public: - explicit attributes(xml_node const & node) : m_node(node) {} - explicit attributes(optional_ptr> ptr) : m_node(ptr.value()) {} - - using const_iterator = attribute_iterator; - using iterator = attribute_iterator; - - iterator begin() { - return iterator{m_node}; - } - iterator end() { - return {}; - } - const_iterator begin() const { - return const_iterator{m_node}; - } - const_iterator end() const { - return {}; - } - }; -} - -template -inline constexpr bool std::ranges::enable_borrowed_range> = true; - -template -inline constexpr bool std::ranges::enable_borrowed_range> = true; - - -#endif +#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED +#define RAPIDXML_ITERATORS_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_iterators.hpp This file contains rapidxml iterators + +#include + +namespace flxml +{ + //! Iterator of child nodes of xml_node + template +class node_iterator + { + public: + using value_type = xml_node; + using reference = xml_node &; + using pointer = xml_node *; + using iterator_category = std::bidirectional_iterator_tag; + using difference_type = long; + + node_iterator() + : m_node() + { + } + + explicit node_iterator(xml_node const &node) + : m_node(node.first_node()) + { + } + + node_iterator(node_iterator && other) noexcept : m_node(other.m_node) {} + node_iterator(node_iterator const & other) : m_node(other.m_node) {} + + reference operator *() const + { + return const_cast(*m_node); + } + + pointer operator->() const + { + return const_cast(m_node.get()); + } + + node_iterator& operator++() + { + m_node = m_node->next_sibling(); + return *this; + } + + node_iterator operator++(int) + { + node_iterator tmp = *this; + ++(*this); + return tmp; + } + + node_iterator& operator--() + { + m_node = m_node->previous_sibling(); + return *this; + } + + node_iterator operator--(int) + { + node_iterator tmp = *this; + --(*this); + return tmp; + } + + bool operator == (const node_iterator& rhs) const + { + return m_node == rhs.m_node; + } + + bool operator != (const node_iterator& rhs) const + { + return m_node != rhs.m_node; + } + + node_iterator & operator = (node_iterator && other) noexcept { + m_node = other.m_node; + return *this; + } + + node_iterator & operator = (node_iterator const & other) { + m_node = other.m_node; + return *this; + } + + bool valid() + { + return m_node.has_value(); + } + + private: + + optional_ptr> m_node; + + }; + + //! Iterator of child nodes of xml_node + template +class descendant_iterator + { + public: + using value_type = xml_node; + using reference = xml_node &; + using pointer = xml_node *; + using iterator_category = std::bidirectional_iterator_tag; + using difference_type = long; + + descendant_iterator() + : m_parent(), m_node() + { + } + + explicit descendant_iterator(xml_node::ptr node) + : m_parent(node), m_node(node->first_node()) + { + } + + descendant_iterator(descendant_iterator && other) noexcept : m_parent(other.m_parent), m_node(other.m_node) {} + descendant_iterator(descendant_iterator const & other) : m_parent(other.m_parent), m_node(other.m_node) {} + + reference operator *() const + { + return const_cast(*m_node); + } + + pointer operator->() const + { + return const_cast(m_node.get()); + } + + descendant_iterator& operator++() + { + if (m_node->first_node()) { + m_node = m_node->first_node(); + } else if (m_node->next_sibling()) { + m_node = m_node->next_sibling(); + } else { + // Run out of children, so move upward until we can find a sibling. + while (true) { + m_node = m_node->parent(); + if (m_node == m_parent) { + m_node = nullptr; + break; + } + if (m_node->next_sibling()) { + m_node = m_node->next_sibling(); + break; + } + } + } + return *this; + } + + descendant_iterator operator++(int) + { + node_iterator tmp = *this; + ++(*this); + return tmp; + } + + descendant_iterator& operator--() + { + if (!m_node->previous_sibling()) { + m_node = m_node->parent(); + if (m_node == m_parent) { + m_node = nullptr; + } + } else { + m_node = m_node->previous_sibling(); + while (m_node->last_node()) { + m_node = m_node->last_node(); + } + } + return *this; + } + + descendant_iterator operator--(int) + { + node_iterator tmp = *this; + --(*this); + return tmp; + } + + bool operator == (const descendant_iterator& rhs) const + { + return m_node == rhs.m_node; + } + + bool operator != (const descendant_iterator& rhs) const + { + return m_node != rhs.m_node; + } + + descendant_iterator & operator = (descendant_iterator && other) noexcept { + m_parent = other.m_parent; + m_node = other.m_node; + return *this; + } + + descendant_iterator & operator = (descendant_iterator const & other) { + m_parent = other.m_parent; + m_node = other.m_node; + return *this; + } + + bool valid() + { + return m_node.has_value(); + } + + private: + + optional_ptr> m_parent; + optional_ptr> m_node; + }; + + //! Iterator of child attributes of xml_node + template + class attribute_iterator + { + + public: + + using value_type = xml_attribute; + using reference = xml_attribute &; + using pointer = xml_attribute *; + using iterator_category = std::bidirectional_iterator_tag; + using difference_type = long; + + attribute_iterator() + : m_attribute() + { + } + + explicit attribute_iterator(xml_node const &node) + : m_attribute(node.first_attribute()) + { + } + + attribute_iterator(attribute_iterator && other) noexcept : m_attribute(other.m_attribute) {} + attribute_iterator(attribute_iterator const & other) : m_attribute(other.m_attribute) {} + + reference operator *() const + { + return const_cast(*m_attribute); + } + + pointer operator->() const + { + return const_cast(m_attribute.get()); + } + + attribute_iterator& operator++() + { + m_attribute = m_attribute->next_attribute(); + return *this; + } + + attribute_iterator operator++(int) + { + attribute_iterator tmp = *this; + ++*this; + return tmp; + } + + attribute_iterator& operator--() + { + m_attribute = m_attribute->previous_attribute(); + return *this; + } + + attribute_iterator operator--(int) + { + attribute_iterator tmp = *this; + --*this; + return tmp; + } + + bool operator ==(const attribute_iterator &rhs) const + { + return m_attribute == rhs.m_attribute; + } + + bool operator !=(const attribute_iterator &rhs) const + { + return m_attribute != rhs.m_attribute; + } + + attribute_iterator & operator = (attribute_iterator && other) noexcept { + m_attribute = other.m_attribute; + return *this; + } + + attribute_iterator & operator = (attribute_iterator const & other) { + m_attribute = other.m_attribute; + return *this; + } + + private: + + optional_ptr> m_attribute; + + }; + + //! Container adaptor for child nodes + template + class children + { + xml_node const & m_node; + public: + explicit children(xml_node const & node) : m_node(node) {} + explicit children(optional_ptr> const ptr) : m_node(ptr.value()) {} + children(children && other) noexcept : m_node(other.m_node) {} + children(children const & other) : m_node(other.m_node) {} + + using const_iterator = node_iterator; + using iterator = node_iterator; + + iterator begin() { + return iterator(m_node); + } + iterator end() { + return {}; + } + const_iterator begin() const { + return const_iterator(m_node); + } + const_iterator end() const { + return {}; + } + }; + + //! Container adaptor for child nodes + template + class descendants + { + xml_node & m_node; + public: + explicit descendants(xml_node & node) : m_node(node) {} + explicit descendants(optional_ptr> ptr) : m_node(ptr.value()) {} + descendants(descendants && other) noexcept : m_node(other.m_node) {} + descendants(descendants const & other) : m_node(other.m_node) {} + + using const_iterator = descendant_iterator; + using iterator = descendant_iterator; + + iterator begin() { + return iterator(&m_node); + } + iterator end() { + return {}; + } + const_iterator begin() const { + return const_iterator(&m_node); + } + const_iterator end() const { + return {}; + } + }; + + //! Container adaptor for attributes + template + class attributes + { + xml_node const & m_node; + public: + explicit attributes(xml_node const & node) : m_node(node) {} + explicit attributes(optional_ptr> ptr) : m_node(ptr.value()) {} + + using const_iterator = attribute_iterator; + using iterator = attribute_iterator; + + iterator begin() { + return iterator{m_node}; + } + iterator end() { + return {}; + } + const_iterator begin() const { + return const_iterator{m_node}; + } + const_iterator end() const { + return {}; + } + }; +} + +template +inline constexpr bool std::ranges::enable_borrowed_range> = true; + +template +inline constexpr bool std::ranges::enable_borrowed_range> = true; + + +#endif diff --git a/rapidxml_predicates.hpp b/include/flxml/predicates.h similarity index 96% rename from rapidxml_predicates.hpp rename to include/flxml/predicates.h index 2f778bd..ae88de4 100644 --- a/rapidxml_predicates.hpp +++ b/include/flxml/predicates.h @@ -7,17 +7,17 @@ #include #include -#include "rapidxml_generator.hpp" -#include "rapidxml.hpp" +#include +#include -namespace rapidxml { +namespace flxml { template class xpath; namespace internal { template class xpath_base; template - class name : public rapidxml::internal::xpath_base { + class name : public flxml::internal::xpath_base { private: std::basic_string m_name; std::optional> m_xmlns; @@ -35,7 +35,7 @@ namespace rapidxml { }; template - class value : public rapidxml::internal::xpath_base { + class value : public flxml::internal::xpath_base { private: std::basic_string m_value; public: @@ -48,7 +48,7 @@ namespace rapidxml { }; template - class xmlns : public rapidxml::internal::xpath_base { + class xmlns : public flxml::internal::xpath_base { private: std::basic_string m_xmlns; public: @@ -61,7 +61,7 @@ namespace rapidxml { }; template - class attr : public rapidxml::internal::xpath_base { + class attr : public flxml::internal::xpath_base { private: std::basic_string m_name; std::basic_string m_value; @@ -89,7 +89,7 @@ namespace rapidxml { }; template - class root : public rapidxml::internal::xpath_base { + class root : public flxml::internal::xpath_base { public: root() = default; @@ -105,7 +105,7 @@ namespace rapidxml { }; template - class any : public rapidxml::internal::xpath_base { + class any : public flxml::internal::xpath_base { public: any() = default; @@ -335,7 +335,7 @@ namespace rapidxml { explicit xpath(std::map & xmlns) : m_xmlns(xmlns) {} - rapidxml::generator &> all(xml_node & current, unsigned int depth = 0) { + flxml::generator &> all(xml_node & current, unsigned int depth = 0) { if (depth >= m_chain.size()) throw std::logic_error("Depth exceeded"); auto & xp = m_chain[depth]; depth++; diff --git a/rapidxml_print.hpp b/include/flxml/print.h similarity index 96% rename from rapidxml_print.hpp rename to include/flxml/print.h index 2315eac..5bd1239 100644 --- a/rapidxml_print.hpp +++ b/include/flxml/print.h @@ -1,477 +1,477 @@ -#ifndef RAPIDXML_PRINT_HPP_INCLUDED -#define RAPIDXML_PRINT_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml_print.hpp This file contains rapidxml printer implementation - -#include "rapidxml.hpp" - -// Only include streams if not disabled -#ifndef RAPIDXML_NO_STREAMS - #include - #include -#endif - -namespace rapidxml -{ - - /////////////////////////////////////////////////////////////////////// - // Printing flags - - const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function. - - /////////////////////////////////////////////////////////////////////// - // Internal - - //! \cond internal - namespace internal - { - - /////////////////////////////////////////////////////////////////////////// - // Internal character operations - - // Copy characters from given range to given output iterator - template - inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out) - { - while (begin != end) - *out++ = *begin++; - return out; - } - - template - inline OutIt copy_chars(std::basic_string_view const & sv, OutIt out) { - return copy_chars(sv.data(), sv.data() + sv.size(), out); - } - - // Copy characters from given range to given output iterator and expand - // characters into references (< > ' " &) - template - inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out) - { - while (begin != end) - { - if (*begin == noexpand) - { - *out++ = *begin; // No expansion, copy character - } - else - { - switch (*begin) - { - case Ch('<'): - *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';'); - break; - case Ch('>'): - *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';'); - break; - case Ch('\''): - *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';'); - break; - case Ch('"'): - *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';'); - break; - case Ch('&'): - *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); - break; - default: - *out++ = *begin; // No expansion, copy character - } - } - ++begin; // Step to next character - } - return out; - } - - - template - inline OutIt copy_and_expand_chars(std::basic_string_view const & sv, Ch noexpand, OutIt out) { - return copy_and_expand_chars(sv.data(), sv.data() + sv.size(), noexpand, out); - } - // Fill given output iterator with repetitions of the same character - template - inline OutIt fill_chars(OutIt out, int n, Ch ch) - { - for (int i = 0; i < n; ++i) - *out++ = ch; - return out; - } - - // Find character - template - inline bool find_char(const Ch *begin, const Ch *end) - { - while (begin != end) - if (*begin++ == ch) - return true; - return false; - } - - /////////////////////////////////////////////////////////////////////////// - // Internal printing operations - - // Print node - template - inline OutIt print_node(OutIt out, const optional_ptr> node, int flags, int indent); - - // Print children of the node - template - inline OutIt print_children(OutIt out, const optional_ptr> node, int flags, int indent) - { - for (auto child = node->first_node(); child; child = child->next_sibling()) - out = print_node(out, child, flags, indent); - return out; - } - - // Print attributes of the node - template - inline OutIt print_attributes(OutIt out, const optional_ptr> node, int flags) - { - for (auto attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute()) - { - if (!(attribute->name().empty()) || attribute->value_raw().empty()) - { - // Print attribute name - *out = Ch(' '), ++out; - out = copy_chars(attribute->name(), out); - *out = Ch('='), ++out; - if (attribute->quote() && !attribute->value_decoded()) { - // Shortcut here; just dump out the raw value. - *out++ = attribute->quote(); - out = copy_chars(attribute->value_raw(), out); - **out++ = attribute->quote(); - } else { - // Print attribute value using appropriate quote type - if (attribute->value().find('"') != std::basic_string_view::npos) { - *out = Ch('\''), ++out; - out = copy_and_expand_chars(attribute->value(), Ch('"'), out); - *out = Ch('\''), ++out; - } else { - *out = Ch('"'), ++out; - out = copy_and_expand_chars(attribute->value(), Ch('\''), out); - *out = Ch('"'), ++out; - } - } - } - } - return out; - } - - // Print data node - template - inline OutIt print_data_node(OutIt out, const optional_ptr> node, int flags, int indent) - { - assert(node->type() == node_type::node_data); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - if (!node->value_decoded()) { - out = copy_chars(node->value_raw(), out); - } else { - out = copy_and_expand_chars(node->value(), Ch(0), out); - } - return out; - } - - // Print data node - template - inline OutIt print_cdata_node(OutIt out, const optional_ptr> node, int flags, int indent) - { - assert(node->type() == node_type::node_cdata); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'); ++out; - *out = Ch('!'); ++out; - *out = Ch('['); ++out; - *out = Ch('C'); ++out; - *out = Ch('D'); ++out; - *out = Ch('A'); ++out; - *out = Ch('T'); ++out; - *out = Ch('A'); ++out; - *out = Ch('['); ++out; - out = copy_chars(node->value(), out); - *out = Ch(']'); ++out; - *out = Ch(']'); ++out; - *out = Ch('>'); ++out; - return out; - } - - // Print element node - template - inline OutIt print_element_node(OutIt out, const optional_ptr> node, int flags, int indent) - { - assert(node->type() == node_type::node_element); - - // Print element name and attributes, if any - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - if (!node->prefix().empty()) { - out = copy_chars(node->prefix(), out); - *out = Ch(':'); ++out; - } - out = copy_chars(node->name(), out); - out = print_attributes(out, node, flags); - - // If node is childless - if (node->value().empty() && !node->first_node()) - { - // Print childless node tag ending - *out = Ch('/'), ++out; - *out = Ch('>'), ++out; - } - else - { - // Print normal node tag ending - *out = Ch('>'), ++out; - - // If the node is clean, just output the contents and move on. - // Can only do this if we're not indenting, otherwise pretty-print won't work. - if (node->clean() && (flags & print_no_indenting)) { - out = copy_chars(node->contents(), out); - } else { - - // Test if node contains a single data node only (and no other nodes) - auto child = node->first_node(); - if (!child) { - // If node has no children, only print its value without indenting - if (!node->value_decoded()) { - out = copy_chars(node->value_raw(), out); - } else { - out = copy_and_expand_chars(node->value(), Ch(0), out); - } - } else if (!child->next_sibling() && child->type() == node_type::node_data) { - // If node has a sole data child, only print its value without indenting - if (!child->value_decoded()) { - out = copy_chars(child->value_raw(), out); - } else { - out = copy_and_expand_chars(child->value(), Ch(0), out); - } - } else { - // Print all children with full indenting - if (!(flags & print_no_indenting)) - *out = Ch('\n'), ++out; - out = print_children(out, node, flags, indent + 1); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - } - } - - // Print node end - *out = Ch('<'), ++out; - *out = Ch('/'), ++out; - if (!node->prefix().empty()) { - out = copy_chars(node->prefix(), out); - *out = Ch(':'); ++out; - } - out = copy_chars(node->name(), out); - *out = Ch('>'), ++out; - } - return out; - } - - // Print declaration node - template - inline OutIt print_declaration_node(OutIt out, const optional_ptr> node, int flags, int indent) - { - // Print declaration start - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('?'), ++out; - *out = Ch('x'), ++out; - *out = Ch('m'), ++out; - *out = Ch('l'), ++out; - - // Print attributes - out = print_attributes(out, node, flags); - - // Print declaration end - *out = Ch('?'), ++out; - *out = Ch('>'), ++out; - - return out; - } - - // Print comment node - template - inline OutIt print_comment_node(OutIt out, const optional_ptr> node, int flags, int indent) - { - assert(node->type() == node_type::node_comment); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('!'), ++out; - *out = Ch('-'), ++out; - *out = Ch('-'), ++out; - out = copy_chars(node->value(), out); - *out = Ch('-'), ++out; - *out = Ch('-'), ++out; - *out = Ch('>'), ++out; - return out; - } - - // Print doctype node - template - inline OutIt print_doctype_node(OutIt out, const optional_ptr> node, int flags, int indent) - { - assert(node->type() == node_type::node_doctype); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('!'), ++out; - *out = Ch('D'), ++out; - *out = Ch('O'), ++out; - *out = Ch('C'), ++out; - *out = Ch('T'), ++out; - *out = Ch('Y'), ++out; - *out = Ch('P'), ++out; - *out = Ch('E'), ++out; - *out = Ch(' '), ++out; - out = copy_chars(node->value(), out); - *out = Ch('>'), ++out; - return out; - } - - // Print pi node - template - inline OutIt print_pi_node(OutIt out, const optional_ptr> node, int flags, int indent) - { - assert(node->type() == node_type::node_pi); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('?'), ++out; - out = copy_chars(node->name(), out); - *out = Ch(' '), ++out; - out = copy_chars(node->value(), out); - *out = Ch('?'), ++out; - *out = Ch('>'), ++out; - return out; - } - - // Print literal node - template - inline OutIt print_literal_node(OutIt out, const optional_ptr> node, int flags, int indent) - { - assert(node->type() == node_type::node_literal); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - out = copy_chars(node->value(), out); - return out; - } - - // Print node - // Print node - template - inline OutIt print_node(OutIt out, const optional_ptr> node, int flags, int indent) - { - // Print proper node type - switch (node->type()) - { - // Document - case node_document: - out = print_children(out, node, flags, indent); - break; - - // Element - case node_element: - out = print_element_node(out, node, flags, indent); - break; - - // Data - case node_data: - out = print_data_node(out, node, flags, indent); - break; - - // CDATA - case node_cdata: - out = print_cdata_node(out, node, flags, indent); - break; - - // Declaration - case node_declaration: - out = print_declaration_node(out, node, flags, indent); - break; - - // Comment - case node_comment: - out = print_comment_node(out, node, flags, indent); - break; - - // Doctype - case node_doctype: - out = print_doctype_node(out, node, flags, indent); - break; - - // Pi - case node_pi: - out = print_pi_node(out, node, flags, indent); - break; - - case node_literal: - out = print_literal_node(out, node, flags, indent); - break; - - // Unknown - default: - assert(0); - break; - } - - // If indenting not disabled, add line break after node - if (!(flags & print_no_indenting)) - *out = Ch('\n'), ++out; - - // Return modified iterator - return out; - } - - } - //! \endcond - - /////////////////////////////////////////////////////////////////////////// - // Printing - - //! Prints XML to given output iterator. - //! \param out Output iterator to print to. - //! \param node Node to be printed. Pass xml_document to print entire document. - //! \param flags Flags controlling how XML is printed. - //! \return Output iterator pointing to position immediately after last character of printed text. - template - inline OutIt print(OutIt out, const xml_node &node, int flags = 0) - { - rapidxml::optional_ptr ptr(const_cast *>(&node)); - return internal::print_node(out, ptr, flags, 0); - } - -#ifndef RAPIDXML_NO_STREAMS - - //! Prints XML to given output stream. - //! \param out Output stream to print to. - //! \param node Node to be printed. Pass xml_document to print entire document. - //! \param flags Flags controlling how XML is printed. - //! \return Output stream. - template - inline std::basic_ostream &print(std::basic_ostream &out, const xml_node &node, int flags = 0) - { - print(std::ostream_iterator(out), node, flags); - return out; - } - - //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process. - //! \param out Output stream to print to. - //! \param node Node to be printed. - //! \return Output stream. - template - inline std::basic_ostream &operator <<(std::basic_ostream &out, const xml_node &node) - { - return print(out, node); - } - -#endif - -} - -#endif +#ifndef RAPIDXML_PRINT_HPP_INCLUDED +#define RAPIDXML_PRINT_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_print.hpp This file contains rapidxml printer implementation + +#include + +// Only include streams if not disabled +#ifndef FLXML_NO_STREAMS + #include + #include +#endif + +namespace flxml +{ + + /////////////////////////////////////////////////////////////////////// + // Printing flags + + const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function. + + /////////////////////////////////////////////////////////////////////// + // Internal + + //! \cond internal + namespace internal + { + + /////////////////////////////////////////////////////////////////////////// + // Internal character operations + + // Copy characters from given range to given output iterator + template + inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out) + { + while (begin != end) + *out++ = *begin++; + return out; + } + + template + inline OutIt copy_chars(std::basic_string_view const & sv, OutIt out) { + return copy_chars(sv.data(), sv.data() + sv.size(), out); + } + + // Copy characters from given range to given output iterator and expand + // characters into references (< > ' " &) + template + inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out) + { + while (begin != end) + { + if (*begin == noexpand) + { + *out++ = *begin; // No expansion, copy character + } + else + { + switch (*begin) + { + case Ch('<'): + *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('>'): + *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('\''): + *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';'); + break; + case Ch('"'): + *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('&'): + *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); + break; + default: + *out++ = *begin; // No expansion, copy character + } + } + ++begin; // Step to next character + } + return out; + } + + + template + inline OutIt copy_and_expand_chars(std::basic_string_view const & sv, Ch noexpand, OutIt out) { + return copy_and_expand_chars(sv.data(), sv.data() + sv.size(), noexpand, out); + } + // Fill given output iterator with repetitions of the same character + template + inline OutIt fill_chars(OutIt out, int n, Ch ch) + { + for (int i = 0; i < n; ++i) + *out++ = ch; + return out; + } + + // Find character + template + inline bool find_char(const Ch *begin, const Ch *end) + { + while (begin != end) + if (*begin++ == ch) + return true; + return false; + } + + /////////////////////////////////////////////////////////////////////////// + // Internal printing operations + + // Print node + template + inline OutIt print_node(OutIt out, const optional_ptr> node, int flags, int indent); + + // Print children of the node + template + inline OutIt print_children(OutIt out, const optional_ptr> node, int flags, int indent) + { + for (auto child = node->first_node(); child; child = child->next_sibling()) + out = print_node(out, child, flags, indent); + return out; + } + + // Print attributes of the node + template + inline OutIt print_attributes(OutIt out, const optional_ptr> node, int flags) + { + for (auto attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute()) + { + if (!(attribute->name().empty()) || attribute->value_raw().empty()) + { + // Print attribute name + *out = Ch(' '), ++out; + out = copy_chars(attribute->name(), out); + *out = Ch('='), ++out; + if (attribute->quote() && !attribute->value_decoded()) { + // Shortcut here; just dump out the raw value. + *out++ = attribute->quote(); + out = copy_chars(attribute->value_raw(), out); + **out++ = attribute->quote(); + } else { + // Print attribute value using appropriate quote type + if (attribute->value().find('"') != std::basic_string_view::npos) { + *out = Ch('\''), ++out; + out = copy_and_expand_chars(attribute->value(), Ch('"'), out); + *out = Ch('\''), ++out; + } else { + *out = Ch('"'), ++out; + out = copy_and_expand_chars(attribute->value(), Ch('\''), out); + *out = Ch('"'), ++out; + } + } + } + } + return out; + } + + // Print data node + template + inline OutIt print_data_node(OutIt out, const optional_ptr> node, int flags, int indent) + { + assert(node->type() == node_type::node_data); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + if (!node->value_decoded()) { + out = copy_chars(node->value_raw(), out); + } else { + out = copy_and_expand_chars(node->value(), Ch(0), out); + } + return out; + } + + // Print data node + template + inline OutIt print_cdata_node(OutIt out, const optional_ptr> node, int flags, int indent) + { + assert(node->type() == node_type::node_cdata); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'); ++out; + *out = Ch('!'); ++out; + *out = Ch('['); ++out; + *out = Ch('C'); ++out; + *out = Ch('D'); ++out; + *out = Ch('A'); ++out; + *out = Ch('T'); ++out; + *out = Ch('A'); ++out; + *out = Ch('['); ++out; + out = copy_chars(node->value(), out); + *out = Ch(']'); ++out; + *out = Ch(']'); ++out; + *out = Ch('>'); ++out; + return out; + } + + // Print element node + template + inline OutIt print_element_node(OutIt out, const optional_ptr> node, int flags, int indent) + { + assert(node->type() == node_type::node_element); + + // Print element name and attributes, if any + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + if (!node->prefix().empty()) { + out = copy_chars(node->prefix(), out); + *out = Ch(':'); ++out; + } + out = copy_chars(node->name(), out); + out = print_attributes(out, node, flags); + + // If node is childless + if (node->value().empty() && !node->first_node()) + { + // Print childless node tag ending + *out = Ch('/'), ++out; + *out = Ch('>'), ++out; + } + else + { + // Print normal node tag ending + *out = Ch('>'), ++out; + + // If the node is clean, just output the contents and move on. + // Can only do this if we're not indenting, otherwise pretty-print won't work. + if (node->clean() && (flags & print_no_indenting)) { + out = copy_chars(node->contents(), out); + } else { + + // Test if node contains a single data node only (and no other nodes) + auto child = node->first_node(); + if (!child) { + // If node has no children, only print its value without indenting + if (!node->value_decoded()) { + out = copy_chars(node->value_raw(), out); + } else { + out = copy_and_expand_chars(node->value(), Ch(0), out); + } + } else if (!child->next_sibling() && child->type() == node_type::node_data) { + // If node has a sole data child, only print its value without indenting + if (!child->value_decoded()) { + out = copy_chars(child->value_raw(), out); + } else { + out = copy_and_expand_chars(child->value(), Ch(0), out); + } + } else { + // Print all children with full indenting + if (!(flags & print_no_indenting)) + *out = Ch('\n'), ++out; + out = print_children(out, node, flags, indent + 1); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + } + } + + // Print node end + *out = Ch('<'), ++out; + *out = Ch('/'), ++out; + if (!node->prefix().empty()) { + out = copy_chars(node->prefix(), out); + *out = Ch(':'); ++out; + } + out = copy_chars(node->name(), out); + *out = Ch('>'), ++out; + } + return out; + } + + // Print declaration node + template + inline OutIt print_declaration_node(OutIt out, const optional_ptr> node, int flags, int indent) + { + // Print declaration start + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('?'), ++out; + *out = Ch('x'), ++out; + *out = Ch('m'), ++out; + *out = Ch('l'), ++out; + + // Print attributes + out = print_attributes(out, node, flags); + + // Print declaration end + *out = Ch('?'), ++out; + *out = Ch('>'), ++out; + + return out; + } + + // Print comment node + template + inline OutIt print_comment_node(OutIt out, const optional_ptr> node, int flags, int indent) + { + assert(node->type() == node_type::node_comment); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('!'), ++out; + *out = Ch('-'), ++out; + *out = Ch('-'), ++out; + out = copy_chars(node->value(), out); + *out = Ch('-'), ++out; + *out = Ch('-'), ++out; + *out = Ch('>'), ++out; + return out; + } + + // Print doctype node + template + inline OutIt print_doctype_node(OutIt out, const optional_ptr> node, int flags, int indent) + { + assert(node->type() == node_type::node_doctype); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('!'), ++out; + *out = Ch('D'), ++out; + *out = Ch('O'), ++out; + *out = Ch('C'), ++out; + *out = Ch('T'), ++out; + *out = Ch('Y'), ++out; + *out = Ch('P'), ++out; + *out = Ch('E'), ++out; + *out = Ch(' '), ++out; + out = copy_chars(node->value(), out); + *out = Ch('>'), ++out; + return out; + } + + // Print pi node + template + inline OutIt print_pi_node(OutIt out, const optional_ptr> node, int flags, int indent) + { + assert(node->type() == node_type::node_pi); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('?'), ++out; + out = copy_chars(node->name(), out); + *out = Ch(' '), ++out; + out = copy_chars(node->value(), out); + *out = Ch('?'), ++out; + *out = Ch('>'), ++out; + return out; + } + + // Print literal node + template + inline OutIt print_literal_node(OutIt out, const optional_ptr> node, int flags, int indent) + { + assert(node->type() == node_type::node_literal); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + out = copy_chars(node->value(), out); + return out; + } + + // Print node + // Print node + template + inline OutIt print_node(OutIt out, const optional_ptr> node, int flags, int indent) + { + // Print proper node type + switch (node->type()) + { + // Document + case node_document: + out = print_children(out, node, flags, indent); + break; + + // Element + case node_element: + out = print_element_node(out, node, flags, indent); + break; + + // Data + case node_data: + out = print_data_node(out, node, flags, indent); + break; + + // CDATA + case node_cdata: + out = print_cdata_node(out, node, flags, indent); + break; + + // Declaration + case node_declaration: + out = print_declaration_node(out, node, flags, indent); + break; + + // Comment + case node_comment: + out = print_comment_node(out, node, flags, indent); + break; + + // Doctype + case node_doctype: + out = print_doctype_node(out, node, flags, indent); + break; + + // Pi + case node_pi: + out = print_pi_node(out, node, flags, indent); + break; + + case node_literal: + out = print_literal_node(out, node, flags, indent); + break; + + // Unknown + default: + assert(0); + break; + } + + // If indenting not disabled, add line break after node + if (!(flags & print_no_indenting)) + *out = Ch('\n'), ++out; + + // Return modified iterator + return out; + } + + } + //! \endcond + + /////////////////////////////////////////////////////////////////////////// + // Printing + + //! Prints XML to given output iterator. + //! \param out Output iterator to print to. + //! \param node Node to be printed. Pass xml_document to print entire document. + //! \param flags Flags controlling how XML is printed. + //! \return Output iterator pointing to position immediately after last character of printed text. + template + inline OutIt print(OutIt out, const xml_node &node, int flags = 0) + { + flxml::optional_ptr ptr(const_cast *>(&node)); + return internal::print_node(out, ptr, flags, 0); + } + +#ifndef RAPIDXML_NO_STREAMS + + //! Prints XML to given output stream. + //! \param out Output stream to print to. + //! \param node Node to be printed. Pass xml_document to print entire document. + //! \param flags Flags controlling how XML is printed. + //! \return Output stream. + template + inline std::basic_ostream &print(std::basic_ostream &out, const xml_node &node, int flags = 0) + { + print(std::ostream_iterator(out), node, flags); + return out; + } + + //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process. + //! \param out Output stream to print to. + //! \param node Node to be printed. + //! \return Output stream. + template + inline std::basic_ostream &operator <<(std::basic_ostream &out, const xml_node &node) + { + return print(out, node); + } + +#endif + +} + +#endif diff --git a/rapidxml_tables.hpp b/include/flxml/tables.h similarity index 99% rename from rapidxml_tables.hpp rename to include/flxml/tables.h index dccce22..815d02d 100644 --- a/rapidxml_tables.hpp +++ b/include/flxml/tables.h @@ -12,7 +12,7 @@ // Internals //! \cond internal -namespace rapidxml::internal { +namespace flxml::internal { // Struct that contains lookup tables for the parser struct lookup_tables { diff --git a/rapidxml_utils.hpp b/include/flxml/utils.h similarity index 95% rename from rapidxml_utils.hpp rename to include/flxml/utils.h index 5eafa35..9b5d474 100644 --- a/rapidxml_utils.hpp +++ b/include/flxml/utils.h @@ -1,122 +1,122 @@ -#ifndef RAPIDXML_UTILS_HPP_INCLUDED -#define RAPIDXML_UTILS_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful -//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective. - -#include "rapidxml.hpp" -#include -#include -#include -#include - -namespace rapidxml -{ - - //! Represents data loaded from a file - template - class file - { - - public: - - //! Loads file into the memory. Data will be automatically destroyed by the destructor. - //! \param filename Filename to load. - file(const char *filename) - { - using namespace std; - - // Open stream - basic_ifstream stream(filename, ios::binary); - if (!stream) - throw runtime_error(string("cannot open file ") + filename); - stream.unsetf(ios::skipws); - - // Determine stream size - stream.seekg(0, ios::end); - size_t size = stream.tellg(); - stream.seekg(0); - - // Load data and add terminating 0 - m_data.resize(size + 1); - stream.read(&m_data.front(), static_cast(size)); - m_data[size] = 0; - } - - //! Loads file into the memory. Data will be automatically destroyed by the destructor - //! \param stream Stream to load from - file(std::basic_istream &stream) - { - using namespace std; - - // Load data and add terminating 0 - stream.unsetf(ios::skipws); - m_data.assign(istreambuf_iterator(stream), istreambuf_iterator()); - if (stream.fail() || stream.bad()) - throw runtime_error("error reading stream"); - m_data.push_back(0); - } - - //! Gets file data. - //! \return Pointer to data of file. - Ch *data() - { - return &m_data.front(); - } - - //! Gets file data. - //! \return Pointer to data of file. - const Ch *data() const - { - return &m_data.front(); - } - - //! Gets file data size. - //! \return Size of file data, in characters. - std::size_t size() const - { - return m_data.size(); - } - - private: - - std::vector m_data; // File data - - }; - - //! Counts children of node. Time complexity is O(n). - //! \return Number of children of node - template - inline std::size_t count_children(xml_node *node) - { - xml_node *child = node->first_node(); - std::size_t count = 0; - while (child) - { - ++count; - child = child->next_sibling(); - } - return count; - } - - //! Counts attributes of node. Time complexity is O(n). - //! \return Number of attributes of node - template - inline std::size_t count_attributes(xml_node *node) - { - xml_attribute *attr = node->first_attribute(); - std::size_t count = 0; - while (attr) - { - ++count; - attr = attr->next_attribute(); - } - return count; - } - -} - -#endif +#ifndef RAPIDXML_UTILS_HPP_INCLUDED +#define RAPIDXML_UTILS_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful +//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective. + +#include +#include +#include +#include +#include + +namespace flxml +{ + + //! Represents data loaded from a file + template + class file + { + + public: + + //! Loads file into the memory. Data will be automatically destroyed by the destructor. + //! \param filename Filename to load. + file(const char *filename) + { + using namespace std; + + // Open stream + basic_ifstream stream(filename, ios::binary); + if (!stream) + throw runtime_error(string("cannot open file ") + filename); + stream.unsetf(ios::skipws); + + // Determine stream size + stream.seekg(0, ios::end); + size_t size = stream.tellg(); + stream.seekg(0); + + // Load data and add terminating 0 + m_data.resize(size + 1); + stream.read(&m_data.front(), static_cast(size)); + m_data[size] = 0; + } + + //! Loads file into the memory. Data will be automatically destroyed by the destructor + //! \param stream Stream to load from + file(std::basic_istream &stream) + { + using namespace std; + + // Load data and add terminating 0 + stream.unsetf(ios::skipws); + m_data.assign(istreambuf_iterator(stream), istreambuf_iterator()); + if (stream.fail() || stream.bad()) + throw runtime_error("error reading stream"); + m_data.push_back(0); + } + + //! Gets file data. + //! \return Pointer to data of file. + Ch *data() + { + return &m_data.front(); + } + + //! Gets file data. + //! \return Pointer to data of file. + const Ch *data() const + { + return &m_data.front(); + } + + //! Gets file data size. + //! \return Size of file data, in characters. + std::size_t size() const + { + return m_data.size(); + } + + private: + + std::vector m_data; // File data + + }; + + //! Counts children of node. Time complexity is O(n). + //! \return Number of children of node + template + inline std::size_t count_children(xml_node *node) + { + xml_node *child = node->first_node(); + std::size_t count = 0; + while (child) + { + ++count; + child = child->next_sibling(); + } + return count; + } + + //! Counts attributes of node. Time complexity is O(n). + //! \return Number of attributes of node + template + inline std::size_t count_attributes(xml_node *node) + { + xml_attribute *attr = node->first_attribute(); + std::size_t count = 0; + while (attr) + { + ++count; + attr = attr->next_attribute(); + } + return count; + } + +} + +#endif diff --git a/rapidxml_wrappers.hpp b/include/flxml/wrappers.h similarity index 99% rename from rapidxml_wrappers.hpp rename to include/flxml/wrappers.h index 9636402..6ec6214 100644 --- a/rapidxml_wrappers.hpp +++ b/include/flxml/wrappers.h @@ -9,7 +9,7 @@ #include #include -namespace rapidxml { +namespace flxml { // Most of rapidxml was written to use a NUL-terminated Ch * for parsing. // This utility struct wraps a buffer to provide something that // looks mostly like a pointer, deferencing to NUL when it hits the end. diff --git a/include/rapidxml.hpp b/include/rapidxml.hpp new file mode 100644 index 0000000..e70a5eb --- /dev/null +++ b/include/rapidxml.hpp @@ -0,0 +1,12 @@ +// +// Created by dwd on 4/19/25. +// + +#ifndef RAPIDXML_HPP +#define RAPIDXML_HPP + +#include + +namespace rapidxml = flxml; + +#endif //RAPIDXML_HPP diff --git a/include/rapidxml_print.hpp b/include/rapidxml_print.hpp new file mode 100644 index 0000000..89a5a60 --- /dev/null +++ b/include/rapidxml_print.hpp @@ -0,0 +1,12 @@ +// +// Created by dwd on 4/19/25. +// + +#ifndef RAPIDXML_PRINT_HPP +#define RAPIDXML_PRINT_HPP + +#include + +namespace rapidxml = flxml; + +#endif //RAPIDXML_PRINT_HPP diff --git a/CMakeLists.txt b/test/CMakeLists.txt similarity index 53% rename from CMakeLists.txt rename to test/CMakeLists.txt index d0db150..264fbde 100644 --- a/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,60 +1,46 @@ cmake_minimum_required(VERSION 3.24) project(rapidxml) +# Include the Conan toolchain +include(${CMAKE_CURRENT_SOURCE_DIR}/conan_toolchain.cmake) + # GoogleTest requires at least C++14 set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) option(RAPIDXML_PERF_TESTS "Enable (very slow) performance tests" OFF) option(RAPIDXML_SENTRY "Use Sentry (for tests only)" ON) -include(FetchContent) -FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip -) -# Used on Windows -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - -FetchContent_MakeAvailable(googletest) +find_package(GTest) +find_package(flxml CONFIG REQUIRED) if (RAPIDXML_SENTRY) set(SENTRY_BACKEND inproc) - add_subdirectory(sentry-native EXCLUDE_FROM_ALL) + find_package(sentry) endif(RAPIDXML_SENTRY) enable_testing() add_executable(rapidxml-test - test/parse-simple.cpp - rapidxml_iterators.hpp - rapidxml_print.hpp - rapidxml_utils.hpp - rapidxml.hpp - test/manipulations.cpp - test/round-trips.cpp - test/low-level-parse.cpp - test/perf.cpp - rapidxml_wrappers.hpp - test/iterators.cpp - rapidxml_predicates.hpp - test/xpath.cpp - rapidxml_generator.hpp - test/main.cc - rapidxml_predicates.hpp - rapidxml_tables.hpp + src/parse-simple.cpp + src/manipulations.cpp + src/round-trips.cpp + src/low-level-parse.cpp + src/perf.cpp + src/iterators.cpp + src/xpath.cpp + src/main.cc ) target_link_libraries(rapidxml-test PRIVATE GTest::gtest + flxml::flxml ) if(RAPIDXML_SENTRY) - target_link_libraries(rapidxml-test PRIVATE sentry) + target_link_libraries(rapidxml-test PRIVATE sentry-native::sentry-native) target_compile_definitions(rapidxml-test PRIVATE DWD_GTEST_SENTRY=1) endif() target_include_directories(rapidxml-test PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ) -target_compile_options(rapidxml-test PRIVATE -Werror -Wall --coverage -g -O0) -target_link_options(rapidxml-test PRIVATE --coverage -g) if (RAPIDXML_PERF_TESTS) message("Running performance tests") file(DOWNLOAD https://www.w3.org/TR/xml/REC-xml-20081126.xml ${CMAKE_CURRENT_BINARY_DIR}/REC-xml-20081126.xml) diff --git a/test/conanfile.py b/test/conanfile.py new file mode 100644 index 0000000..ac82b80 --- /dev/null +++ b/test/conanfile.py @@ -0,0 +1,31 @@ +from conan import ConanFile +from conan.tools.cmake import CMakeToolchain, CMake, CMakeDeps + +class FLXML(ConanFile): + name = "flxml-test" + settings = "os", "compiler", "build_type", "arch" + test_type = "explicit" + + def configure(self): + self.options["sentry-native"].backend = "inproc" + + def requirements(self): + self.requires(f'flxml/{self.version}') + self.requires("sentry-native/0.7.11") + self.requires("gtest/1.12.1") + + def generate(self): + deps = CMakeDeps(self) + deps.generate() + tc = CMakeToolchain(self) + tc.user_presets_path = False + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + if not self.conf.get("tools.build:skip_test"): + self.run("./rapidxml-test", env="conanrun") diff --git a/sonar-project.properties b/test/sonar-project.properties similarity index 100% rename from sonar-project.properties rename to test/sonar-project.properties diff --git a/test/iterators.cpp b/test/src/iterators.cpp similarity index 84% rename from test/iterators.cpp rename to test/src/iterators.cpp index 141054b..bb269b1 100644 --- a/test/iterators.cpp +++ b/test/src/iterators.cpp @@ -6,12 +6,12 @@ #include #include #include -#include "rapidxml.hpp" +#include TEST(Iterators, Nodes) { std::string xml = ""; - rapidxml::xml_document<> doc; - doc.parse(xml); + flxml::xml_document<> doc; + doc.parse(xml); int i = 0; for (auto & child : doc.first_node()->children()) { ++i; @@ -32,8 +32,8 @@ TEST(Iterators, Nodes) { TEST(Iterators, Attributes) { std::string xml = R"()"; - rapidxml::xml_document<> doc; - doc.parse(xml); + flxml::xml_document<> doc; + doc.parse(xml); int i = 0; for (auto & child : doc.first_node()->attributes()) { ++i; @@ -54,8 +54,8 @@ TEST(Iterators, Attributes) { TEST(Predicates, Nodes) { std::string xml = ""; - rapidxml::xml_document<> doc; - doc.parse(xml); + flxml::xml_document<> doc; + doc.parse(xml); auto r = doc.first_node()->children(); for (auto const & child : r | std::ranges::views::filter([](auto const & n) { return n.name() == "two"; })) { EXPECT_EQ(child.name(), "two"); @@ -68,9 +68,9 @@ TEST(Predicates, Nodes) { TEST(Predicates, AllNodes) { std::string xml = ""; - rapidxml::xml_document<> doc; - doc.parse(xml); - auto it = rapidxml::descendant_iterator<>(doc.first_node()); + flxml::xml_document<> doc; + doc.parse(xml); + auto it = flxml::descendant_iterator<>(doc.first_node()); EXPECT_EQ(it->name(), "one"); ++it; EXPECT_EQ(it->name(), "two"); @@ -88,9 +88,9 @@ TEST(Predicates, AllNodes) { TEST(Predicates, AllNodesRev) { std::string xml = ""; - rapidxml::xml_document<> doc; - doc.parse(xml); - auto it = rapidxml::descendant_iterator<>(doc.first_node()); + flxml::xml_document<> doc; + doc.parse(xml); + auto it = flxml::descendant_iterator<>(doc.first_node()); EXPECT_EQ(it->name(), "one"); ++it; EXPECT_EQ(it->name(), "two"); @@ -116,8 +116,8 @@ TEST(Predicates, AllNodesRev) { TEST(Predicates, Attributes) { std::string xml = R"()"; - rapidxml::xml_document<> doc; - doc.parse(xml); + flxml::xml_document<> doc; + doc.parse(xml); auto r = doc.first_node()->attributes(); for (auto const & child : r | std::ranges::views::filter([](auto const & n) { return n.name() == "two"; })) { EXPECT_EQ(child.name(), "two"); diff --git a/test/low-level-parse.cpp b/test/src/low-level-parse.cpp similarity index 59% rename from test/low-level-parse.cpp rename to test/src/low-level-parse.cpp index df2fc75..208a9b4 100644 --- a/test/low-level-parse.cpp +++ b/test/src/low-level-parse.cpp @@ -3,10 +3,10 @@ // #include -#include "rapidxml.hpp" +#include TEST(Constants, Empty) { - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; auto empty = doc.nullstr(); EXPECT_EQ(empty, ""); EXPECT_EQ(empty.size(), 0); @@ -16,7 +16,7 @@ TEST(Predicates, Skip) { std::string test_data{""}; auto start = test_data.c_str(); auto end = ++start; - rapidxml::xml_document<>::skip::element_name_pred,0>(end); + flxml::xml_document<>::skip::element_name_pred,0>(end); EXPECT_EQ(*end, '/'); std::string_view sv({start, end}); EXPECT_EQ(sv, "simple"); @@ -24,9 +24,9 @@ TEST(Predicates, Skip) { TEST(PredicateBuffer, Skip) { std::string test_data{""}; - auto start = rapidxml::buffer_ptr(test_data); + auto start = flxml::buffer_ptr(test_data); auto end = ++start; - rapidxml::xml_document<>::skip::element_name_pred,0>(end); + flxml::xml_document<>::skip::element_name_pred,0>(end); EXPECT_EQ(*end, '/'); std::string_view sv({start, end}); EXPECT_EQ(sv, "simple"); @@ -35,37 +35,37 @@ TEST(PredicateBuffer, Skip) { TEST(Predicates, SkipAndExpand) { std::string test_data{"&hello;<"}; char * start = const_cast(test_data.c_str()); - auto end = rapidxml::xml_document<>::skip_and_expand_character_refs< - rapidxml::xml_document<>::text_pred, - rapidxml::xml_document<>::text_pure_with_ws_pred, - rapidxml::parse_no_entity_translation>(start); + auto end = flxml::xml_document<>::skip_and_expand_character_refs< + flxml::xml_document<>::text_pred, + flxml::xml_document<>::text_pure_with_ws_pred, + flxml::parse_no_entity_translation>(start); EXPECT_EQ(*end, '<'); } TEST(Predicates, SkipAndExpandShort) { std::string test_data{"&hello;"}; char * start = const_cast(test_data.c_str()); - auto end = rapidxml::xml_document<>::skip_and_expand_character_refs< - rapidxml::xml_document<>::text_pred, - rapidxml::xml_document<>::text_pure_with_ws_pred, - rapidxml::parse_no_entity_translation>(start); + auto end = flxml::xml_document<>::skip_and_expand_character_refs< + flxml::xml_document<>::text_pred, + flxml::xml_document<>::text_pure_with_ws_pred, + flxml::parse_no_entity_translation>(start); EXPECT_EQ(*end, '\0'); } TEST(Predicates, SkipAndExpandShorter) { std::string test_data{"&hell"}; char * start = const_cast(test_data.c_str()); - auto end = rapidxml::xml_document<>::skip_and_expand_character_refs< - rapidxml::xml_document<>::text_pred, - rapidxml::xml_document<>::text_pure_with_ws_pred, - rapidxml::parse_no_entity_translation>(start); + auto end = flxml::xml_document<>::skip_and_expand_character_refs< + flxml::xml_document<>::text_pred, + flxml::xml_document<>::text_pure_with_ws_pred, + flxml::parse_no_entity_translation>(start); EXPECT_EQ(*end, '\0'); } TEST(ParseFns, ParseBom) { std::string test_data{"\xEF\xBB\xBF"}; char *start = const_cast(test_data.c_str()); - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; doc.parse_bom<0>(start); EXPECT_EQ(*start, '<'); } @@ -73,7 +73,7 @@ TEST(ParseFns, ParseBom) { TEST(ParseFns, ParseBomShort) { std::string test_data{"\xEF\xBB\xBF"}; char *start = const_cast(test_data.c_str()); - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; doc.parse_bom<0>(start); EXPECT_EQ(*start, '\0'); } @@ -81,7 +81,7 @@ TEST(ParseFns, ParseBomShort) { TEST(ParseFns, ParseBomShorter) { std::string test_data{"\xEF\xBB"}; char *start = const_cast(test_data.c_str()); - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; doc.parse_bom<0>(start); EXPECT_EQ(*start, '\xEF'); } diff --git a/test/main.cc b/test/src/main.cc similarity index 100% rename from test/main.cc rename to test/src/main.cc diff --git a/test/manipulations.cpp b/test/src/manipulations.cpp similarity index 78% rename from test/manipulations.cpp rename to test/src/manipulations.cpp index d1b4c4b..16105b0 100644 --- a/test/manipulations.cpp +++ b/test/src/manipulations.cpp @@ -4,20 +4,20 @@ #include -#include "rapidxml.hpp" -#include "rapidxml_print.hpp" +#include +#include namespace { - auto print(rapidxml::xml_document<> & doc) { + auto print(flxml::xml_document<> & doc) { std::string output; - rapidxml::print(std::back_inserter(output), *doc.first_node()); + flxml::print(std::back_inserter(output), *doc.first_node()); return output; } } TEST(Create, Node) { - rapidxml::xml_document<> doc; - auto node = doc.allocate_node(rapidxml::node_element, "fish", "cakes"); + flxml::xml_document<> doc; + auto node = doc.allocate_node(flxml::node_element, "fish", "cakes"); doc.append_node(node); EXPECT_EQ( @@ -27,8 +27,8 @@ TEST(Create, Node) { } TEST(Create, NodeEmpty) { - rapidxml::xml_document<> doc; - auto node = doc.allocate_node(rapidxml::node_element, "fish"); + flxml::xml_document<> doc; + auto node = doc.allocate_node(flxml::node_element, "fish"); doc.append_node(node); EXPECT_EQ( @@ -38,8 +38,8 @@ TEST(Create, NodeEmpty) { } TEST(Create, Node2) { - rapidxml::xml_document<> doc; - auto node = doc.allocate_node(rapidxml::node_element, "fish", "cakes"); + flxml::xml_document<> doc; + auto node = doc.allocate_node(flxml::node_element, "fish", "cakes"); doc.append_node(node); EXPECT_EQ( @@ -55,8 +55,8 @@ std::string const & fn() { } TEST(Create, NodeAttr) { - rapidxml::xml_document<> doc; - auto node = doc.allocate_node(rapidxml::node_element, "fish", "cakes"); + flxml::xml_document<> doc; + auto node = doc.allocate_node(flxml::node_element, "fish", "cakes"); auto haddock = doc.allocate_attribute("id", "haddock"); node->append_attribute(haddock); doc.append_node(node); @@ -67,7 +67,7 @@ TEST(Create, NodeAttr) { ); const std::string & s2 = fn(); - const rapidxml::xml_attribute<>::view_type & sv{s2}; + const flxml::xml_attribute<>::view_type & sv{s2}; auto tuna = doc.allocate_attribute("not-id", fn()); // These check that the same buffer is being used throughout, instead of creating temporaries. diff --git a/test/parse-simple.cpp b/test/src/parse-simple.cpp similarity index 83% rename from test/parse-simple.cpp rename to test/src/parse-simple.cpp index dd2c64b..7eea213 100644 --- a/test/parse-simple.cpp +++ b/test/src/parse-simple.cpp @@ -3,11 +3,11 @@ // #include -#include +#include TEST(Parser, SingleElement) { char doc_text[] = ""; - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; doc.parse<0>(doc_text); auto node = doc.first_node(); @@ -19,8 +19,8 @@ TEST(Parser, SingleElement) { TEST(Parser, DefaultElementNS) { char doc_text[] = ""; - rapidxml::xml_document<> doc; - doc.parse(doc_text); + flxml::xml_document<> doc; + doc.parse(doc_text); auto node = doc.first_node(); EXPECT_NE(nullptr, node); @@ -32,11 +32,11 @@ TEST(Parser, DefaultElementNS) { EXPECT_EQ(child->xmlns(), "this"); doc.validate(); auto no_node = child->next_sibling(); - EXPECT_THROW(no_node->xmlns(), rapidxml::no_such_node); + EXPECT_THROW(no_node->xmlns(), flxml::no_such_node); } TEST(Parser, UnboundPrefix) { - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; char doc_text[] = ""; doc.parse<0>(doc_text); @@ -44,12 +44,12 @@ TEST(Parser, UnboundPrefix) { EXPECT_EQ("single-element", node->name()); EXPECT_THROW( doc.validate(), - rapidxml::element_xmlns_unbound + flxml::element_xmlns_unbound ); } TEST(Parser, DuplicateAttribute) { - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; char doc_text[] = ""; doc.parse<0>(doc_text); @@ -57,12 +57,12 @@ TEST(Parser, DuplicateAttribute) { EXPECT_EQ("single-element", node->name()); EXPECT_THROW( doc.validate(), - rapidxml::duplicate_attribute + flxml::duplicate_attribute ); } TEST(Parser, UnboundAttrPrefix) { - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; char doc_text[] = ""; doc.parse<0>(doc_text); @@ -71,17 +71,17 @@ TEST(Parser, UnboundAttrPrefix) { auto attr = node->first_attribute(); EXPECT_THROW( doc.validate(), - rapidxml::attr_xmlns_unbound + flxml::attr_xmlns_unbound ); EXPECT_THROW( attr->xmlns(), - rapidxml::attr_xmlns_unbound + flxml::attr_xmlns_unbound ); } TEST(Parser, DuplicateAttrPrefix) { - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; char doc_text[] = ""; doc.parse<0>(doc_text); @@ -89,13 +89,13 @@ TEST(Parser, DuplicateAttrPrefix) { assert(std::string("single-element") == node->name()); EXPECT_THROW( doc.validate(), - rapidxml::duplicate_attribute + flxml::duplicate_attribute ); } TEST(Parser, Xmlns) { - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; char doc_text[] = ""; doc.parse<0>(doc_text); @@ -107,7 +107,7 @@ TEST(Parser, Xmlns) { } TEST(Parser, ChildXmlns) { - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; char doc_text[] = ""; doc.parse<0>(doc_text); @@ -150,18 +150,18 @@ TEST(Parser, ChildXmlns) { } TEST(Parser, HandleEOF){ - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; char doc_text[] = ""; EXPECT_THROW( doc.parse<0>(doc_text), - rapidxml::eof_error + flxml::eof_error ); } TEST(ParseOptions, Fastest) { - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; char doc_text[] = ""; - doc.parse(doc_text); + doc.parse(doc_text); auto node = doc.first_node(); EXPECT_EQ("single", node->name()); @@ -180,9 +180,9 @@ TEST(ParseOptions, Fastest) { } TEST(ParseOptions, OpenOnly) { - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; char doc_text[] = ""; - doc.parse(doc_text); + doc.parse(doc_text); auto node = doc.first_node(); EXPECT_EQ("single", node->name()); @@ -192,9 +192,9 @@ TEST(ParseOptions, OpenOnly) { } TEST(ParseOptions, ParseOne) { - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; char doc_text[] = "Hello!"; - const char * text = doc.parse(doc_text); + const char * text = doc.parse(doc_text); { auto node = doc.first_node(); @@ -208,8 +208,8 @@ TEST(ParseOptions, ParseOne) { doc.validate(); unsigned counter = 0; while (*text) { - rapidxml::xml_document<> subdoc; - text = subdoc.parse(text, &doc); + flxml::xml_document<> subdoc; + text = subdoc.parse(text, &doc); auto node = subdoc.first_node(); ASSERT_NE(nullptr, node); switch(++counter) { @@ -229,9 +229,9 @@ TEST(ParseOptions, ParseOne) { } TEST(ParseOptions, OpenOnlyFastest) { - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; char doc_text[] = "Hello!"; - const char * text = doc.parse(doc_text); + const char * text = doc.parse(doc_text); { auto node = doc.first_node(); @@ -245,8 +245,8 @@ TEST(ParseOptions, OpenOnlyFastest) { doc.validate(); unsigned counter = 0; while (*text) { - rapidxml::xml_document<> subdoc; - text = subdoc.parse(text, &doc); + flxml::xml_document<> subdoc; + text = subdoc.parse(text, &doc); auto node = subdoc.first_node(); ASSERT_NE(nullptr, node); switch(++counter) { @@ -267,38 +267,38 @@ TEST(ParseOptions, OpenOnlyFastest) { TEST(Parser_Emoji, Single) { std::string foo{"'"}; - rapidxml::xml_document<> doc; - doc.parse(foo); + flxml::xml_document<> doc; + doc.parse(foo); EXPECT_EQ("'", doc.first_node()->value()); } TEST(Parser_Emoji, SingleUni) { std::string foo{"Ӓ"}; - rapidxml::xml_document<> doc; - doc.parse(foo); + flxml::xml_document<> doc; + doc.parse(foo); EXPECT_EQ("\xD3\x92", doc.first_node()->value()); } TEST(Parser_Emoji, SingleEmoji) { std::string foo{"😀"}; - rapidxml::xml_document<> doc; - doc.parse(foo); + flxml::xml_document<> doc; + doc.parse(foo); EXPECT_EQ("\xF0\x9F\x98\x80", doc.first_node()->value()); EXPECT_EQ(4, doc.first_node()->value().size()); } TEST(Parser_Emoji, SingleEmojiReuse) { std::string bar("Sir I bear a rhyme excelling in mystic verse and magic spelling 😀"); - rapidxml::xml_document<> doc; - rapidxml::xml_document<> parent_doc; - parent_doc.parse(""); - doc.parse(bar, &parent_doc); + flxml::xml_document<> doc; + flxml::xml_document<> parent_doc; + parent_doc.parse(""); + doc.parse(bar, &parent_doc); EXPECT_EQ("Sir I bear a rhyme excelling in mystic verse and magic spelling \xF0\x9F\x98\x80", doc.first_node()->value()); auto doc_a = doc.first_node()->document(); doc.first_node()->value(doc_a->allocate_string("Sausages are the loneliest fruit, and are but one of the strange things I have witnessed in my long and interesting life.")); EXPECT_EQ("Sausages are the loneliest fruit, and are but one of the strange things I have witnessed in my long and interesting life.", doc.first_node()->value()); bar = "😀"; - doc.parse(bar, &parent_doc); + doc.parse(bar, &parent_doc); EXPECT_EQ("\xF0\x9F\x98\x80", doc.first_node()->value()); EXPECT_EQ(4, doc.first_node()->value().size()); } diff --git a/test/perf.cpp b/test/src/perf.cpp similarity index 77% rename from test/perf.cpp rename to test/src/perf.cpp index a29b95a..c666590 100644 --- a/test/perf.cpp +++ b/test/src/perf.cpp @@ -2,13 +2,13 @@ // Created by dave on 07/07/2024. // -#include -#include +#include +#include #include #include -#include "rapidxml_print.hpp" -#include "rapidxml_iterators.hpp" +#include "flxml/print.h" +#include "flxml/iterators.h" const auto xml_sample_file = "REC-xml-20081126.xml"; @@ -24,13 +24,13 @@ TEST(Perf, Parse) { using std::chrono::microseconds; PERF_TEST(); - rapidxml::file source(xml_sample_file); + flxml::file source(xml_sample_file); std::vector timings; for (auto i = 0; i != 1000; ++i) { - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; auto t1 = high_resolution_clock::now(); - doc.parse(source.data()); + doc.parse(source.data()); auto t2 = high_resolution_clock::now(); auto ms_int = duration_cast(t2 - t1); timings.push_back(ms_int.count()); @@ -48,14 +48,14 @@ TEST(Perf, Parse2) { using std::chrono::microseconds; PERF_TEST(); - rapidxml::file source(xml_sample_file); + flxml::file source(xml_sample_file); std::vector timings; for (auto i = 0; i != 1000; ++i) { - rapidxml::xml_document<> doc; + flxml::xml_document<> doc; std::string_view sv{source.data(), source.size() - 1}; // Drop the NUL. auto t1 = high_resolution_clock::now(); - doc.parse(sv); + doc.parse(sv); auto t2 = high_resolution_clock::now(); auto ms_int = duration_cast(t2 - t1); timings.push_back(ms_int.count()); @@ -73,15 +73,15 @@ TEST(Perf, PrintClean) { using std::chrono::microseconds; PERF_TEST(); - rapidxml::file source(xml_sample_file); + flxml::file source(xml_sample_file); std::vector timings; - rapidxml::xml_document<> doc; - doc.parse(source.data()); + flxml::xml_document<> doc; + doc.parse(source.data()); for (auto i = 0; i != 1000; ++i) { std::string output; auto t1 = high_resolution_clock::now(); - rapidxml::print(std::back_inserter(output), doc); + flxml::print(std::back_inserter(output), doc); auto t2 = high_resolution_clock::now(); auto ms_int = duration_cast(t2 - t1); timings.push_back(ms_int.count()); @@ -99,19 +99,19 @@ TEST(Perf, PrintDirty) { using std::chrono::microseconds; PERF_TEST(); - rapidxml::file source(xml_sample_file); + flxml::file source(xml_sample_file); std::vector timings; - rapidxml::xml_document<> doc_o; - doc_o.parse(source.data()); - rapidxml::xml_document<> doc; - for (auto & child : rapidxml::children(doc_o)) { + flxml::xml_document<> doc_o; + doc_o.parse(source.data()); + flxml::xml_document<> doc; + for (auto & child : flxml::children(doc_o)) { doc.append_node(doc.clone_node(&child, true)); } for (auto i = 0; i != 1000; ++i) { std::string output; auto t1 = high_resolution_clock::now(); - rapidxml::print(std::back_inserter(output), doc); + flxml::print(std::back_inserter(output), doc); auto t2 = high_resolution_clock::now(); auto ms_int = duration_cast(t2 - t1); timings.push_back(ms_int.count()); diff --git a/test/round-trips.cpp b/test/src/round-trips.cpp similarity index 82% rename from test/round-trips.cpp rename to test/src/round-trips.cpp index 3e2b516..1381b38 100644 --- a/test/round-trips.cpp +++ b/test/src/round-trips.cpp @@ -3,14 +3,13 @@ // #include -#include "rapidxml.hpp" -#include "rapidxml_print.hpp" -#include "rapidxml_iterators.hpp" +#include +#include namespace { - auto print(rapidxml::xml_document<> & doc) { + auto print(flxml::xml_document<> & doc) { std::string output; - rapidxml::print(std::back_inserter(output), doc, rapidxml::print_no_indenting); + flxml::print(std::back_inserter(output), doc, flxml::print_no_indenting); return output; } } @@ -18,8 +17,8 @@ namespace { TEST(RoundTrip, Simple) { const char input[] = ""; std::vector buffer{input, input + sizeof(input)}; - rapidxml::xml_document<> doc; - doc.parse(buffer.data()); + flxml::xml_document<> doc; + doc.parse(buffer.data()); auto output = print(doc); // Have we parsed correctly? EXPECT_EQ(input, output); @@ -30,8 +29,8 @@ TEST(RoundTrip, Simple) { TEST(RoundTrip, SimpleMod) { const char input[] = ""; std::vector buffer{input, input + sizeof(input)}; - rapidxml::xml_document<> doc; - doc.parse(buffer.data()); + flxml::xml_document<> doc; + doc.parse(buffer.data()); auto output = print(doc); // Have we parsed correctly? EXPECT_EQ(input, output); @@ -63,7 +62,7 @@ TEST(RoundTrip, SimpleMod) { EXPECT_EQ(check->name(), name); EXPECT_EQ(check->name().data(), name.data()); EXPECT_EQ(output3, "the otheranother'the otherthe otherthe otherlast time"); - rapidxml::xml_document<> doc2; + flxml::xml_document<> doc2; doc2.clone_node(doc.first_node(), true); auto output4 = print(doc); EXPECT_EQ(output3, output4); @@ -72,12 +71,12 @@ TEST(RoundTrip, SimpleMod) { TEST(RoundTrip, SimpleApos) { const char input[] = ""; std::vector buffer{input, input + sizeof(input)}; - rapidxml::xml_document<> doc; - doc.parse(buffer.data()); + flxml::xml_document<> doc; + doc.parse(buffer.data()); auto output = print(doc); // Have we parsed correctly? - rapidxml::xml_document<> doc2; - for (auto & child : rapidxml::children(doc)) { + flxml::xml_document<> doc2; + for (auto & child : flxml::children(doc)) { doc2.append_node(doc2.clone_node(&child, true)); } EXPECT_EQ(input, print(doc2)); @@ -90,13 +89,13 @@ TEST(RoundTrip, SimpleApos2) { const char input[] = ""; const char expected[] = ""; std::vector buffer{input, input + sizeof(input)}; - rapidxml::xml_document<> doc; - doc.parse(buffer.data()); + flxml::xml_document<> doc; + doc.parse(buffer.data()); auto output = print(doc); EXPECT_EQ(doc.first_node()->first_attribute()->value(), "'"); // Have we parsed correctly? - rapidxml::xml_document<> doc2; - for (auto & child : rapidxml::children(doc)) { + flxml::xml_document<> doc2; + for (auto & child : flxml::children(doc)) { doc2.append_node(doc2.clone_node(&child, true)); } EXPECT_EQ(expected, print(doc2)); @@ -109,14 +108,14 @@ TEST(RoundTrip, SimpleLtBody) { const char input[] = "<"; const char expected[] = "<"; std::vector buffer{input, input + sizeof(input)}; - rapidxml::xml_document<> doc; - doc.parse(buffer.data()); + flxml::xml_document<> doc; + doc.parse(buffer.data()); auto output = print(doc); EXPECT_EQ(doc.first_node()->value(), "<"); EXPECT_EQ(doc.first_node()->first_attribute()->value(), "'"); // Have we parsed correctly? - rapidxml::xml_document<> doc2; - for (auto & child : rapidxml::children(doc)) { + flxml::xml_document<> doc2; + for (auto & child : flxml::children(doc)) { doc2.append_node(doc2.clone_node(&child, true)); } EXPECT_EQ(expected, print(doc2)); @@ -130,8 +129,8 @@ TEST(RoundTrip, MutateBody) { const char expected[] = "<"; const char expected2[] = "new value"; std::vector buffer{input, input + sizeof(input)}; - rapidxml::xml_document<> doc; - doc.parse(buffer.data()); + flxml::xml_document<> doc; + doc.parse(buffer.data()); auto output = print(doc); EXPECT_EQ(expected, output); // Have we mutated the underlying buffer? @@ -146,11 +145,11 @@ TEST(RoundTrip, Everything) { const char input[] = ""; const char expected[] = ""; std::vector buffer{input, input + sizeof(input)}; - rapidxml::xml_document<> doc; - doc.parse(buffer.data()); + flxml::xml_document<> doc; + doc.parse(buffer.data()); auto output = print(doc); - rapidxml::xml_document<> doc2; - for (auto & child : rapidxml::children(doc)) { + flxml::xml_document<> doc2; + for (auto & child : flxml::children(doc)) { doc2.append_node(doc2.clone_node(&child, true)); } EXPECT_EQ(expected, print(doc2)); @@ -164,12 +163,12 @@ TEST(RoundTrip, EverythingStream) { const char input[] = ""; const char expected[] = "\n\n\n\t\n\n\n"; std::vector buffer{input, input + sizeof(input) - 1}; - rapidxml::xml_document<> doc; - doc.parse(buffer); + flxml::xml_document<> doc; + doc.parse(buffer); std::stringstream ss1; ss1 << doc; auto output = ss1.str(); - rapidxml::xml_document<> doc2; + flxml::xml_document<> doc2; for (auto & child : doc.children()) { doc2.append_node(doc2.clone_node(&child, true)); } diff --git a/test/xpath.cpp b/test/src/xpath.cpp similarity index 61% rename from test/xpath.cpp rename to test/src/xpath.cpp index abe7bc7..92c27b6 100644 --- a/test/xpath.cpp +++ b/test/src/xpath.cpp @@ -3,12 +3,12 @@ // #include -#include "rapidxml_predicates.hpp" +#include TEST(XPath, parse) { std::string xpath_string = "//"; std::string_view sv{xpath_string}; - auto xp = rapidxml::xpath<>::parse(sv); + auto xp = flxml::xpath<>::parse(sv); EXPECT_EQ(sv.length(), 0); EXPECT_NE(xp.get(), nullptr); EXPECT_EQ(xp->chain().size(), 1); @@ -17,7 +17,7 @@ TEST(XPath, parse) { TEST(XPath, parse2) { std::string xpath_string = "//child"; std::string_view sv{xpath_string}; - auto xp = rapidxml::xpath<>::parse(sv); + auto xp = flxml::xpath<>::parse(sv); EXPECT_EQ(sv.length(), 0); EXPECT_NE(xp.get(), nullptr); EXPECT_EQ(xp->chain().size(), 2); @@ -26,7 +26,7 @@ TEST(XPath, parse2) { TEST(XPath, parse1) { std::string xpath_string = "/child"; std::string_view sv{xpath_string}; - auto xp = rapidxml::xpath<>::parse(sv); + auto xp = flxml::xpath<>::parse(sv); EXPECT_EQ(sv.length(), 0); EXPECT_NE(xp.get(), nullptr); EXPECT_EQ(xp->chain().size(), 2); @@ -35,7 +35,7 @@ TEST(XPath, parse1) { TEST(XPath, parse3) { std::string xpath_string = "//child[another/element]/something"; std::string_view sv{xpath_string}; - auto xp = rapidxml::xpath<>::parse(sv); + auto xp = flxml::xpath<>::parse(sv); EXPECT_EQ(sv.length(), 0); EXPECT_NE(xp.get(), nullptr); EXPECT_EQ(xp->chain().size(), 4); @@ -47,7 +47,7 @@ TEST(XPath, parse4) { std::string xpath_string = ""; std::string_view sv{xpath_string}; EXPECT_THROW( - rapidxml::xpath<>::parse(sv), + flxml::xpath<>::parse(sv), std::runtime_error ); } @@ -56,7 +56,7 @@ TEST(XPath, parse4) { TEST(XPath, parse_attr) { std::string xpath_string = "//child[@foo='bar']/something"; std::string_view sv{xpath_string}; - auto xp = rapidxml::xpath<>::parse(sv); + auto xp = flxml::xpath<>::parse(sv); EXPECT_EQ(sv.length(), 0); EXPECT_NE(xp.get(), nullptr); EXPECT_EQ(xp->chain().size(), 4); @@ -67,7 +67,7 @@ TEST(XPath, parse_attr) { TEST(XPath, parse_text) { std::string xpath_string = "//child[text()='bar']/something"; std::string_view sv{xpath_string}; - auto xp = rapidxml::xpath<>::parse(sv); + auto xp = flxml::xpath<>::parse(sv); EXPECT_EQ(sv.length(), 0); EXPECT_NE(xp.get(), nullptr); EXPECT_EQ(xp->chain().size(), 4); @@ -76,44 +76,44 @@ TEST(XPath, parse_text) { } TEST(XPathFirst, simple_all) { - rapidxml::xml_document<> doc; - doc.parse(""); + flxml::xml_document<> doc; + doc.parse(""); std::string xpath = "//"; std::string_view sv{xpath}; - auto xp = rapidxml::xpath<>::parse(sv); + auto xp = flxml::xpath<>::parse(sv); auto r = xp->first(doc); ASSERT_TRUE(r); - EXPECT_EQ(r->type(), rapidxml::node_type::node_document); + EXPECT_EQ(r->type(), flxml::node_type::node_document); } TEST(XPathFirst, simple_any) { - rapidxml::xml_document<> doc; - doc.parse(""); + flxml::xml_document<> doc; + doc.parse(""); std::string xpath = "//child"; std::string_view sv{xpath}; - auto xp = rapidxml::xpath<>::parse(sv); + auto xp = flxml::xpath<>::parse(sv); auto r = xp->first(doc); ASSERT_TRUE(r); EXPECT_EQ(r->name(), "child"); } TEST(XPathFirst, simple_sub) { - rapidxml::xml_document<> doc; - doc.parse(""); + flxml::xml_document<> doc; + doc.parse(""); std::string xpath = "//[child]"; std::string_view sv{xpath}; - auto xp = rapidxml::xpath<>::parse(sv); + auto xp = flxml::xpath<>::parse(sv); auto r = xp->first(doc); ASSERT_TRUE(r); EXPECT_EQ(r->name(), "simple"); } TEST(XPathFirst, simple_attr) { - rapidxml::xml_document<> doc; - doc.parse("foobar"); + flxml::xml_document<> doc; + doc.parse("foobar"); std::string xpath = "//child[@attr='val2']"; std::string_view sv{xpath}; - auto xp = rapidxml::xpath<>::parse(sv); + auto xp = flxml::xpath<>::parse(sv); auto r = xp->first(doc); ASSERT_TRUE(r); EXPECT_EQ(r->name(), "child"); @@ -121,9 +121,9 @@ TEST(XPathFirst, simple_attr) { } TEST(XPathFirst, simple_text) { - rapidxml::xml_document<> doc; - doc.parse("foobar"); - auto xp = rapidxml::xpath<>::parse("//child[text()='bar']"); + flxml::xml_document<> doc; + doc.parse("foobar"); + auto xp = flxml::xpath<>::parse("//child[text()='bar']"); auto r = xp->first(doc); ASSERT_TRUE(r); EXPECT_EQ(r->name(), "child"); @@ -131,9 +131,9 @@ TEST(XPathFirst, simple_text) { } TEST(XPathNS, simple_text) { - rapidxml::xml_document<> doc; - doc.parse("foobar"); - auto xp = rapidxml::xpath<>::parse("//child[text()='bar']"); + flxml::xml_document<> doc; + doc.parse("foobar"); + auto xp = flxml::xpath<>::parse("//child[text()='bar']"); auto r = xp->first(doc); ASSERT_TRUE(r); EXPECT_EQ(r->name(), "child"); @@ -141,13 +141,13 @@ TEST(XPathNS, simple_text) { } TEST(XPathNS, xmlns_text) { - rapidxml::xml_document<> doc; - doc.parse("foobar"); + flxml::xml_document<> doc; + doc.parse("foobar"); std::map xmlns = { {"x1", "p2"}, {"x2", "p1"} }; - auto xp = rapidxml::xpath<>::parse(xmlns,"//x1:child[text()='bar']"); + auto xp = flxml::xpath<>::parse(xmlns,"//x1:child[text()='bar']"); auto r = xp->first(doc); ASSERT_TRUE(r); EXPECT_EQ(r->name(), "child"); @@ -155,13 +155,13 @@ TEST(XPathNS, xmlns_text) { } TEST(XPathNS, xmlns_both) { - rapidxml::xml_document<> doc; - doc.parse("foobar"); + flxml::xml_document<> doc; + doc.parse("foobar"); std::map xmlns = { {"x1", "p2"}, {"x2", "p1"} }; - auto xp = rapidxml::xpath<>::parse(xmlns,"//x1:child[text()='bar'][@attr='val2']"); + auto xp = flxml::xpath<>::parse(xmlns,"//x1:child[text()='bar'][@attr='val2']"); auto r = xp->first(doc); ASSERT_TRUE(r); EXPECT_EQ(r->name(), "child"); @@ -169,13 +169,13 @@ TEST(XPathNS, xmlns_both) { } TEST(XPathNS, xmlns_text_miss) { - rapidxml::xml_document<> doc; - doc.parse("foobar"); + flxml::xml_document<> doc; + doc.parse("foobar"); std::map xmlns = { {"x1", "p2"}, {"x2", "p1"} }; - auto xp = rapidxml::xpath<>::parse(xmlns,"//x2:child[text()='bar']"); + auto xp = flxml::xpath<>::parse(xmlns,"//x2:child[text()='bar']"); auto r = xp->first(doc); ASSERT_FALSE(r); }