#pragma once #include #include #include #include #include class IOutputStream; namespace NConfig { class IValue: public TAtomicRefCount { 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 inline IValue* ConstructValueImpl(const T& t, ...) { extern IValue* ConstructValueImpl(const T& t); return ConstructValueImpl(t); } template ::value>* = nullptr> inline IValue* ConstructValueImpl(const T& t, TDummy) { extern IValue* ConstructValueImpl(const double& t); return ConstructValueImpl(t); } template ::value>* = nullptr> inline IValue* ConstructValueImpl(const T& t, TDummy) { typedef std::conditional_t::value, i64, ui64> Type; extern IValue* ConstructValueImpl(const Type& t); return ConstructValueImpl(t); } template ::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 inline IValue* ConstructValue(const T& t) { return NCfgPrivate::ConstructValueImpl(t, NCfgPrivate::TDummy()); } IValue* Null(); namespace NCfgPrivate { template struct TSelector { static inline ui64 Cvt(const IValue* v) { return v->AsUInt(); } }; template <> struct TSelector { static inline i64 Cvt(const IValue* v) { return v->AsInt(); } }; [[noreturn]] void ReportTypeMismatch(TStringBuf realType, TStringBuf expectedType); } template inline T ValueAs(const IValue* val) { typedef NCfgPrivate::TSelector::value> TCvt; return SafeIntegerCast(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(); } }