# Program Listing for File xpath.hpp

↰ Return to documentation for file (`zeem/xpath.hpp`)

    /*-
     * SPDX-License-Identifier: BSD-2-Clause
     *
     * Copyright (c) 2024 Maarten L. Hekkelman
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer
     * 2. Redistributions in binary form must reproduce the above copyright notice,
     *    this list of conditions and the following disclaimer in the documentation
     *    and/or other materials provided with the distribution.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */

    #pragma once

    #include <memory>
    #include <string>
    #include <string_view>
    #include <type_traits>
    #include <vector>

    namespace zeem
    {

    class node;

    // --------------------------------------------------------------------

    class context final
    {
      public:
        context();

        context(const context &ctxt) = default;

        context(context &&ctxt) noexcept
        {
            std::swap(m_impl, ctxt.m_impl);
        }

        context &operator=(context ctxt)
        {
            std::swap(m_impl, ctxt.m_impl);
            return *this;
        }

        void set(const std::string &name, std::string value);

        void set(const std::string &name, double value);

        template <typename T>
            requires std::is_same_v<T, std::string> or std::is_same_v<T, double>
        T get(std::string name);

      private:
        friend class xpath;

        std::shared_ptr<struct context_imp> m_impl;
    };

    // --------------------------------------------------------------------

    class xpath final
    {
      public:
        explicit xpath(std::string_view path);

        xpath(const xpath &rhs) = default;

        xpath(xpath &&rhs) noexcept
        {
            std::swap(m_impl, rhs.m_impl);
        }

        xpath &operator=(xpath xp)
        {
            std::swap(m_impl, xp.m_impl);
            return *this;
        }

        template <typename T>
        [[nodiscard]] std::vector<T *> evaluate(const node &root, const context &ctxt = {}) const;

        bool matches(const node *n, const context &ctxt = {}) const;

      private:
        std::shared_ptr<class expression> m_impl;
    };

    } // namespace zeem