#pragma once #include <typeinfo> #include <util/generic/ptr.h> #include <util/generic/cast.h> #include <util/generic/string.h> #include <util/generic/typetraits.h> class IOutputStream; namespace NConfig { class IValue: public TAtomicRefCount<IValue> { public: virtual ~IValue() = default; virtual bool IsA(const std::type_info& info) const = 0; virtual TString TypeName() const = 0; virtual void* Ptr() const = 0; virtual ui64 AsUInt() const = 0; virtual i64 AsInt() const = 0; virtual double AsDouble() const = 0; virtual bool AsBool() const = 0; virtual TString AsString() const = 0; virtual void ToJson(IOutputStream& out) const = 0; }; namespace NCfgPrivate { struct TDummy { }; template <class T> inline IValue* ConstructValueImpl(const T& t, ...) { extern IValue* ConstructValueImpl(const T& t); return ConstructValueImpl(t); } template <class T, std::enable_if_t<std::is_floating_point<T>::value>* = nullptr> inline IValue* ConstructValueImpl(const T& t, TDummy) { extern IValue* ConstructValueImpl(const double& t); return ConstructValueImpl(t); } template <class T, std::enable_if_t<std::is_integral<T>::value>* = nullptr> inline IValue* ConstructValueImpl(const T& t, TDummy) { typedef std::conditional_t<std::is_signed<T>::value, i64, ui64> Type; extern IValue* ConstructValueImpl(const Type& t); return ConstructValueImpl(t); } template <class T, std::enable_if_t<std::is_convertible<T, TString>::value>* = nullptr> inline IValue* ConstructValueImpl(const T& t, TDummy) { extern IValue* ConstructValueImpl(const TString& t); return ConstructValueImpl(t); } inline IValue* ConstructValueImpl(const bool& t, TDummy) { extern IValue* ConstructValueImpl(const bool& t); return ConstructValueImpl(t); } } template <class T> inline IValue* ConstructValue(const T& t) { return NCfgPrivate::ConstructValueImpl(t, NCfgPrivate::TDummy()); } IValue* Null(); namespace NCfgPrivate { template <bool Unsigned> struct TSelector { static inline ui64 Cvt(const IValue* v) { return v->AsUInt(); } }; template <> struct TSelector<false> { static inline i64 Cvt(const IValue* v) { return v->AsInt(); } }; [[noreturn]] void ReportTypeMismatch(TStringBuf realType, TStringBuf expectedType); } template <class T> inline T ValueAs(const IValue* val) { typedef NCfgPrivate::TSelector<std::is_unsigned<T>::value> TCvt; return SafeIntegerCast<T>(TCvt::Cvt(val)); } template <> inline double ValueAs(const IValue* val) { return val->AsDouble(); } template <> inline float ValueAs(const IValue* val) { return (float)val->AsDouble(); } template <> inline bool ValueAs(const IValue* val) { return val->AsBool(); } template <> inline TString ValueAs(const IValue* val) { return val->AsString(); } }