123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- #include "scimpl.h"
- #include <library/cpp/json/json_reader.h>
- #include <util/stream/output.h>
- #include <util/generic/maybe.h>
- namespace NSc {
- struct TJsonError {
- size_t Offset = 0;
- TMaybe<TString> Reason;
- };
- struct TJsonDeserializer : NJson::TJsonCallbacks {
- struct TContainer {
- TValue* Container = nullptr;
- TValue* LastValue = nullptr;
- bool ExpectKey = false;
- TContainer(TValue& v)
- : Container(&v)
- , ExpectKey(v.IsDict())
- {
- }
- bool Add(TStringBuf v, bool allowDuplicated) {
- if (!ExpectKey || Y_UNLIKELY(!Container->IsDict()))
- return false;
- if (!allowDuplicated && Y_UNLIKELY(Container->Has(v)))
- return false;
- LastValue = &Container->GetOrAdd(v);
- ExpectKey = false;
- return true;
- }
- void Push() {
- LastValue = &Container->Push();
- }
- TValue& NextValue() {
- if (Container->IsArray()) {
- Push();
- } else if (Container->IsDict()) {
- ExpectKey = true;
- }
- return *(LastValue ? LastValue : Container);
- }
- bool IsArray() const {
- return !!Container && Container->IsArray();
- }
- bool IsDict() const {
- return !!Container && Container->IsDict();
- }
- };
- typedef TVector<TContainer> TStackType;
- public:
- TValue& Root;
- TJsonError& Error;
- const TJsonOpts& Cfg;
- TStackType Stack;
- bool Virgin = true;
- public:
- TJsonDeserializer(TValue& root, TJsonError& err, const TJsonOpts& cfg)
- : Root(root)
- , Error(err)
- , Cfg(cfg)
- {
- Root.SetNull();
- Stack.reserve(10);
- }
- bool HasNextValue() const {
- return Virgin | !Stack.empty();
- }
- TValue& NextValue() {
- Virgin = false;
- return Stack.empty() ? Root : Stack.back().NextValue();
- }
- bool OnNull() override {
- if (Y_UNLIKELY(!HasNextValue()))
- return false;
- NextValue().SetNull();
- return true;
- }
- bool OnEnd() override {
- return Stack.empty();
- }
- template <typename T>
- bool OnValue(T v) {
- if (Y_UNLIKELY(!HasNextValue()))
- return false;
- NextValue() = v;
- return true;
- }
- template <typename T>
- bool OnIntValue(T v) {
- if (Y_UNLIKELY(!HasNextValue()))
- return false;
- NextValue().SetIntNumber(v);
- return true;
- }
- bool OnBoolean(bool v) override {
- if (Y_UNLIKELY(!HasNextValue()))
- return false;
- NextValue().SetBool(v);
- return true;
- }
- bool OnInteger(long long v) override {
- return OnIntValue(v);
- }
- bool OnUInteger(unsigned long long v) override {
- return OnIntValue(v);
- }
- bool OnDouble(double v) override {
- return OnValue(v);
- }
- bool OnString(const TStringBuf& v) override {
- return OnValue(v);
- }
- bool OnMapKey(const TStringBuf& k) override {
- if (Y_UNLIKELY(Stack.empty()))
- return false;
- return Stack.back().Add(k, !(Cfg.Opts & TJsonOpts::JO_PARSER_DISALLOW_DUPLICATE_KEYS));
- }
- bool OnOpenMap() override {
- if (Y_UNLIKELY(!HasNextValue()))
- return false;
- Stack.push_back(TContainer(NextValue().SetDict()));
- return true;
- }
- bool OnCloseMap() override {
- if (Y_UNLIKELY(Stack.empty() || !Stack.back().IsDict()))
- return false;
- Stack.pop_back();
- return true;
- }
- bool OnOpenArray() override {
- if (Y_UNLIKELY(!HasNextValue()))
- return false;
- Stack.push_back(TContainer(NextValue().SetArray()));
- return true;
- }
- bool OnCloseArray() override {
- if (Y_UNLIKELY(Stack.empty() || !Stack.back().IsArray()))
- return false;
- Stack.pop_back();
- return true;
- }
- void OnError(size_t off, TStringBuf reason) override {
- Error.Offset = off;
- Error.Reason = reason;
- }
- };
- static bool DoParseFromJson(TValue& res, TJsonError& err, TStringBuf json, const TJsonOpts& cfg) {
- TJsonDeserializer d(res, err, cfg);
- if (cfg.RelaxedJson) {
- return NJson::ReadJsonFast(json, &d);
- } else {
- TMemoryInput min(json.data(), json.size());
- return NJson::ReadJson(&min, &cfg, &d);
- }
- }
- static bool DoParseFromJson(TValue& res, TStringBuf json, const TJsonOpts& cfg) {
- TJsonError err;
- return DoParseFromJson(res, err, json, cfg);
- }
- TValue TValue::FromJson(TStringBuf v, const TJsonOpts& cfg) {
- TValue res;
- if (FromJson(res, v, cfg)) {
- return res;
- } else {
- return DefaultValue();
- }
- }
- TValue TValue::FromJsonThrow(TStringBuf json, const TJsonOpts& cfg) {
- TValue res;
- TJsonError err;
- if (DoParseFromJson(res, err, json, cfg)) {
- return res;
- }
- TString reason = err.Reason.Empty() ? "NULL" : *err.Reason;
- ythrow TSchemeParseException(err.Offset, reason) << "JSON error at offset " << err.Offset << " (" << reason << ")";
- }
- bool TValue::FromJson(TValue& res, TStringBuf json, const TJsonOpts& cfg) {
- if (DoParseFromJson(res, json, cfg)) {
- return true;
- }
- res.SetNull();
- return false;
- }
- }
|