| /** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #pragma once |
| |
| #include <string_view> |
| #include <tuple> |
| #include <optional> |
| #include <string> |
| #include <memory> |
| #include <utility> |
| #include "nonstd/expected.hpp" |
| #include "utils/StringUtils.h" |
| #include "utils/gsl.h" |
| |
| namespace org::apache::nifi::minifi::core::flow { |
| |
| class Node { |
| public: |
| struct Cursor { |
| int line{0}; |
| int column{0}; |
| int pos{0}; |
| }; |
| |
| class Iterator { |
| friend class Node; |
| public: |
| class Value; |
| |
| class IteratorImpl { |
| public: |
| virtual IteratorImpl& operator++() = 0; |
| virtual bool operator==(const IteratorImpl& other) const = 0; |
| virtual Value operator*() const = 0; |
| bool operator!=(const IteratorImpl& other) const {return !(*this == other);} |
| |
| virtual std::unique_ptr<IteratorImpl> clone() const = 0; |
| virtual ~IteratorImpl() = default; |
| std::string path_; |
| }; |
| |
| Iterator& operator++() { |
| impl_->operator++(); |
| ++idx_; |
| return *this; |
| } |
| |
| explicit Iterator(std::unique_ptr<IteratorImpl> impl) : impl_(std::move(impl)) {} |
| Iterator(const Iterator& other): impl_(other.impl_->clone()) {} |
| Iterator(Iterator&&) = default; |
| Iterator& operator=(const Iterator& other) { |
| if (this == &other) { |
| return *this; |
| } |
| impl_ = other.impl_->clone(); |
| return *this; |
| } |
| Iterator& operator=(Iterator&&) = default; |
| |
| bool operator==(const Iterator& other) const {return impl_->operator==(*other.impl_);} |
| bool operator!=(const Iterator& other) const {return !(*this == other);} |
| |
| Value operator*() const; |
| |
| private: |
| std::unique_ptr<IteratorImpl> impl_; |
| int idx_{0}; |
| }; |
| |
| class NodeImpl { |
| public: |
| virtual explicit operator bool() const = 0; |
| virtual bool isSequence() const = 0; |
| virtual bool isMap() const = 0; |
| virtual bool isNull() const = 0; |
| |
| virtual nonstd::expected<std::string, std::exception_ptr> getString() const = 0; |
| virtual nonstd::expected<bool, std::exception_ptr> getBool() const = 0; |
| virtual nonstd::expected<int64_t, std::exception_ptr> getInt64() const = 0; |
| virtual nonstd::expected<std::string, std::exception_ptr> getIntegerAsString() const = 0; |
| virtual nonstd::expected<std::string, std::exception_ptr> getScalarAsString() const = 0; |
| |
| virtual std::string getDebugString() const = 0; |
| |
| virtual size_t size() const = 0; |
| virtual Iterator begin() const = 0; |
| virtual Iterator end() const = 0; |
| virtual Node operator[](std::string_view key) const = 0; |
| |
| virtual std::optional<Cursor> getCursor() const = 0; |
| |
| virtual Node createEmpty() const = 0; |
| |
| virtual ~NodeImpl() = default; |
| |
| std::string path_; |
| }; |
| |
| Node() = default; |
| explicit Node(std::shared_ptr<NodeImpl> impl): impl_(std::move(impl)) {} |
| |
| explicit operator bool() const {return impl_->operator bool();} |
| bool isSequence() const {return impl_->isSequence();} |
| bool isMap() const {return impl_->isMap();} |
| bool isNull() const {return impl_->isNull();} |
| |
| nonstd::expected<std::string, std::exception_ptr> getString() const {return impl_->getString();} |
| nonstd::expected<bool, std::exception_ptr> getBool() const {return impl_->getBool();} |
| nonstd::expected<int64_t, std::exception_ptr> getInt64() const {return impl_->getInt64();} |
| nonstd::expected<std::string, std::exception_ptr> getIntegerAsString() const {return impl_->getIntegerAsString();} |
| nonstd::expected<std::string, std::exception_ptr> getScalarAsString() const {return impl_->getScalarAsString();} |
| |
| // return a string representation of the node (need not be deserializable) |
| std::string getDebugString() const {return impl_->getDebugString();} |
| |
| size_t size() const {return impl_->size();} |
| size_t empty() const { |
| return size() == 0; |
| } |
| Iterator begin() const { |
| Iterator it = impl_->begin(); |
| it.impl_->path_ = impl_->path_; |
| return it; |
| } |
| Iterator end() const { |
| Iterator it = impl_->end(); |
| it.impl_->path_ = impl_->path_; |
| return it; |
| } |
| |
| // considers @key to be a member of this node as is |
| Node getMember(std::string_view key) { |
| Node result = impl_->operator[](key); |
| result.impl_->path_ = utils::string::join_pack(impl_->path_, "/", key); |
| return result; |
| } |
| |
| // considers @key to be a '/'-delimited access path |
| Node operator[](std::string_view key) const { |
| Node result = *this; |
| for (auto& field : utils::string::split(std::string{key}, "/")) { |
| if (key == ".") { |
| // pass: self |
| } else { |
| result = result.getMember(field); |
| } |
| if (!result) { |
| break; |
| } |
| } |
| return result; |
| } |
| |
| // considers @keys to be a set of viable access paths, the first viable is returned |
| Node operator[](std::span<const std::string> keys) const { |
| for (auto& key : keys) { |
| if (Node result = (*this)[key]) { |
| return result; |
| } |
| } |
| return impl_->createEmpty(); |
| } |
| |
| std::string getPath() const {return impl_->path_;} |
| |
| std::optional<Cursor> getCursor() const {return impl_->getCursor();} |
| |
| private: |
| std::shared_ptr<NodeImpl> impl_; |
| }; |
| |
| class Node::Iterator::Value : public Node, public std::pair<Node, Node> { |
| public: |
| Value(Node node, Node key, Node value): Node{std::move(node)}, std::pair<Node, Node>{std::move(key), std::move(value)} {} |
| }; |
| |
| } // namespace org::apache::nifi::minifi::core::flow |