utils/include/core/state/Value.h (385 lines of code) (raw):

/** * * 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 <typeindex> #include <limits> #include <sstream> #include <iostream> #include <memory> #include <string> #include <utility> #include <vector> #include <typeinfo> #include "minifi-cpp/core/state/Value.h" #include "utils/ValueParser.h" #include "utils/ValueCaster.h" #include "utils/meta/type_list.h" #include "rapidjson/writer.h" #include "rapidjson/document.h" #include "rapidjson/stringbuffer.h" namespace org::apache::nifi::minifi::state::response { /** * Purpose: Represents an AST value * Contains an embedded string representation to be used for a toString analog. * * Extensions can be more strongly typed and can be used anywhere where an abstract * representation is needed. */ class ValueImpl : public Value { using ParseException = utils::internal::ParseException; public: explicit ValueImpl(std::string value) : string_value(std::move(value)), type_id(std::type_index(typeid(std::string))) { } ~ValueImpl() override = default; [[nodiscard]] std::string getStringValue() const override { return string_value; } [[nodiscard]] const char* c_str() const override { return string_value.c_str(); } [[nodiscard]] bool empty() const noexcept override { return string_value.empty(); } std::type_index getTypeIndex() override { return type_id; } protected: template<typename T> void setTypeId() { type_id = std::type_index(typeid(T)); } bool getValue(uint32_t &ref) override { try { uint32_t value; utils::internal::ValueParser(string_value).parse(value).parseEnd(); ref = value; } catch(const ParseException&) { return false; } return true; } bool getValue(int &ref) override { try { int value; utils::internal::ValueParser(string_value).parse(value).parseEnd(); ref = value; } catch(const ParseException&) { return false; } return true; } bool getValue(int64_t &ref) override { try { int64_t value; utils::internal::ValueParser(string_value).parse(value).parseEnd(); ref = value; } catch(const ParseException&) { return false; } return true; } bool getValue(uint64_t &ref) override { try { uint64_t value; utils::internal::ValueParser(string_value).parse(value).parseEnd(); ref = value; } catch(const ParseException&) { return false; } return true; } bool getValue(bool &ref) override { try { bool value; utils::internal::ValueParser(string_value).parse(value).parseEnd(); ref = value; } catch(const ParseException&) { return false; } return true; } bool getValue(double &ref) override { try { double value; utils::internal::ValueParser(string_value).parse(value).parseEnd(); ref = value; } catch(const ParseException&) { return false; } return true; } std::string string_value; std::type_index type_id; }; class UInt32Value : public ValueImpl { public: explicit UInt32Value(uint32_t value) : ValueImpl(std::to_string(value)), value(value) { setTypeId<uint32_t>(); } explicit UInt32Value(const std::string &strvalue) : ValueImpl(strvalue) { utils::internal::ValueParser(strvalue).parse(value).parseEnd(); setTypeId<uint32_t>(); } [[nodiscard]] uint32_t getValue() const { return value; } protected: bool getValue(uint32_t &ref) override { ref = value; return true; } bool getValue(int &ref) override { return utils::internal::cast_if_in_range(value, ref); } bool getValue(int64_t &ref) override { ref = value; return true; } bool getValue(uint64_t &ref) override { ref = value; return true; } bool getValue(bool& /*ref*/) override { return false; } bool getValue(double& ref) override { return utils::internal::cast_if_in_range(value, ref); } uint32_t value{}; }; class IntValue : public ValueImpl { public: explicit IntValue(int value) : ValueImpl(std::to_string(value)), value(value) { setTypeId<int>(); } explicit IntValue(const std::string &strvalue) : ValueImpl(strvalue) { utils::internal::ValueParser(strvalue).parse(value).parseEnd(); setTypeId<int>(); } [[nodiscard]] int getValue() const { return value; } protected: bool getValue(int &ref) override { ref = value; return true; } bool getValue(uint32_t &ref) override { return utils::internal::cast_if_in_range(value, ref); } bool getValue(int64_t &ref) override { ref = value; return true; } bool getValue(uint64_t &ref) override { return utils::internal::cast_if_in_range(value, ref); } bool getValue(bool& /*ref*/) override { return false; } bool getValue(double& ref) override { return utils::internal::cast_if_in_range(value, ref); } int value{}; }; class BoolValue : public ValueImpl { public: explicit BoolValue(bool value) : ValueImpl(value ? "true" : "false"), value(value) { setTypeId<bool>(); } explicit BoolValue(const std::string &strvalue) : ValueImpl(strvalue) { utils::internal::ValueParser(strvalue).parse(value).parseEnd(); setTypeId<bool>(); } [[nodiscard]] bool getValue() const { return value; } protected: bool getValue(int &ref) override { return PreventSwearingInFutureRefactor(ref); } bool getValue(uint32_t &ref) override { return PreventSwearingInFutureRefactor(ref); } bool getValue(int64_t &ref) override { return PreventSwearingInFutureRefactor(ref); } bool getValue(uint64_t &ref) override { return PreventSwearingInFutureRefactor(ref); } bool getValue(double &ref) override { return PreventSwearingInFutureRefactor(ref); } bool getValue(bool &ref) override { ref = value; return true; } bool value{}; private: template<typename T> bool PreventSwearingInFutureRefactor(T &ref) { if (value != 0 && value != 1) { return false; } ref = value != 0; return true; } }; class UInt64Value : public ValueImpl { public: explicit UInt64Value(uint64_t value) : ValueImpl(std::to_string(value)), value(value) { setTypeId<uint64_t>(); } explicit UInt64Value(const std::string &strvalue) : ValueImpl(strvalue) { utils::internal::ValueParser(strvalue).parse(value).parseEnd(); setTypeId<uint64_t>(); } [[nodiscard]] uint64_t getValue() const { return value; } protected: bool getValue(int& ref) override { return utils::internal::cast_if_in_range(value, ref); } bool getValue(uint32_t& ref) override { return utils::internal::cast_if_in_range(value, ref); } bool getValue(int64_t &ref) override { return utils::internal::cast_if_in_range(value, ref); } bool getValue(uint64_t &ref) override { return utils::internal::cast_if_in_range(value, ref); } bool getValue(bool& /*ref*/) override { return false; } bool getValue(double& ref) override { return utils::internal::cast_if_in_range(value, ref); } uint64_t value{}; }; class Int64Value : public ValueImpl { public: explicit Int64Value(int64_t value) : ValueImpl(std::to_string(value)), value(value) { setTypeId<int64_t>(); } explicit Int64Value(const std::string &strvalue) : ValueImpl(strvalue) { utils::internal::ValueParser(strvalue).parse(value).parseEnd(); setTypeId<int64_t>(); } [[nodiscard]] int64_t getValue() const { return value; } protected: bool getValue(int& ref) override { return utils::internal::cast_if_in_range(value, ref); } bool getValue(uint32_t& ref) override { return utils::internal::cast_if_in_range(value, ref); } bool getValue(int64_t& ref) override { ref = value; return true; } bool getValue(uint64_t& ref) override { return utils::internal::cast_if_in_range(value, ref); } bool getValue(bool& /*ref*/) override { return false; } bool getValue(double& ref) override { return utils::internal::cast_if_in_range(value, ref); } int64_t value{}; }; class DoubleValue : public ValueImpl { public: explicit DoubleValue(double value) : ValueImpl(std::to_string(value)), value(value) { setTypeId<double>(); } explicit DoubleValue(const std::string &strvalue) : ValueImpl(strvalue) { utils::internal::ValueParser(strvalue).parse(value).parseEnd(); setTypeId<double>(); } [[nodiscard]] double getValue() const { return value; } protected: bool getValue(int& ref) override { return utils::internal::cast_if_in_range(value, ref); } bool getValue(uint32_t& ref) override { return utils::internal::cast_if_in_range(value, ref); } bool getValue(int64_t& ref) override { return utils::internal::cast_if_in_range(value, ref); } bool getValue(uint64_t& ref) override { return utils::internal::cast_if_in_range(value, ref); } bool getValue(bool&) override { return false; } bool getValue(double& ref) override { ref = value; return true; } double value{}; }; static inline std::shared_ptr<Value> createValue(const bool &object) { return std::make_shared<BoolValue>(object); } static inline std::shared_ptr<Value> createValue(const char *object) { return std::make_shared<ValueImpl>(object); } static inline std::shared_ptr<Value> createValue(char *object) { return std::make_shared<ValueImpl>(std::string(object)); } static inline std::shared_ptr<Value> createValue(const std::string &object) { return std::make_shared<ValueImpl>(object); } static inline std::shared_ptr<Value> createValue(const uint32_t &object) { return std::make_shared<UInt32Value>(object); } #if ( defined(__APPLE__) || defined(__MACH__) || defined(DARWIN) ) static inline std::shared_ptr<Value> createValue(const size_t &object) { return std::make_shared<UInt64Value>(object); } #endif static inline std::shared_ptr<Value> createValue(const uint64_t &object) { return std::make_shared<UInt64Value>(object); } static inline std::shared_ptr<Value> createValue(const int64_t &object) { return std::make_shared<Int64Value>(object); } static inline std::shared_ptr<Value> createValue(const int &object) { return std::make_shared<IntValue>(object); } static inline std::shared_ptr<Value> createValue(const double &object) { return std::make_shared<DoubleValue>(object); } template<typename T> requires (ValueNode::supported_types::contains<T>()) // NOLINT /* implicit, because it doesn't change the meaning, and it simplifies construction of maps */ ValueNode::ValueNode(const T value) // NOLINT :value_{createValue(value)} {} /** * Define the representations and eventual storage relationships through * createValue */ template<typename T> requires (ValueNode::supported_types::contains<T>()) // NOLINT ValueNode& ValueNode::operator=(const T ref) { value_ = createValue(ref); return *this; } inline std::string to_string(const SerializedResponseNode& node) { return node.to_string(); } std::string hashResponseNodes(const std::vector<SerializedResponseNode>& nodes); } // namespace org::apache::nifi::minifi::state::response