#pragma once #include "fwd.h" #include "value.h" #include #include #include #include #include #include #include #include #include class IInputStream; class IOutputStream; namespace NConfig { typedef THashMap TGlobals; class TConfigError: public TWithBackTrace { }; class TConfigParseError: public TConfigError { }; class TTypeMismatch: public TConfigError { }; struct TArray; struct TDict; class TConfig { public: inline TConfig() : V_(Null()) { } inline TConfig(IValue* v) : V_(v) { } TConfig(const TConfig& config) = default; TConfig& operator=(const TConfig& config) = default; template inline bool IsA() const { return V_->IsA(typeid(T)); } inline bool IsNumeric() const { return IsA() || IsA() || IsA(); } template inline const T& Get() const { return GetNonConstant(); } template inline T& GetNonConstant() const { if (this->IsA()) { return *(T*)V_->Ptr(); } if constexpr (std::is_same_v) { NCfgPrivate::ReportTypeMismatch(V_->TypeName(), "array"); } else if constexpr (std::is_same_v) { NCfgPrivate::ReportTypeMismatch(V_->TypeName(), "dict"); } else if constexpr (std::is_same_v) { NCfgPrivate::ReportTypeMismatch(V_->TypeName(), "string"); } else { NCfgPrivate::ReportTypeMismatch(V_->TypeName(), ::TypeName()); } } template inline T As() const { return ValueAs(V_.Get()); } template inline T As(T def) const { return IsNull() ? def : As(); } inline bool IsNull() const noexcept { return V_.Get() == Null(); } const TConfig& Or(const TConfig& r) const { return IsNull() ? r : *this; } //assume value is dict bool Has(const TStringBuf& key) const; const TConfig& operator[](const TStringBuf& key) const; const TConfig& At(const TStringBuf& key) const; //assume value is array const TConfig& operator[](size_t index) const; size_t GetArraySize() const; static TConfig FromIni(IInputStream& in, const TGlobals& g = TGlobals()); static TConfig FromJson(IInputStream& in, const TGlobals& g = TGlobals()); static TConfig FromLua(IInputStream& in, const TGlobals& g = TGlobals()); //load yconf format. unsafe, but natural mapping static TConfig FromMarkup(IInputStream& in, const TGlobals& g = TGlobals()); static TConfig FromStream(IInputStream& in, const TGlobals& g = TGlobals()); inline void ToJson(IOutputStream& out) const { V_->ToJson(out); } void DumpJson(IOutputStream& out) const; void DumpLua(IOutputStream& out) const; static TConfig ReadJson(TStringBuf in, const TGlobals& g = TGlobals()); static TConfig ReadLua(TStringBuf in, const TGlobals& g = TGlobals()); static TConfig ReadMarkup(TStringBuf in, const TGlobals& g = TGlobals()); static TConfig ReadIni(TStringBuf in, const TGlobals& g = TGlobals()); void Load(IInputStream* stream); void Save(IOutputStream* stream) const; private: TIntrusivePtr V_; }; struct TArray: public TDeque { const TConfig& Index(size_t index) const; const TConfig& At(size_t index) const; }; struct TDict: public THashMap { const TConfig& Find(const TStringBuf& key) const; const TConfig& At(const TStringBuf& key) const; }; THolder CreatePreprocessor(const TGlobals& g, IInputStream& in); }