diff options
author | Anton Samokhvalov <pg83@yandex.ru> | 2022-02-10 16:45:17 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:17 +0300 |
commit | d3a398281c6fd1d3672036cb2d63f842d2cb28c5 (patch) | |
tree | dd4bd3ca0f36b817e96812825ffaf10d645803f2 /library/cpp/json | |
parent | 72cb13b4aff9bc9cf22e49251bc8fd143f82538f (diff) | |
download | ydb-d3a398281c6fd1d3672036cb2d63f842d2cb28c5.tar.gz |
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 2 of 2.
Diffstat (limited to 'library/cpp/json')
39 files changed, 3585 insertions, 3585 deletions
diff --git a/library/cpp/json/common/defs.cpp b/library/cpp/json/common/defs.cpp index 7ae904ba54..da86da82e4 100644 --- a/library/cpp/json/common/defs.cpp +++ b/library/cpp/json/common/defs.cpp @@ -1,68 +1,68 @@ -#include "defs.h" - -using namespace NJson; - -TJsonCallbacks::~TJsonCallbacks() { -} - -bool TJsonCallbacks::OnNull() { - return true; -} - -bool TJsonCallbacks::OnBoolean(bool) { - return true; -} - -bool TJsonCallbacks::OnInteger(long long) { - return true; -} - -bool TJsonCallbacks::OnUInteger(unsigned long long) { - return true; -} - -bool TJsonCallbacks::OnDouble(double) { - return true; -} - -bool TJsonCallbacks::OnString(const TStringBuf&) { - return true; -} - -bool TJsonCallbacks::OnOpenMap() { - return true; -} - -bool TJsonCallbacks::OnMapKey(const TStringBuf&) { - return true; -} - -bool TJsonCallbacks::OnCloseMap() { - return true; -} - -bool TJsonCallbacks::OnOpenArray() { - return true; -} - -bool TJsonCallbacks::OnCloseArray() { - return true; -} - -bool TJsonCallbacks::OnStringNoCopy(const TStringBuf& s) { - return OnString(s); -} - -bool TJsonCallbacks::OnMapKeyNoCopy(const TStringBuf& s) { - return OnMapKey(s); -} - -bool TJsonCallbacks::OnEnd() { - return true; -} - -void TJsonCallbacks::OnError(size_t off, TStringBuf reason) { - if (ThrowException) { - ythrow TJsonException() << "JSON error at offset " << off << " (" << reason << ")"; - } -} +#include "defs.h" + +using namespace NJson; + +TJsonCallbacks::~TJsonCallbacks() { +} + +bool TJsonCallbacks::OnNull() { + return true; +} + +bool TJsonCallbacks::OnBoolean(bool) { + return true; +} + +bool TJsonCallbacks::OnInteger(long long) { + return true; +} + +bool TJsonCallbacks::OnUInteger(unsigned long long) { + return true; +} + +bool TJsonCallbacks::OnDouble(double) { + return true; +} + +bool TJsonCallbacks::OnString(const TStringBuf&) { + return true; +} + +bool TJsonCallbacks::OnOpenMap() { + return true; +} + +bool TJsonCallbacks::OnMapKey(const TStringBuf&) { + return true; +} + +bool TJsonCallbacks::OnCloseMap() { + return true; +} + +bool TJsonCallbacks::OnOpenArray() { + return true; +} + +bool TJsonCallbacks::OnCloseArray() { + return true; +} + +bool TJsonCallbacks::OnStringNoCopy(const TStringBuf& s) { + return OnString(s); +} + +bool TJsonCallbacks::OnMapKeyNoCopy(const TStringBuf& s) { + return OnMapKey(s); +} + +bool TJsonCallbacks::OnEnd() { + return true; +} + +void TJsonCallbacks::OnError(size_t off, TStringBuf reason) { + if (ThrowException) { + ythrow TJsonException() << "JSON error at offset " << off << " (" << reason << ")"; + } +} diff --git a/library/cpp/json/common/defs.h b/library/cpp/json/common/defs.h index 8e0e6923fc..d3c8761bcc 100644 --- a/library/cpp/json/common/defs.h +++ b/library/cpp/json/common/defs.h @@ -1,38 +1,38 @@ -#pragma once - -#include <util/generic/strbuf.h> -#include <util/generic/yexception.h> - -namespace NJson { - class TJsonException: public yexception { - }; - - class TJsonCallbacks { - public: - explicit TJsonCallbacks(bool throwException = false) - : ThrowException(throwException) - { - } - - virtual ~TJsonCallbacks(); - - virtual bool OnNull(); - virtual bool OnBoolean(bool); - virtual bool OnInteger(long long); - virtual bool OnUInteger(unsigned long long); - virtual bool OnDouble(double); - virtual bool OnString(const TStringBuf&); - virtual bool OnOpenMap(); - virtual bool OnMapKey(const TStringBuf&); - virtual bool OnCloseMap(); - virtual bool OnOpenArray(); - virtual bool OnCloseArray(); - virtual bool OnStringNoCopy(const TStringBuf& s); - virtual bool OnMapKeyNoCopy(const TStringBuf& s); - virtual bool OnEnd(); - virtual void OnError(size_t off, TStringBuf reason); - - protected: - bool ThrowException; - }; -} +#pragma once + +#include <util/generic/strbuf.h> +#include <util/generic/yexception.h> + +namespace NJson { + class TJsonException: public yexception { + }; + + class TJsonCallbacks { + public: + explicit TJsonCallbacks(bool throwException = false) + : ThrowException(throwException) + { + } + + virtual ~TJsonCallbacks(); + + virtual bool OnNull(); + virtual bool OnBoolean(bool); + virtual bool OnInteger(long long); + virtual bool OnUInteger(unsigned long long); + virtual bool OnDouble(double); + virtual bool OnString(const TStringBuf&); + virtual bool OnOpenMap(); + virtual bool OnMapKey(const TStringBuf&); + virtual bool OnCloseMap(); + virtual bool OnOpenArray(); + virtual bool OnCloseArray(); + virtual bool OnStringNoCopy(const TStringBuf& s); + virtual bool OnMapKeyNoCopy(const TStringBuf& s); + virtual bool OnEnd(); + virtual void OnError(size_t off, TStringBuf reason); + + protected: + bool ThrowException; + }; +} diff --git a/library/cpp/json/common/ya.make b/library/cpp/json/common/ya.make index c64976ccd1..5bbd3b0792 100644 --- a/library/cpp/json/common/ya.make +++ b/library/cpp/json/common/ya.make @@ -1,9 +1,9 @@ -LIBRARY() - -OWNER(pg) - -SRCS( - defs.cpp -) - -END() +LIBRARY() + +OWNER(pg) + +SRCS( + defs.cpp +) + +END() diff --git a/library/cpp/json/domscheme_traits.h b/library/cpp/json/domscheme_traits.h index 68b149a690..a5a99cd8cf 100644 --- a/library/cpp/json/domscheme_traits.h +++ b/library/cpp/json/domscheme_traits.h @@ -1,7 +1,7 @@ #pragma once -#include "json_value.h" -#include "json_reader.h" +#include "json_value.h" +#include "json_reader.h" #include "json_writer.h" #include <util/generic/algorithm.h> @@ -125,7 +125,7 @@ struct TJsonTraits { // boolean ops static inline void Get(TConstValueRef v, bool def, bool& b) { b = - v->GetType() == NJson::JSON_UNDEFINED ? def : v->IsNull() ? def : v->GetBooleanRobust(); + v->GetType() == NJson::JSON_UNDEFINED ? def : v->IsNull() ? def : v->GetBooleanRobust(); } static inline void Get(TConstValueRef v, bool& b) { @@ -136,14 +136,14 @@ struct TJsonTraits { return v->IsBoolean(); } -#define INTEGER_OPS(type, checkOp, getOp) \ - static inline void Get(TConstValueRef v, type def, type& i) { \ - i = v->checkOp() ? v->getOp() : def; \ - } \ - static inline void Get(TConstValueRef v, type& i) { \ - i = v->getOp(); \ - } \ - static inline bool IsValidPrimitive(const type&, TConstValueRef v) { \ +#define INTEGER_OPS(type, checkOp, getOp) \ + static inline void Get(TConstValueRef v, type def, type& i) { \ + i = v->checkOp() ? v->getOp() : def; \ + } \ + static inline void Get(TConstValueRef v, type& i) { \ + i = v->getOp(); \ + } \ + static inline bool IsValidPrimitive(const type&, TConstValueRef v) { \ return v->checkOp() && v->getOp() >= Min<type>() && v->getOp() <= Max<type>(); \ } diff --git a/library/cpp/json/easy_parse/json_easy_parser.cpp b/library/cpp/json/easy_parse/json_easy_parser.cpp index 4856768635..3c781f544b 100644 --- a/library/cpp/json/easy_parse/json_easy_parser.cpp +++ b/library/cpp/json/easy_parse/json_easy_parser.cpp @@ -5,232 +5,232 @@ #include <util/string/strip.h> namespace NJson { - static TString MAP_IDENTIFIER = "{}"; - static TString ARRAY_IDENTIFIER = "[]"; - static TString ANY_IDENTIFIER = "*"; - - static void ParsePath(TString path, TVector<TPathElem>* res) { - TVector<const char*> parts; - Split(path.begin(), '/', &parts); - for (size_t n = 0; n < parts.size(); ++n) { + static TString MAP_IDENTIFIER = "{}"; + static TString ARRAY_IDENTIFIER = "[]"; + static TString ANY_IDENTIFIER = "*"; + + static void ParsePath(TString path, TVector<TPathElem>* res) { + TVector<const char*> parts; + Split(path.begin(), '/', &parts); + for (size_t n = 0; n < parts.size(); ++n) { TString part = Strip(parts[n]); - if (!part.empty()) { - if (part[0] != '[') { - res->push_back(TPathElem(NImpl::MAP)); - res->push_back(TPathElem(part)); - } else { - int arrayCounter; - try { - arrayCounter = FromString<int>(part.substr(1, part.length() - 2)); - } catch (yexception&) { - arrayCounter = -1; - } - res->push_back(TPathElem(arrayCounter)); + if (!part.empty()) { + if (part[0] != '[') { + res->push_back(TPathElem(NImpl::MAP)); + res->push_back(TPathElem(part)); + } else { + int arrayCounter; + try { + arrayCounter = FromString<int>(part.substr(1, part.length() - 2)); + } catch (yexception&) { + arrayCounter = -1; + } + res->push_back(TPathElem(arrayCounter)); } } } } - void TJsonParser::AddField(const TString& path, bool nonEmpty) { - Fields.emplace_back(); - Fields.back().NonEmpty = nonEmpty; - ParsePath(path, &Fields.back().Path); - } - - TString TJsonParser::ConvertToTabDelimited(const TString& json) const { - TStringInput in(json); - TStringStream out; - ConvertToTabDelimited(in, out); - return out.Str(); - } - - class TRewriteJsonImpl: public NJson::TJsonCallbacks { - const TJsonParser& Parent; - TVector<TString> FieldValues; - TVector<TPathElem> Stack; - bool ShouldUpdateOnArrayChange; - int CurrentFieldIdx; - bool HasFormatError; - - private: - static bool PathElementMatch(const TPathElem& templ, const TPathElem& real) { - if (templ.Type != real.Type) - return false; - if (templ.Type == NImpl::ARRAY) - return templ.ArrayCounter == -1 || templ.ArrayCounter == real.ArrayCounter; - if (templ.Type == NImpl::MAP_KEY) - return templ.Key == ANY_IDENTIFIER || templ.Key == real.Key; - return true; - } - - bool CheckFilter(const TVector<TPathElem>& path) const { - if (Stack.size() < path.size()) + void TJsonParser::AddField(const TString& path, bool nonEmpty) { + Fields.emplace_back(); + Fields.back().NonEmpty = nonEmpty; + ParsePath(path, &Fields.back().Path); + } + + TString TJsonParser::ConvertToTabDelimited(const TString& json) const { + TStringInput in(json); + TStringStream out; + ConvertToTabDelimited(in, out); + return out.Str(); + } + + class TRewriteJsonImpl: public NJson::TJsonCallbacks { + const TJsonParser& Parent; + TVector<TString> FieldValues; + TVector<TPathElem> Stack; + bool ShouldUpdateOnArrayChange; + int CurrentFieldIdx; + bool HasFormatError; + + private: + static bool PathElementMatch(const TPathElem& templ, const TPathElem& real) { + if (templ.Type != real.Type) + return false; + if (templ.Type == NImpl::ARRAY) + return templ.ArrayCounter == -1 || templ.ArrayCounter == real.ArrayCounter; + if (templ.Type == NImpl::MAP_KEY) + return templ.Key == ANY_IDENTIFIER || templ.Key == real.Key; + return true; + } + + bool CheckFilter(const TVector<TPathElem>& path) const { + if (Stack.size() < path.size()) return false; for (size_t n = 0; n < path.size(); ++n) { - if (!PathElementMatch(path[n], Stack[n])) - return false; - } - return true; + if (!PathElementMatch(path[n], Stack[n])) + return false; + } + return true; } - void UpdateRule() { + void UpdateRule() { for (size_t n = 0; n < Parent.Fields.size(); ++n) { - if (FieldValues[n].empty() && CheckFilter(Parent.Fields[n].Path)) { - CurrentFieldIdx = n; - return; - } + if (FieldValues[n].empty() && CheckFilter(Parent.Fields[n].Path)) { + CurrentFieldIdx = n; + return; + } + } + CurrentFieldIdx = -1; + } + + void Pop() { + Stack.pop_back(); + } + + void IncreaseArrayCounter() { + if (!Stack.empty() && Stack.back().Type == NImpl::ARRAY) { + ++Stack.back().ArrayCounter; + if (ShouldUpdateOnArrayChange) + UpdateRule(); } - CurrentFieldIdx = -1; - } - - void Pop() { - Stack.pop_back(); - } - - void IncreaseArrayCounter() { - if (!Stack.empty() && Stack.back().Type == NImpl::ARRAY) { - ++Stack.back().ArrayCounter; - if (ShouldUpdateOnArrayChange) - UpdateRule(); - } - } - - template <class T> - bool OnValue(const T& val) { - IncreaseArrayCounter(); - if (CurrentFieldIdx >= 0) { - FieldValues[CurrentFieldIdx] = ToString(val); + } + + template <class T> + bool OnValue(const T& val) { + IncreaseArrayCounter(); + if (CurrentFieldIdx >= 0) { + FieldValues[CurrentFieldIdx] = ToString(val); UpdateRule(); - } - return true; - } - - public: - TRewriteJsonImpl(const TJsonParser& parent) - : Parent(parent) - , FieldValues(parent.Fields.size()) - , ShouldUpdateOnArrayChange(false) - , CurrentFieldIdx(-1) - , HasFormatError(false) - { + } + return true; + } + + public: + TRewriteJsonImpl(const TJsonParser& parent) + : Parent(parent) + , FieldValues(parent.Fields.size()) + , ShouldUpdateOnArrayChange(false) + , CurrentFieldIdx(-1) + , HasFormatError(false) + { for (size_t n = 0; n < Parent.Fields.size(); ++n) { if (!Parent.Fields[n].Path.empty() && Parent.Fields[n].Path.back().Type == NImpl::ARRAY) - ShouldUpdateOnArrayChange = true; - } - } - - bool OnOpenMap() override { - IncreaseArrayCounter(); - Stack.push_back(TPathElem(NImpl::MAP)); - if (CurrentFieldIdx >= 0) - HasFormatError = true; - else - UpdateRule(); - return true; - } - - bool OnOpenArray() override { - IncreaseArrayCounter(); - Stack.push_back(TPathElem(-1)); - if (CurrentFieldIdx >= 0) - HasFormatError = true; - else - UpdateRule(); - return true; - } - - bool OnCloseMap() override { - while (!Stack.empty() && Stack.back().Type != NImpl::MAP) - Pop(); - if (!Stack.empty()) - Pop(); + ShouldUpdateOnArrayChange = true; + } + } + + bool OnOpenMap() override { + IncreaseArrayCounter(); + Stack.push_back(TPathElem(NImpl::MAP)); + if (CurrentFieldIdx >= 0) + HasFormatError = true; + else + UpdateRule(); + return true; + } + + bool OnOpenArray() override { + IncreaseArrayCounter(); + Stack.push_back(TPathElem(-1)); + if (CurrentFieldIdx >= 0) + HasFormatError = true; + else + UpdateRule(); + return true; + } + + bool OnCloseMap() override { + while (!Stack.empty() && Stack.back().Type != NImpl::MAP) + Pop(); + if (!Stack.empty()) + Pop(); UpdateRule(); - return true; - } + return true; + } - bool OnCloseArray() override { - if (!Stack.empty()) - Pop(); + bool OnCloseArray() override { + if (!Stack.empty()) + Pop(); UpdateRule(); - return true; - } - - bool OnMapKey(const TStringBuf& key) override { - if (!Stack.empty() && Stack.back().Type == NImpl::MAP_KEY) { - Pop(); - UpdateRule(); - } + return true; + } + + bool OnMapKey(const TStringBuf& key) override { + if (!Stack.empty() && Stack.back().Type == NImpl::MAP_KEY) { + Pop(); + UpdateRule(); + } Stack.push_back(TPathElem(TString{key})); - if (CurrentFieldIdx >= 0) - HasFormatError = true; - else - UpdateRule(); - return true; - } + if (CurrentFieldIdx >= 0) + HasFormatError = true; + else + UpdateRule(); + return true; + } - bool OnBoolean(bool b) override { - return OnValue(b); - } + bool OnBoolean(bool b) override { + return OnValue(b); + } - bool OnInteger(long long i) override { - return OnValue(i); + bool OnInteger(long long i) override { + return OnValue(i); } - bool OnDouble(double f) override { - return OnValue(f); - } + bool OnDouble(double f) override { + return OnValue(f); + } - bool OnString(const TStringBuf& str) override { - return OnValue(str); - } + bool OnString(const TStringBuf& str) override { + return OnValue(str); + } - bool IsOK() const { - if (HasFormatError) - return false; + bool IsOK() const { + if (HasFormatError) + return false; for (size_t n = 0; n < FieldValues.size(); ++n) - if (Parent.Fields[n].NonEmpty && FieldValues[n].empty()) - return false; - return true; - } + if (Parent.Fields[n].NonEmpty && FieldValues[n].empty()) + return false; + return true; + } - void WriteTo(IOutputStream& out) const { + void WriteTo(IOutputStream& out) const { for (size_t n = 0; n < FieldValues.size(); ++n) - out << "\t" << FieldValues[n]; - } - - void WriteTo(TVector<TString>* res) const { - *res = FieldValues; - } - }; - - void TJsonParser::ConvertToTabDelimited(IInputStream& in, IOutputStream& out) const { - TRewriteJsonImpl impl(*this); - ReadJson(&in, &impl); - if (impl.IsOK()) { - out << Prefix; - impl.WriteTo(out); - out.Flush(); - } + out << "\t" << FieldValues[n]; + } + + void WriteTo(TVector<TString>* res) const { + *res = FieldValues; + } + }; + + void TJsonParser::ConvertToTabDelimited(IInputStream& in, IOutputStream& out) const { + TRewriteJsonImpl impl(*this); + ReadJson(&in, &impl); + if (impl.IsOK()) { + out << Prefix; + impl.WriteTo(out); + out.Flush(); + } } - bool TJsonParser::Parse(const TString& json, TVector<TString>* res) const { - TRewriteJsonImpl impl(*this); - TStringInput in(json); - ReadJson(&in, &impl); - if (impl.IsOK()) { - impl.WriteTo(res); - return true; - } else - return false; + bool TJsonParser::Parse(const TString& json, TVector<TString>* res) const { + TRewriteJsonImpl impl(*this); + TStringInput in(json); + ReadJson(&in, &impl); + if (impl.IsOK()) { + impl.WriteTo(res); + return true; + } else + return false; } - //struct TTestMe { - // TTestMe() { - // TJsonParser worker; - // worker.AddField("/x/y/z", true); - // TString ret1 = worker.ConvertToTabDelimited("{ \"x\" : { \"y\" : { \"w\" : 1, \"z\" : 2 } } }"); - // TString ret2 = worker.ConvertToTabDelimited(" [1, 2, 3, 4, 5] "); - // } - //} testMe; + //struct TTestMe { + // TTestMe() { + // TJsonParser worker; + // worker.AddField("/x/y/z", true); + // TString ret1 = worker.ConvertToTabDelimited("{ \"x\" : { \"y\" : { \"w\" : 1, \"z\" : 2 } } }"); + // TString ret2 = worker.ConvertToTabDelimited(" [1, 2, 3, 4, 5] "); + // } + //} testMe; } diff --git a/library/cpp/json/easy_parse/json_easy_parser.h b/library/cpp/json/easy_parse/json_easy_parser.h index 310ec6f2ec..59d7791ab1 100644 --- a/library/cpp/json/easy_parse/json_easy_parser.h +++ b/library/cpp/json/easy_parse/json_easy_parser.h @@ -1,5 +1,5 @@ #pragma once - + #include <util/generic/string.h> #include <util/generic/vector.h> #include <util/stream/input.h> @@ -33,14 +33,14 @@ namespace NJson { friend class TRewriteJsonImpl; - void ConvertToTabDelimited(IInputStream& in, IOutputStream& out) const; - + void ConvertToTabDelimited(IInputStream& in, IOutputStream& out) const; + public: - void SetPrefix(const TString& prefix) { + void SetPrefix(const TString& prefix) { Prefix = prefix; } - void AddField(const TString& path, bool mustExist); - TString ConvertToTabDelimited(const TString& json) const; - bool Parse(const TString& json, TVector<TString>* res) const; + void AddField(const TString& path, bool mustExist); + TString ConvertToTabDelimited(const TString& json) const; + bool Parse(const TString& json, TVector<TString>* res) const; }; } diff --git a/library/cpp/json/easy_parse/json_easy_parser_impl.h b/library/cpp/json/easy_parse/json_easy_parser_impl.h index 4ac14e8a44..ec55d838b3 100644 --- a/library/cpp/json/easy_parse/json_easy_parser_impl.h +++ b/library/cpp/json/easy_parse/json_easy_parser_impl.h @@ -22,7 +22,7 @@ namespace NJson { { } - TPathElemImpl(const TStringType& key) + TPathElemImpl(const TStringType& key) : Type(NImpl::MAP_KEY) , Key(key) , ArrayCounter() @@ -31,8 +31,8 @@ namespace NJson { TPathElemImpl(int arrayCounter) : Type(NImpl::ARRAY) - , ArrayCounter(arrayCounter) - { + , ArrayCounter(arrayCounter) + { } }; diff --git a/library/cpp/json/fast_sax/parser.h b/library/cpp/json/fast_sax/parser.h index 31f5348da9..b5f031dd9e 100644 --- a/library/cpp/json/fast_sax/parser.h +++ b/library/cpp/json/fast_sax/parser.h @@ -1,13 +1,13 @@ -#pragma once - +#pragma once + #include <library/cpp/json/common/defs.h> - -namespace NJson { - bool ReadJsonFast(TStringBuf in, TJsonCallbacks* callbacks); - - inline bool ValidateJsonFast(TStringBuf in, bool throwOnError = false) { + +namespace NJson { + bool ReadJsonFast(TStringBuf in, TJsonCallbacks* callbacks); + + inline bool ValidateJsonFast(TStringBuf in, bool throwOnError = false) { Y_ASSERT(false); // this method is broken, see details in IGNIETFERRO-1243. Use NJson::ValidateJson instead, or fix this one before using - TJsonCallbacks c(throwOnError); - return ReadJsonFast(in, &c); - } -} + TJsonCallbacks c(throwOnError); + return ReadJsonFast(in, &c); + } +} diff --git a/library/cpp/json/fast_sax/parser.rl6 b/library/cpp/json/fast_sax/parser.rl6 index 0f1ad3b3b1..edb4e9ee1b 100644 --- a/library/cpp/json/fast_sax/parser.rl6 +++ b/library/cpp/json/fast_sax/parser.rl6 @@ -2,7 +2,7 @@ #include <library/cpp/json/fast_sax/parser.h> #include <util/string/cast.h> -#include <util/generic/buffer.h> +#include <util/generic/buffer.h> #include <util/generic/strbuf.h> #include <util/generic/ymath.h> @@ -15,7 +15,7 @@ enum EStoredStr { struct TParserCtx { TJsonCallbacks& Hndl; - TBuffer Buffer; + TBuffer Buffer; TStringBuf String; EStoredStr Stored = SS_NONE; bool ExpectValue = true; @@ -142,9 +142,9 @@ struct TParserCtx { } bool OnStrE() { - Buffer.Clear(); - Buffer.Reserve(2 * (te - ts)); - + Buffer.Clear(); + Buffer.Reserve(2 * (te - ts)); + return OnString(UnescapeJsonUnicode(TStringBuf(ts + 1, te - ts - 2), Buffer.data()), SS_MUSTCOPY); } @@ -170,8 +170,8 @@ struct TParserCtx { Stored = SS_NONE; switch (stored) { - default: - return false; + default: + return false; case SS_NOCOPY: return Hndl.OnMapKeyNoCopy(String); case SS_MUSTCOPY: diff --git a/library/cpp/json/fast_sax/unescape.cpp b/library/cpp/json/fast_sax/unescape.cpp index 772fe92a0d..72109b0b5e 100644 --- a/library/cpp/json/fast_sax/unescape.cpp +++ b/library/cpp/json/fast_sax/unescape.cpp @@ -1,7 +1,7 @@ -#include "unescape.h" - -#include <util/string/escape.h> - -TStringBuf UnescapeJsonUnicode(TStringBuf data, char* scratch) { +#include "unescape.h" + +#include <util/string/escape.h> + +TStringBuf UnescapeJsonUnicode(TStringBuf data, char* scratch) { return TStringBuf(scratch, UnescapeC(data.data(), data.size(), scratch)); -} +} diff --git a/library/cpp/json/fast_sax/unescape.h b/library/cpp/json/fast_sax/unescape.h index 55315548bc..5e40e1e866 100644 --- a/library/cpp/json/fast_sax/unescape.h +++ b/library/cpp/json/fast_sax/unescape.h @@ -1,5 +1,5 @@ -#pragma once - -#include <util/generic/strbuf.h> - -TStringBuf UnescapeJsonUnicode(TStringBuf data, char* scratch); +#pragma once + +#include <util/generic/strbuf.h> + +TStringBuf UnescapeJsonUnicode(TStringBuf data, char* scratch); diff --git a/library/cpp/json/fast_sax/ya.make b/library/cpp/json/fast_sax/ya.make index 46e5c7c5d9..c6447ab6ac 100644 --- a/library/cpp/json/fast_sax/ya.make +++ b/library/cpp/json/fast_sax/ya.make @@ -1,17 +1,17 @@ -LIBRARY() - +LIBRARY() + OWNER( pg velavokr ) - -PEERDIR( + +PEERDIR( library/cpp/json/common -) - -SRCS( - parser.rl6 - unescape.cpp -) - -END() +) + +SRCS( + parser.rl6 + unescape.cpp +) + +END() diff --git a/library/cpp/json/flex_buffers/cvt.cpp b/library/cpp/json/flex_buffers/cvt.cpp index 9f7d630373..fee0cea0b8 100644 --- a/library/cpp/json/flex_buffers/cvt.cpp +++ b/library/cpp/json/flex_buffers/cvt.cpp @@ -1,139 +1,139 @@ -#include "cvt.h" - -#include <flatbuffers/flexbuffers.h> - +#include "cvt.h" + +#include <flatbuffers/flexbuffers.h> + #include <library/cpp/json/fast_sax/parser.h> #include <library/cpp/json/json_reader.h> - -#include <util/generic/vector.h> -#include <util/stream/output.h> -#include <util/stream/input.h> -#include <util/memory/pool.h> - -using namespace NJson; - -namespace { - struct TJsonToFlexCallbacks: public TJsonCallbacks { - inline TJsonToFlexCallbacks() - : P(8192) - { - } - + +#include <util/generic/vector.h> +#include <util/stream/output.h> +#include <util/stream/input.h> +#include <util/memory/pool.h> + +using namespace NJson; + +namespace { + struct TJsonToFlexCallbacks: public TJsonCallbacks { + inline TJsonToFlexCallbacks() + : P(8192) + { + } + bool OnNull() override { - B.Null(); - - return true; - } - + B.Null(); + + return true; + } + bool OnBoolean(bool v) override { - B.Bool(v); - - return true; - } - + B.Bool(v); + + return true; + } + bool OnInteger(long long v) override { - B.Int(v); - - return true; - } - + B.Int(v); + + return true; + } + bool OnUInteger(unsigned long long v) override { - B.UInt(v); - - return true; - } - + B.UInt(v); + + return true; + } + bool OnDouble(double v) override { - B.Double(v); - - return true; - } - + B.Double(v); + + return true; + } + bool OnString(const TStringBuf& v) override { B.String(v.data(), v.size()); - - return true; - } - + + return true; + } + bool OnOpenMap() override { - S.push_back(B.StartMap()); - - return true; - } - + S.push_back(B.StartMap()); + + return true; + } + bool OnMapKey(const TStringBuf& v) override { auto iv = P.AppendCString(v); - + B.Key(iv.data(), iv.size()); - - return true; - } - + + return true; + } + bool OnCloseMap() override { - B.EndMap(PopOffset()); - - return true; - } - + B.EndMap(PopOffset()); + + return true; + } + bool OnOpenArray() override { - S.push_back(B.StartVector()); - - return true; - } - + S.push_back(B.StartVector()); + + return true; + } + bool OnCloseArray() override { - B.EndVector(PopOffset(), false, false); - - return true; - } - + B.EndVector(PopOffset(), false, false); + + return true; + } + bool OnStringNoCopy(const TStringBuf& s) override { - return OnString(s); - } - + return OnString(s); + } + bool OnMapKeyNoCopy(const TStringBuf& s) override { - return OnMapKey(s); - } - + return OnMapKey(s); + } + bool OnEnd() override { - B.Finish(); - - Y_ENSURE(S.empty()); - - return true; - } - + B.Finish(); + + Y_ENSURE(S.empty()); + + return true; + } + void OnError(size_t, TStringBuf reason) override { - ythrow yexception() << reason; - } - - inline size_t PopOffset() { - auto res = S.back(); - - S.pop_back(); - - return res; - } - - inline auto& Buffer() { - return B.GetBuffer(); - } - - flexbuffers::Builder B; - TVector<size_t> S; - TMemoryPool P; - }; -} - -void NJson::ConvertJsonToFlexBuffers(TStringBuf input, TFlexBuffersData& result) { - TJsonToFlexCallbacks cb; - - ReadJsonFast(input, &cb); - result.swap(const_cast<std::vector<ui8>&>(cb.Buffer())); -} - -TString NJson::FlexToString(const TFlexBuffersData& v) { + ythrow yexception() << reason; + } + + inline size_t PopOffset() { + auto res = S.back(); + + S.pop_back(); + + return res; + } + + inline auto& Buffer() { + return B.GetBuffer(); + } + + flexbuffers::Builder B; + TVector<size_t> S; + TMemoryPool P; + }; +} + +void NJson::ConvertJsonToFlexBuffers(TStringBuf input, TFlexBuffersData& result) { + TJsonToFlexCallbacks cb; + + ReadJsonFast(input, &cb); + result.swap(const_cast<std::vector<ui8>&>(cb.Buffer())); +} + +TString NJson::FlexToString(const TFlexBuffersData& v) { auto root = flexbuffers::GetRoot(v.data(), v.size()); - - return TString(root.ToString()); -} + + return TString(root.ToString()); +} diff --git a/library/cpp/json/flex_buffers/cvt.h b/library/cpp/json/flex_buffers/cvt.h index 489f2dad83..82d2874268 100644 --- a/library/cpp/json/flex_buffers/cvt.h +++ b/library/cpp/json/flex_buffers/cvt.h @@ -1,20 +1,20 @@ -#pragma once - -#include <util/generic/vector.h> -#include <util/generic/strbuf.h> -#include <util/generic/string.h> - -namespace NJson { - using TFlexBuffersData = TVector<ui8>; - - TString FlexToString(const TFlexBuffersData& v); - void ConvertJsonToFlexBuffers(TStringBuf input, TFlexBuffersData& result); - - inline TFlexBuffersData ConvertJsonToFlexBuffers(TStringBuf input) { - TFlexBuffersData result; - - ConvertJsonToFlexBuffers(input, result); - - return result; - } -} +#pragma once + +#include <util/generic/vector.h> +#include <util/generic/strbuf.h> +#include <util/generic/string.h> + +namespace NJson { + using TFlexBuffersData = TVector<ui8>; + + TString FlexToString(const TFlexBuffersData& v); + void ConvertJsonToFlexBuffers(TStringBuf input, TFlexBuffersData& result); + + inline TFlexBuffersData ConvertJsonToFlexBuffers(TStringBuf input) { + TFlexBuffersData result; + + ConvertJsonToFlexBuffers(input, result); + + return result; + } +} diff --git a/library/cpp/json/flex_buffers/ut/cvt_ut.cpp b/library/cpp/json/flex_buffers/ut/cvt_ut.cpp index de3eb0d520..9fffef4d38 100644 --- a/library/cpp/json/flex_buffers/ut/cvt_ut.cpp +++ b/library/cpp/json/flex_buffers/ut/cvt_ut.cpp @@ -1,21 +1,21 @@ #include <library/cpp/testing/unittest/registar.h> #include <library/cpp/json/flex_buffers/cvt.h> - -using namespace NJson; - -static auto JSON = R"({ - "a": { - "b": [1, 2, 3], - "c": ["x", "y", 3, "z"] - } -})"; - -static auto RES = R"({ a: { b: [ 1, 2, 3 ], c: [ "x", "y", 3, "z" ] } })"; - -Y_UNIT_TEST_SUITE(JsonToFlex) { - Y_UNIT_TEST(Test1) { - auto buf = ConvertJsonToFlexBuffers(JSON); - - UNIT_ASSERT_VALUES_EQUAL(FlexToString(buf), RES); - } -} + +using namespace NJson; + +static auto JSON = R"({ + "a": { + "b": [1, 2, 3], + "c": ["x", "y", 3, "z"] + } +})"; + +static auto RES = R"({ a: { b: [ 1, 2, 3 ], c: [ "x", "y", 3, "z" ] } })"; + +Y_UNIT_TEST_SUITE(JsonToFlex) { + Y_UNIT_TEST(Test1) { + auto buf = ConvertJsonToFlexBuffers(JSON); + + UNIT_ASSERT_VALUES_EQUAL(FlexToString(buf), RES); + } +} diff --git a/library/cpp/json/flex_buffers/ut/ya.make b/library/cpp/json/flex_buffers/ut/ya.make index 148ac13856..3fdc93f88e 100644 --- a/library/cpp/json/flex_buffers/ut/ya.make +++ b/library/cpp/json/flex_buffers/ut/ya.make @@ -1,9 +1,9 @@ UNITTEST_FOR(library/cpp/json/flex_buffers) - -OWNER(pg) - -SRCS( - cvt_ut.cpp -) - -END() + +OWNER(pg) + +SRCS( + cvt_ut.cpp +) + +END() diff --git a/library/cpp/json/flex_buffers/ya.make b/library/cpp/json/flex_buffers/ya.make index 1b38b2f3d1..3ece5e3703 100644 --- a/library/cpp/json/flex_buffers/ya.make +++ b/library/cpp/json/flex_buffers/ya.make @@ -1,16 +1,16 @@ -LIBRARY() - -OWNER(pg) - +LIBRARY() + +OWNER(pg) + ADDINCL(contrib/libs/flatbuffers/include) - -PEERDIR( + +PEERDIR( library/cpp/json - contrib/libs/flatbuffers -) - -SRCS( - cvt.cpp -) - -END() + contrib/libs/flatbuffers +) + +SRCS( + cvt.cpp +) + +END() diff --git a/library/cpp/json/fuzzy_test/main.cpp b/library/cpp/json/fuzzy_test/main.cpp index bdbf2679ff..29a53aac14 100644 --- a/library/cpp/json/fuzzy_test/main.cpp +++ b/library/cpp/json/fuzzy_test/main.cpp @@ -1,30 +1,30 @@ #include <library/cpp/json/json_reader.h> - -#include <util/random/random.h> -#include <util/stream/str.h> - -extern "C" int LLVMFuzzerTestOneInput(const ui8* data, size_t size) { + +#include <util/random/random.h> +#include <util/stream/str.h> + +extern "C" int LLVMFuzzerTestOneInput(const ui8* data, size_t size) { const auto json = TString((const char*)data, size); - - try { - NJson::TJsonValue value; - NJson::ReadJsonFastTree(json, &value, true); - } catch (...) { - //Cout << json << " -> " << CurrentExceptionMessage() << Endl; - } - - try { - NJson::TJsonCallbacks cb; - NJson::ReadJsonFast(json, &cb); - } catch (...) { - //Cout << json << " -> " << CurrentExceptionMessage() << Endl; - } - - try { - NJson::ValidateJson(json); - } catch (...) { - //Cout << json << " -> " << CurrentExceptionMessage() << Endl; - } - - return 0; -} + + try { + NJson::TJsonValue value; + NJson::ReadJsonFastTree(json, &value, true); + } catch (...) { + //Cout << json << " -> " << CurrentExceptionMessage() << Endl; + } + + try { + NJson::TJsonCallbacks cb; + NJson::ReadJsonFast(json, &cb); + } catch (...) { + //Cout << json << " -> " << CurrentExceptionMessage() << Endl; + } + + try { + NJson::ValidateJson(json); + } catch (...) { + //Cout << json << " -> " << CurrentExceptionMessage() << Endl; + } + + return 0; +} diff --git a/library/cpp/json/fuzzy_test/ya.make b/library/cpp/json/fuzzy_test/ya.make index 1ccd587546..ff50bc1f62 100644 --- a/library/cpp/json/fuzzy_test/ya.make +++ b/library/cpp/json/fuzzy_test/ya.make @@ -1,13 +1,13 @@ FUZZ() - -OWNER(pg) - -PEERDIR( + +OWNER(pg) + +PEERDIR( library/cpp/json -) - -SRCS( - main.cpp -) - -END() +) + +SRCS( + main.cpp +) + +END() diff --git a/library/cpp/json/json_prettifier.cpp b/library/cpp/json/json_prettifier.cpp index cf36ae210d..bb16aab44e 100644 --- a/library/cpp/json/json_prettifier.cpp +++ b/library/cpp/json/json_prettifier.cpp @@ -1,277 +1,277 @@ #include "json_prettifier.h" #include <util/generic/deque.h> -#include <util/generic/algorithm.h> +#include <util/generic/algorithm.h> #include <util/memory/pool.h> #include <util/string/util.h> #include <library/cpp/string_utils/relaxed_escaper/relaxed_escaper.h> namespace NJson { - struct TRewritableOut { - IOutputStream& Slave; - - char Last = 0; - bool Dirty = false; - - TRewritableOut(IOutputStream& sl) - : Slave(sl) - { - } - - template <typename T> - void Write(const T& t) { - Flush(); - Slave << t; - } - - void Hold(char c) { - if (Dirty) - Flush(); - Last = c; - Dirty = true; - } - - void Flush() { - if (Dirty) { - Slave << Last; - Dirty = false; - } - } - - void Revert() { + struct TRewritableOut { + IOutputStream& Slave; + + char Last = 0; + bool Dirty = false; + + TRewritableOut(IOutputStream& sl) + : Slave(sl) + { + } + + template <typename T> + void Write(const T& t) { + Flush(); + Slave << t; + } + + void Hold(char c) { + if (Dirty) + Flush(); + Last = c; + Dirty = true; + } + + void Flush() { + if (Dirty) { + Slave << Last; + Dirty = false; + } + } + + void Revert() { Dirty = false; } - }; - - struct TSpaces { - char S[256]; - - TSpaces() { - memset(&S, ' ', sizeof(S)); - } - - TStringBuf Get(ui8 sz) const { - return TStringBuf(S, sz); - } - }; - - bool TJsonPrettifier::MayUnquoteNew(TStringBuf s) { - static str_spn alpha("a-zA-Z_@$", true); - static str_spn alnum("a-zA-Z_@$0-9.-", true); - static TStringBuf true0("true"); - static TStringBuf false0("false"); - static TStringBuf null0("null"); - - return !!s && alpha.chars_table[(ui8)s[0]] && alnum.cbrk(s.begin() + 1, s.end()) == s.end() && !EqualToOneOf(s, null0, true0, false0); + }; + + struct TSpaces { + char S[256]; + + TSpaces() { + memset(&S, ' ', sizeof(S)); + } + + TStringBuf Get(ui8 sz) const { + return TStringBuf(S, sz); + } + }; + + bool TJsonPrettifier::MayUnquoteNew(TStringBuf s) { + static str_spn alpha("a-zA-Z_@$", true); + static str_spn alnum("a-zA-Z_@$0-9.-", true); + static TStringBuf true0("true"); + static TStringBuf false0("false"); + static TStringBuf null0("null"); + + return !!s && alpha.chars_table[(ui8)s[0]] && alnum.cbrk(s.begin() + 1, s.end()) == s.end() && !EqualToOneOf(s, null0, true0, false0); } - // to keep arcadia tests happy - bool TJsonPrettifier::MayUnquoteOld(TStringBuf s) { - static str_spn alpha("a-zA-Z_@$", true); - static str_spn alnum("a-zA-Z_@$0-9", true); - static TStringBuf true0("true"); - static TStringBuf false0("false"); - static TStringBuf true1("on"); - static TStringBuf false1("off"); - static TStringBuf true2("da"); - static TStringBuf false2("net"); - static TStringBuf null0("null"); - - return !!s && alpha.chars_table[(ui8)s[0]] && alnum.cbrk(s.begin() + 1, s.end()) == s.end() && !EqualToOneOf(s, null0, true0, false0, true1, false1, true2, false2); - } - - class TPrettifier: public TJsonCallbacks { - TRewritableOut Out; - TStringBuf Spaces; - TStringBuf Quote; - TStringBuf Unsafe; - TStringBuf Safe; - - ui32 Level = 0; - ui32 MaxPaddingLevel; - - bool Unquote = false; - bool Compactify = false; - bool NewUnquote = false; - - public: - TPrettifier(IOutputStream& out, const TJsonPrettifier& p) - : Out(out) - , MaxPaddingLevel(p.MaxPaddingLevel) - , Unquote(p.Unquote) - , Compactify(p.Compactify) - , NewUnquote(p.NewUnquote) - { - static TSpaces spaces; - Spaces = spaces.Get(p.Padding); - if (p.SingleQuotes) { - Quote = Unsafe = "'"; - Safe = "\""; - } else { - Quote = Unsafe = "\""; - Safe = "'"; - } - } - - void Pad(bool close = false) { - if (Compactify) { - Out.Flush(); - return; - } - if (Level > MaxPaddingLevel || (Level == MaxPaddingLevel && close)) { - Out.Write(" "); - return; - } - if (Level || close) { - Out.Write(Spaces ? "\n" : " "); - } - for (ui32 i = 0; i < Level; ++i) { - Out.Write(Spaces); - } - } - - void WriteSpace(char sp) { - if (Compactify) { - Out.Flush(); - return; - } - - Out.Write(sp); + // to keep arcadia tests happy + bool TJsonPrettifier::MayUnquoteOld(TStringBuf s) { + static str_spn alpha("a-zA-Z_@$", true); + static str_spn alnum("a-zA-Z_@$0-9", true); + static TStringBuf true0("true"); + static TStringBuf false0("false"); + static TStringBuf true1("on"); + static TStringBuf false1("off"); + static TStringBuf true2("da"); + static TStringBuf false2("net"); + static TStringBuf null0("null"); + + return !!s && alpha.chars_table[(ui8)s[0]] && alnum.cbrk(s.begin() + 1, s.end()) == s.end() && !EqualToOneOf(s, null0, true0, false0, true1, false1, true2, false2); + } + + class TPrettifier: public TJsonCallbacks { + TRewritableOut Out; + TStringBuf Spaces; + TStringBuf Quote; + TStringBuf Unsafe; + TStringBuf Safe; + + ui32 Level = 0; + ui32 MaxPaddingLevel; + + bool Unquote = false; + bool Compactify = false; + bool NewUnquote = false; + + public: + TPrettifier(IOutputStream& out, const TJsonPrettifier& p) + : Out(out) + , MaxPaddingLevel(p.MaxPaddingLevel) + , Unquote(p.Unquote) + , Compactify(p.Compactify) + , NewUnquote(p.NewUnquote) + { + static TSpaces spaces; + Spaces = spaces.Get(p.Padding); + if (p.SingleQuotes) { + Quote = Unsafe = "'"; + Safe = "\""; + } else { + Quote = Unsafe = "\""; + Safe = "'"; + } } - void OnVal() { - if (Out.Dirty && ':' == Out.Last) { - WriteSpace(' '); - } else { - Pad(); - } + void Pad(bool close = false) { + if (Compactify) { + Out.Flush(); + return; + } + if (Level > MaxPaddingLevel || (Level == MaxPaddingLevel && close)) { + Out.Write(" "); + return; + } + if (Level || close) { + Out.Write(Spaces ? "\n" : " "); + } + for (ui32 i = 0; i < Level; ++i) { + Out.Write(Spaces); + } } - - void AfterVal() { - Out.Hold(','); + + void WriteSpace(char sp) { + if (Compactify) { + Out.Flush(); + return; + } + + Out.Write(sp); + } + + void OnVal() { + if (Out.Dirty && ':' == Out.Last) { + WriteSpace(' '); + } else { + Pad(); + } } - - template <typename T> - bool WriteVal(const T& t) { - OnVal(); - Out.Write(t); - AfterVal(); - return true; + + void AfterVal() { + Out.Hold(','); + } + + template <typename T> + bool WriteVal(const T& t) { + OnVal(); + Out.Write(t); + AfterVal(); + return true; } - - bool OnNull() override { + + bool OnNull() override { return WriteVal(TStringBuf("null")); } - bool OnBoolean(bool v) override { + bool OnBoolean(bool v) override { return WriteVal(v ? TStringBuf("true") : TStringBuf("false")); } - bool OnInteger(long long i) override { - return WriteVal(i); - } + bool OnInteger(long long i) override { + return WriteVal(i); + } + + bool OnUInteger(unsigned long long i) override { + return WriteVal(i); + } + + bool OnDouble(double d) override { + return WriteVal(d); + } + + void WriteString(TStringBuf s) { + if (Unquote && (NewUnquote ? TJsonPrettifier::MayUnquoteNew(s) : TJsonPrettifier::MayUnquoteOld(s))) { + Out.Slave << s; + } else { + Out.Slave << Quote; + NEscJ::EscapeJ<false, true>(s, Out.Slave, Safe, Unsafe); + Out.Slave << Quote; + } + } + + bool OnString(const TStringBuf& s) override { + OnVal(); + WriteString(s); + AfterVal(); + return true; + } + + bool OnOpen(char c) { + OnVal(); + Level++; + Out.Hold(c); + return true; + } + + bool OnOpenMap() override { + return OnOpen('{'); + } + + bool OnOpenArray() override { + return OnOpen('['); + } + + bool OnMapKey(const TStringBuf& k) override { + OnVal(); + WriteString(k); + WriteSpace(' '); + Out.Hold(':'); + return true; + } + + bool OnClose(char c) { + if (!Level) + return false; + + Level--; + + if (Out.Dirty && c == Out.Last) { + WriteSpace(' '); + } else { + Out.Revert(); + Pad(true); + } + + return true; + } + + bool OnCloseMap() override { + if (!OnClose('{')) + return false; + Out.Write("}"); + AfterVal(); + return true; + } - bool OnUInteger(unsigned long long i) override { - return WriteVal(i); + bool OnCloseArray() override { + if (!OnClose('[')) + return false; + Out.Write("]"); + AfterVal(); + return true; } - bool OnDouble(double d) override { - return WriteVal(d); - } - - void WriteString(TStringBuf s) { - if (Unquote && (NewUnquote ? TJsonPrettifier::MayUnquoteNew(s) : TJsonPrettifier::MayUnquoteOld(s))) { - Out.Slave << s; - } else { - Out.Slave << Quote; - NEscJ::EscapeJ<false, true>(s, Out.Slave, Safe, Unsafe); - Out.Slave << Quote; - } - } - - bool OnString(const TStringBuf& s) override { - OnVal(); - WriteString(s); - AfterVal(); - return true; - } - - bool OnOpen(char c) { - OnVal(); - Level++; - Out.Hold(c); - return true; - } - - bool OnOpenMap() override { - return OnOpen('{'); - } - - bool OnOpenArray() override { - return OnOpen('['); - } - - bool OnMapKey(const TStringBuf& k) override { - OnVal(); - WriteString(k); - WriteSpace(' '); - Out.Hold(':'); - return true; + bool OnEnd() override { + return !Level; } + }; - bool OnClose(char c) { - if (!Level) - return false; - - Level--; - - if (Out.Dirty && c == Out.Last) { - WriteSpace(' '); - } else { - Out.Revert(); - Pad(true); - } - - return true; - } - - bool OnCloseMap() override { - if (!OnClose('{')) - return false; - Out.Write("}"); - AfterVal(); - return true; - } - - bool OnCloseArray() override { - if (!OnClose('[')) - return false; - Out.Write("]"); - AfterVal(); - return true; - } - - bool OnEnd() override { - return !Level; - } - }; - - bool TJsonPrettifier::Prettify(TStringBuf in, IOutputStream& out) const { - TPrettifier p(out, *this); - if (Strict) { + bool TJsonPrettifier::Prettify(TStringBuf in, IOutputStream& out) const { + TPrettifier p(out, *this); + if (Strict) { TMemoryInput mIn(in.data(), in.size()); - return ReadJson(&mIn, &p); + return ReadJson(&mIn, &p); } else { - return ReadJsonFast(in, &p); + return ReadJsonFast(in, &p); } } - TString TJsonPrettifier::Prettify(TStringBuf in) const { - TStringStream s; - if (Prettify(in, s)) - return s.Str(); - return TString(); + TString TJsonPrettifier::Prettify(TStringBuf in) const { + TStringStream s; + if (Prettify(in, s)) + return s.Str(); + return TString(); } } diff --git a/library/cpp/json/json_prettifier.h b/library/cpp/json/json_prettifier.h index 873942f11a..27d611b0b4 100644 --- a/library/cpp/json/json_prettifier.h +++ b/library/cpp/json/json_prettifier.h @@ -5,54 +5,54 @@ #include <util/generic/ylimits.h> namespace NJson { - struct TJsonPrettifier { - bool Unquote = false; - ui8 Padding = 4; - bool SingleQuotes = false; - bool Compactify = false; - bool Strict = false; - bool NewUnquote = false; // use new unquote, may break old tests - ui32 MaxPaddingLevel = Max<ui32>(); - - static TJsonPrettifier Prettifier(bool unquote = false, ui8 padding = 4, bool singlequotes = false) { - TJsonPrettifier p; - p.Unquote = unquote; - p.Padding = padding; - p.SingleQuotes = singlequotes; - return p; - } - - static TJsonPrettifier Compactifier(bool unquote = false, bool singlequote = false) { - TJsonPrettifier p; - p.Unquote = unquote; - p.Padding = 0; - p.Compactify = true; - p.SingleQuotes = singlequote; - return p; - } - - bool Prettify(TStringBuf in, IOutputStream& out) const; - - TString Prettify(TStringBuf in) const; - - static bool MayUnquoteNew(TStringBuf in); - static bool MayUnquoteOld(TStringBuf in); - }; - - inline TString PrettifyJson(TStringBuf in, bool unquote = false, ui8 padding = 4, bool sq = false) { - return TJsonPrettifier::Prettifier(unquote, padding, sq).Prettify(in); - } - - inline bool PrettifyJson(TStringBuf in, IOutputStream& out, bool unquote = false, ui8 padding = 4, bool sq = false) { - return TJsonPrettifier::Prettifier(unquote, padding, sq).Prettify(in, out); - } - - inline bool CompactifyJson(TStringBuf in, IOutputStream& out, bool unquote = false, bool sq = false) { - return TJsonPrettifier::Compactifier(unquote, sq).Prettify(in, out); - } - - inline TString CompactifyJson(TStringBuf in, bool unquote = false, bool sq = false) { - return TJsonPrettifier::Compactifier(unquote, sq).Prettify(in); - } + struct TJsonPrettifier { + bool Unquote = false; + ui8 Padding = 4; + bool SingleQuotes = false; + bool Compactify = false; + bool Strict = false; + bool NewUnquote = false; // use new unquote, may break old tests + ui32 MaxPaddingLevel = Max<ui32>(); + + static TJsonPrettifier Prettifier(bool unquote = false, ui8 padding = 4, bool singlequotes = false) { + TJsonPrettifier p; + p.Unquote = unquote; + p.Padding = padding; + p.SingleQuotes = singlequotes; + return p; + } + + static TJsonPrettifier Compactifier(bool unquote = false, bool singlequote = false) { + TJsonPrettifier p; + p.Unquote = unquote; + p.Padding = 0; + p.Compactify = true; + p.SingleQuotes = singlequote; + return p; + } + + bool Prettify(TStringBuf in, IOutputStream& out) const; + + TString Prettify(TStringBuf in) const; + + static bool MayUnquoteNew(TStringBuf in); + static bool MayUnquoteOld(TStringBuf in); + }; + + inline TString PrettifyJson(TStringBuf in, bool unquote = false, ui8 padding = 4, bool sq = false) { + return TJsonPrettifier::Prettifier(unquote, padding, sq).Prettify(in); + } + + inline bool PrettifyJson(TStringBuf in, IOutputStream& out, bool unquote = false, ui8 padding = 4, bool sq = false) { + return TJsonPrettifier::Prettifier(unquote, padding, sq).Prettify(in, out); + } + + inline bool CompactifyJson(TStringBuf in, IOutputStream& out, bool unquote = false, bool sq = false) { + return TJsonPrettifier::Compactifier(unquote, sq).Prettify(in, out); + } + + inline TString CompactifyJson(TStringBuf in, bool unquote = false, bool sq = false) { + return TJsonPrettifier::Compactifier(unquote, sq).Prettify(in); + } } diff --git a/library/cpp/json/json_reader.cpp b/library/cpp/json/json_reader.cpp index 87ec7d2742..072c8deafe 100644 --- a/library/cpp/json/json_reader.cpp +++ b/library/cpp/json/json_reader.cpp @@ -20,117 +20,117 @@ namespace NJson { } } - static const size_t DEFAULT_BUFFER_LEN = 65536; - - bool TParserCallbacks::OpenComplexValue(EJsonValueType type) { - TJsonValue* pvalue; - switch (CurrentState) { - case START: - Value.SetType(type); - ValuesStack.push_back(&Value); - break; - case IN_ARRAY: - pvalue = &ValuesStack.back()->AppendValue(type); - ValuesStack.push_back(pvalue); - break; - case AFTER_MAP_KEY: - pvalue = &ValuesStack.back()->InsertValue(Key, type); - ValuesStack.push_back(pvalue); - CurrentState = IN_MAP; - break; - default: - return false; - } - return true; - } - - bool TParserCallbacks::CloseComplexValue() { - if (ValuesStack.empty()) { + static const size_t DEFAULT_BUFFER_LEN = 65536; + + bool TParserCallbacks::OpenComplexValue(EJsonValueType type) { + TJsonValue* pvalue; + switch (CurrentState) { + case START: + Value.SetType(type); + ValuesStack.push_back(&Value); + break; + case IN_ARRAY: + pvalue = &ValuesStack.back()->AppendValue(type); + ValuesStack.push_back(pvalue); + break; + case AFTER_MAP_KEY: + pvalue = &ValuesStack.back()->InsertValue(Key, type); + ValuesStack.push_back(pvalue); + CurrentState = IN_MAP; + break; + default: + return false; + } + return true; + } + + bool TParserCallbacks::CloseComplexValue() { + if (ValuesStack.empty()) { return false; } - - ValuesStack.pop_back(); - if (!ValuesStack.empty()) { - switch (ValuesStack.back()->GetType()) { - case JSON_ARRAY: - CurrentState = IN_ARRAY; - break; - case JSON_MAP: - CurrentState = IN_MAP; - break; - default: - return false; - } - } else { - CurrentState = FINISH; - } - return true; + + ValuesStack.pop_back(); + if (!ValuesStack.empty()) { + switch (ValuesStack.back()->GetType()) { + case JSON_ARRAY: + CurrentState = IN_ARRAY; + break; + case JSON_MAP: + CurrentState = IN_MAP; + break; + default: + return false; + } + } else { + CurrentState = FINISH; + } + return true; } TParserCallbacks::TParserCallbacks(TJsonValue& value, bool throwOnError, bool notClosedBracketIsError) - : TJsonCallbacks(throwOnError) - , Value(value) + : TJsonCallbacks(throwOnError) + , Value(value) , NotClosedBracketIsError(notClosedBracketIsError) - , CurrentState(START) - { - } - - bool TParserCallbacks::OnNull() { - return SetValue(JSON_NULL); - } - - bool TParserCallbacks::OnBoolean(bool val) { - return SetValue(val); - } - - bool TParserCallbacks::OnInteger(long long val) { - return SetValue(val); - } - - bool TParserCallbacks::OnUInteger(unsigned long long val) { - return SetValue(val); - } - - bool TParserCallbacks::OnString(const TStringBuf& val) { - return SetValue(val); - } - - bool TParserCallbacks::OnDouble(double val) { - return SetValue(val); - } - - bool TParserCallbacks::OnOpenArray() { - bool res = OpenComplexValue(JSON_ARRAY); - if (res) - CurrentState = IN_ARRAY; - return res; - } - - bool TParserCallbacks::OnCloseArray() { - return CloseComplexValue(); - } - - bool TParserCallbacks::OnOpenMap() { - bool res = OpenComplexValue(JSON_MAP); - if (res) - CurrentState = IN_MAP; - return res; - } - - bool TParserCallbacks::OnCloseMap() { - return CloseComplexValue(); - } - - bool TParserCallbacks::OnMapKey(const TStringBuf& val) { - switch (CurrentState) { - case IN_MAP: - Key = val; - CurrentState = AFTER_MAP_KEY; - break; - default: - return false; - } - return true; + , CurrentState(START) + { + } + + bool TParserCallbacks::OnNull() { + return SetValue(JSON_NULL); + } + + bool TParserCallbacks::OnBoolean(bool val) { + return SetValue(val); + } + + bool TParserCallbacks::OnInteger(long long val) { + return SetValue(val); + } + + bool TParserCallbacks::OnUInteger(unsigned long long val) { + return SetValue(val); + } + + bool TParserCallbacks::OnString(const TStringBuf& val) { + return SetValue(val); + } + + bool TParserCallbacks::OnDouble(double val) { + return SetValue(val); + } + + bool TParserCallbacks::OnOpenArray() { + bool res = OpenComplexValue(JSON_ARRAY); + if (res) + CurrentState = IN_ARRAY; + return res; + } + + bool TParserCallbacks::OnCloseArray() { + return CloseComplexValue(); + } + + bool TParserCallbacks::OnOpenMap() { + bool res = OpenComplexValue(JSON_MAP); + if (res) + CurrentState = IN_MAP; + return res; + } + + bool TParserCallbacks::OnCloseMap() { + return CloseComplexValue(); + } + + bool TParserCallbacks::OnMapKey(const TStringBuf& val) { + switch (CurrentState) { + case IN_MAP: + Key = val; + CurrentState = AFTER_MAP_KEY; + break; + default: + return false; + } + return true; } bool TParserCallbacks::OnEnd() { @@ -140,182 +140,182 @@ namespace NJson { return true; } - TJsonReaderConfig::TJsonReaderConfig() - : BufferSize(DEFAULT_BUFFER_LEN) - { - } + TJsonReaderConfig::TJsonReaderConfig() + : BufferSize(DEFAULT_BUFFER_LEN) + { + } - void TJsonReaderConfig::SetBufferSize(size_t bufferSize) { - BufferSize = Max((size_t)1, Min(bufferSize, DEFAULT_BUFFER_LEN)); - } + void TJsonReaderConfig::SetBufferSize(size_t bufferSize) { + BufferSize = Max((size_t)1, Min(bufferSize, DEFAULT_BUFFER_LEN)); + } - size_t TJsonReaderConfig::GetBufferSize() const { - return BufferSize; - } + size_t TJsonReaderConfig::GetBufferSize() const { + return BufferSize; + } - namespace { - struct TJsonValueBuilder { + namespace { + struct TJsonValueBuilder { #ifdef NDEBUG - using TItem = TJsonValue*; + using TItem = TJsonValue*; - inline TJsonValue& Access(TItem& item) const { - return *item; - } + inline TJsonValue& Access(TItem& item) const { + return *item; + } #else - struct TItem { - TJsonValue* V; - size_t DuplicateKeyCount; - - TItem(TJsonValue* v) - : V(v) - , DuplicateKeyCount(0) - { - } - }; - - inline TJsonValue& Access(TItem& item) const { - return *item.V; + struct TItem { + TJsonValue* V; + size_t DuplicateKeyCount; + + TItem(TJsonValue* v) + : V(v) + , DuplicateKeyCount(0) + { + } + }; + + inline TJsonValue& Access(TItem& item) const { + return *item.V; } #endif - NJson::TJsonValue& V; - - TStack<TItem> S; - - TJsonValueBuilder(NJson::TJsonValue& v) - : V(v) - { - S.emplace(&V); - } - - template <class T> - void Set(const T& t) { - if (Access(S.top()).IsArray()) { - Access(S.top()).AppendValue(t); - } else { - Access(S.top()) = t; - S.pop(); - } - } - - bool Null() { - Set(NJson::JSON_NULL); - return true; - } - - bool Bool(bool b) { - Set(b); - return true; - } - - bool Int(int i) { - Set(i); - return true; - } - - template <class U> - bool ProcessUint(U u) { - if (Y_LIKELY(u <= static_cast<ui64>(Max<i64>()))) { - Set(i64(u)); - } else { - Set(u); - } - return true; - } - - bool Uint(unsigned u) { - return ProcessUint(u); - } - - bool Int64(i64 i) { - Set(i); - return true; - } - - bool Uint64(ui64 u) { - return ProcessUint(u); - } - - bool Double(double d) { - Set(d); - return true; - } - - bool RawNumber(const char* str, rapidjson::SizeType length, bool copy) { - Y_ASSERT(false && "this method should never be called"); - Y_UNUSED(str); - Y_UNUSED(length); - Y_UNUSED(copy); - return true; - } - - bool String(const char* str, rapidjson::SizeType length, bool copy) { - Y_ASSERT(copy); - Set(TStringBuf(str, length)); - return true; - } - - bool StartObject() { - if (Access(S.top()).IsArray()) { - S.emplace(&Access(S.top()).AppendValue(NJson::JSON_MAP)); - } else { - Access(S.top()).SetType(NJson::JSON_MAP); - } - return true; - } - - bool Key(const char* str, rapidjson::SizeType length, bool copy) { - Y_ASSERT(copy); - auto& value = Access(S.top())[TStringBuf(str, length)]; + NJson::TJsonValue& V; + + TStack<TItem> S; + + TJsonValueBuilder(NJson::TJsonValue& v) + : V(v) + { + S.emplace(&V); + } + + template <class T> + void Set(const T& t) { + if (Access(S.top()).IsArray()) { + Access(S.top()).AppendValue(t); + } else { + Access(S.top()) = t; + S.pop(); + } + } + + bool Null() { + Set(NJson::JSON_NULL); + return true; + } + + bool Bool(bool b) { + Set(b); + return true; + } + + bool Int(int i) { + Set(i); + return true; + } + + template <class U> + bool ProcessUint(U u) { + if (Y_LIKELY(u <= static_cast<ui64>(Max<i64>()))) { + Set(i64(u)); + } else { + Set(u); + } + return true; + } + + bool Uint(unsigned u) { + return ProcessUint(u); + } + + bool Int64(i64 i) { + Set(i); + return true; + } + + bool Uint64(ui64 u) { + return ProcessUint(u); + } + + bool Double(double d) { + Set(d); + return true; + } + + bool RawNumber(const char* str, rapidjson::SizeType length, bool copy) { + Y_ASSERT(false && "this method should never be called"); + Y_UNUSED(str); + Y_UNUSED(length); + Y_UNUSED(copy); + return true; + } + + bool String(const char* str, rapidjson::SizeType length, bool copy) { + Y_ASSERT(copy); + Set(TStringBuf(str, length)); + return true; + } + + bool StartObject() { + if (Access(S.top()).IsArray()) { + S.emplace(&Access(S.top()).AppendValue(NJson::JSON_MAP)); + } else { + Access(S.top()).SetType(NJson::JSON_MAP); + } + return true; + } + + bool Key(const char* str, rapidjson::SizeType length, bool copy) { + Y_ASSERT(copy); + auto& value = Access(S.top())[TStringBuf(str, length)]; if (Y_UNLIKELY(value.GetType() != JSON_UNDEFINED)) { #ifndef NDEBUG - ++S.top().DuplicateKeyCount; + ++S.top().DuplicateKeyCount; #endif - value.SetType(JSON_UNDEFINED); - } - S.emplace(&value); - return true; + value.SetType(JSON_UNDEFINED); + } + S.emplace(&value); + return true; } - inline int GetDuplicateKeyCount() const { + inline int GetDuplicateKeyCount() const { #ifdef NDEBUG - return 0; + return 0; #else - return S.top().DuplicateKeyCount; + return S.top().DuplicateKeyCount; #endif - } - - bool EndObject(rapidjson::SizeType memberCount) { - Y_ASSERT(memberCount == Access(S.top()).GetMap().size() + GetDuplicateKeyCount()); - S.pop(); - return true; - } - - bool StartArray() { - if (Access(S.top()).IsArray()) { - S.emplace(&Access(S.top()).AppendValue(NJson::JSON_ARRAY)); - } else { - Access(S.top()).SetType(NJson::JSON_ARRAY); - } - return true; - } - - bool EndArray(rapidjson::SizeType elementCount) { - Y_ASSERT(elementCount == Access(S.top()).GetArray().size()); - S.pop(); - return true; - } - }; - - template <class TRapidJsonCompliantInputStream, class THandler> - auto Read(const TJsonReaderConfig& config, - rapidjson::Reader& reader, - TRapidJsonCompliantInputStream& is, - THandler& handler) { + } + + bool EndObject(rapidjson::SizeType memberCount) { + Y_ASSERT(memberCount == Access(S.top()).GetMap().size() + GetDuplicateKeyCount()); + S.pop(); + return true; + } + + bool StartArray() { + if (Access(S.top()).IsArray()) { + S.emplace(&Access(S.top()).AppendValue(NJson::JSON_ARRAY)); + } else { + Access(S.top()).SetType(NJson::JSON_ARRAY); + } + return true; + } + + bool EndArray(rapidjson::SizeType elementCount) { + Y_ASSERT(elementCount == Access(S.top()).GetArray().size()); + S.pop(); + return true; + } + }; + + template <class TRapidJsonCompliantInputStream, class THandler> + auto Read(const TJsonReaderConfig& config, + rapidjson::Reader& reader, + TRapidJsonCompliantInputStream& is, + THandler& handler) { ui8 flags = ReaderConfigToRapidJsonFlags::NOCOMMENTS_VALID_NOESCAPE; - if (config.AllowComments) { + if (config.AllowComments) { flags |= ReaderConfigFlags::COMMENTS; } @@ -329,9 +329,9 @@ namespace NJson { switch (flags) { case ReaderConfigToRapidJsonFlags::COMMENTS_NOVALID_NOESCAPE: - return reader.Parse<rapidjson::kParseCommentsFlag>(is, handler); + return reader.Parse<rapidjson::kParseCommentsFlag>(is, handler); case ReaderConfigToRapidJsonFlags::COMMENTS_VALID_NOESCAPE: - return reader.Parse<rapidjson::kParseCommentsFlag | rapidjson::kParseValidateEncodingFlag>(is, handler); + return reader.Parse<rapidjson::kParseCommentsFlag | rapidjson::kParseValidateEncodingFlag>(is, handler); case ReaderConfigToRapidJsonFlags::COMMENTS_VALID_ESCAPE: return reader.Parse<rapidjson::kParseCommentsFlag | rapidjson::kParseValidateEncodingFlag | rapidjson::kParseEscapedApostropheFlag>(is, handler); case ReaderConfigToRapidJsonFlags::COMMENTS_NOVALID_ESCAPE: @@ -343,84 +343,84 @@ namespace NJson { case ReaderConfigToRapidJsonFlags::NOCOMMENTS_NOVALID_ESCAPE: return reader.Parse<rapidjson::kParseEscapedApostropheFlag>(is, handler); default: - return reader.Parse<rapidjson::kParseNoFlags>(is, handler); + return reader.Parse<rapidjson::kParseNoFlags>(is, handler); } } - template <class TRapidJsonCompliantInputStream, class THandler> - bool ReadJson(TRapidJsonCompliantInputStream& is, const TJsonReaderConfig* config, THandler& handler, bool throwOnError) { - rapidjson::Reader reader; - - auto result = Read(*config, reader, is, handler); - - if (result.IsError()) { - if (throwOnError) { + template <class TRapidJsonCompliantInputStream, class THandler> + bool ReadJson(TRapidJsonCompliantInputStream& is, const TJsonReaderConfig* config, THandler& handler, bool throwOnError) { + rapidjson::Reader reader; + + auto result = Read(*config, reader, is, handler); + + if (result.IsError()) { + if (throwOnError) { ythrow TJsonException() << PrintError(result); - } else { - return false; - } - } - + } else { + return false; + } + } + return true; } - template <class TRapidJsonCompliantInputStream> - bool ReadJsonTree(TRapidJsonCompliantInputStream& is, const TJsonReaderConfig* config, TJsonValue* out, bool throwOnError) { - out->SetType(NJson::JSON_NULL); - - TJsonValueBuilder handler(*out); - - return ReadJson(is, config, handler, throwOnError); + template <class TRapidJsonCompliantInputStream> + bool ReadJsonTree(TRapidJsonCompliantInputStream& is, const TJsonReaderConfig* config, TJsonValue* out, bool throwOnError) { + out->SetType(NJson::JSON_NULL); + + TJsonValueBuilder handler(*out); + + return ReadJson(is, config, handler, throwOnError); + } + + template <class TData> + bool ReadJsonTreeImpl(TData* in, const TJsonReaderConfig* config, TJsonValue* out, bool throwOnError) { + std::conditional_t<std::is_same<TData, TStringBuf>::value, TStringBufStreamWrapper, TInputStreamWrapper> is(*in); + return ReadJsonTree(is, config, out, throwOnError); + } + + template <class TData> + bool ReadJsonTreeImpl(TData* in, bool allowComments, TJsonValue* out, bool throwOnError) { + TJsonReaderConfig config; + config.AllowComments = allowComments; + return ReadJsonTreeImpl(in, &config, out, throwOnError); } - template <class TData> - bool ReadJsonTreeImpl(TData* in, const TJsonReaderConfig* config, TJsonValue* out, bool throwOnError) { - std::conditional_t<std::is_same<TData, TStringBuf>::value, TStringBufStreamWrapper, TInputStreamWrapper> is(*in); - return ReadJsonTree(is, config, out, throwOnError); - } - - template <class TData> - bool ReadJsonTreeImpl(TData* in, bool allowComments, TJsonValue* out, bool throwOnError) { - TJsonReaderConfig config; - config.AllowComments = allowComments; - return ReadJsonTreeImpl(in, &config, out, throwOnError); - } - - template <class TData> - bool ReadJsonTreeImpl(TData* in, TJsonValue* out, bool throwOnError) { - return ReadJsonTreeImpl(in, false, out, throwOnError); + template <class TData> + bool ReadJsonTreeImpl(TData* in, TJsonValue* out, bool throwOnError) { + return ReadJsonTreeImpl(in, false, out, throwOnError); } - } //namespace + } //namespace - bool ReadJsonTree(TStringBuf in, TJsonValue* out, bool throwOnError) { - return ReadJsonTreeImpl(&in, out, throwOnError); + bool ReadJsonTree(TStringBuf in, TJsonValue* out, bool throwOnError) { + return ReadJsonTreeImpl(&in, out, throwOnError); } - bool ReadJsonTree(TStringBuf in, bool allowComments, TJsonValue* out, bool throwOnError) { - return ReadJsonTreeImpl(&in, allowComments, out, throwOnError); - } + bool ReadJsonTree(TStringBuf in, bool allowComments, TJsonValue* out, bool throwOnError) { + return ReadJsonTreeImpl(&in, allowComments, out, throwOnError); + } - bool ReadJsonTree(TStringBuf in, const TJsonReaderConfig* config, TJsonValue* out, bool throwOnError) { - return ReadJsonTreeImpl(&in, config, out, throwOnError); + bool ReadJsonTree(TStringBuf in, const TJsonReaderConfig* config, TJsonValue* out, bool throwOnError) { + return ReadJsonTreeImpl(&in, config, out, throwOnError); } - bool ReadJsonTree(IInputStream* in, TJsonValue* out, bool throwOnError) { - return ReadJsonTreeImpl(in, out, throwOnError); + bool ReadJsonTree(IInputStream* in, TJsonValue* out, bool throwOnError) { + return ReadJsonTreeImpl(in, out, throwOnError); } - bool ReadJsonTree(IInputStream* in, bool allowComments, TJsonValue* out, bool throwOnError) { - return ReadJsonTreeImpl(in, allowComments, out, throwOnError); + bool ReadJsonTree(IInputStream* in, bool allowComments, TJsonValue* out, bool throwOnError) { + return ReadJsonTreeImpl(in, allowComments, out, throwOnError); } - bool ReadJsonTree(IInputStream* in, const TJsonReaderConfig* config, TJsonValue* out, bool throwOnError) { - return ReadJsonTreeImpl(in, config, out, throwOnError); + bool ReadJsonTree(IInputStream* in, const TJsonReaderConfig* config, TJsonValue* out, bool throwOnError) { + return ReadJsonTreeImpl(in, config, out, throwOnError); } bool ReadJsonFastTree(TStringBuf in, TJsonValue* out, bool throwOnError, bool notClosedBracketIsError) { TParserCallbacks cb(*out, throwOnError, notClosedBracketIsError); - return ReadJsonFast(in, &cb); - } + return ReadJsonFast(in, &cb); + } TJsonValue ReadJsonFastTree(TStringBuf in, bool notClosedBracketIsError) { TJsonValue value; @@ -429,99 +429,99 @@ namespace NJson { return value; } - namespace { - struct TJsonCallbacksWrapper { - TJsonCallbacks& Impl; - - TJsonCallbacksWrapper(TJsonCallbacks& impl) - : Impl(impl) - { - } - - bool Null() { - return Impl.OnNull(); - } - - bool Bool(bool b) { - return Impl.OnBoolean(b); - } - - template <class U> - bool ProcessUint(U u) { - if (Y_LIKELY(u <= ui64(Max<i64>()))) { - return Impl.OnInteger(i64(u)); - } else { - return Impl.OnUInteger(u); - } - } - - bool Int(int i) { - return Impl.OnInteger(i); - } - - bool Uint(unsigned u) { - return ProcessUint(u); - } - - bool Int64(i64 i) { - return Impl.OnInteger(i); - } - - bool Uint64(ui64 u) { - return ProcessUint(u); - } - - bool Double(double d) { - return Impl.OnDouble(d); - } - - bool RawNumber(const char* str, rapidjson::SizeType length, bool copy) { - Y_ASSERT(false && "this method should never be called"); - Y_UNUSED(str); - Y_UNUSED(length); - Y_UNUSED(copy); - return true; - } - - bool String(const char* str, rapidjson::SizeType length, bool copy) { - Y_ASSERT(copy); - return Impl.OnString(TStringBuf(str, length)); - } - - bool StartObject() { - return Impl.OnOpenMap(); - } - - bool Key(const char* str, rapidjson::SizeType length, bool copy) { - Y_ASSERT(copy); - return Impl.OnMapKey(TStringBuf(str, length)); - } - - bool EndObject(rapidjson::SizeType memberCount) { - Y_UNUSED(memberCount); - return Impl.OnCloseMap(); - } - - bool StartArray() { - return Impl.OnOpenArray(); - } - - bool EndArray(rapidjson::SizeType elementCount) { - Y_UNUSED(elementCount); - return Impl.OnCloseArray(); - } - }; - } - - bool ReadJson(IInputStream* in, TJsonCallbacks* cbs) { - return ReadJson(in, false, cbs); - } - - bool ReadJson(IInputStream* in, bool allowComments, TJsonCallbacks* cbs) { - TJsonReaderConfig config; - config.AllowComments = allowComments; - return ReadJson(in, &config, cbs); - } + namespace { + struct TJsonCallbacksWrapper { + TJsonCallbacks& Impl; + + TJsonCallbacksWrapper(TJsonCallbacks& impl) + : Impl(impl) + { + } + + bool Null() { + return Impl.OnNull(); + } + + bool Bool(bool b) { + return Impl.OnBoolean(b); + } + + template <class U> + bool ProcessUint(U u) { + if (Y_LIKELY(u <= ui64(Max<i64>()))) { + return Impl.OnInteger(i64(u)); + } else { + return Impl.OnUInteger(u); + } + } + + bool Int(int i) { + return Impl.OnInteger(i); + } + + bool Uint(unsigned u) { + return ProcessUint(u); + } + + bool Int64(i64 i) { + return Impl.OnInteger(i); + } + + bool Uint64(ui64 u) { + return ProcessUint(u); + } + + bool Double(double d) { + return Impl.OnDouble(d); + } + + bool RawNumber(const char* str, rapidjson::SizeType length, bool copy) { + Y_ASSERT(false && "this method should never be called"); + Y_UNUSED(str); + Y_UNUSED(length); + Y_UNUSED(copy); + return true; + } + + bool String(const char* str, rapidjson::SizeType length, bool copy) { + Y_ASSERT(copy); + return Impl.OnString(TStringBuf(str, length)); + } + + bool StartObject() { + return Impl.OnOpenMap(); + } + + bool Key(const char* str, rapidjson::SizeType length, bool copy) { + Y_ASSERT(copy); + return Impl.OnMapKey(TStringBuf(str, length)); + } + + bool EndObject(rapidjson::SizeType memberCount) { + Y_UNUSED(memberCount); + return Impl.OnCloseMap(); + } + + bool StartArray() { + return Impl.OnOpenArray(); + } + + bool EndArray(rapidjson::SizeType elementCount) { + Y_UNUSED(elementCount); + return Impl.OnCloseArray(); + } + }; + } + + bool ReadJson(IInputStream* in, TJsonCallbacks* cbs) { + return ReadJson(in, false, cbs); + } + + bool ReadJson(IInputStream* in, bool allowComments, TJsonCallbacks* cbs) { + TJsonReaderConfig config; + config.AllowComments = allowComments; + return ReadJson(in, &config, cbs); + } bool ReadJson(IInputStream* in, bool allowComments, bool allowEscapedApostrophe, TJsonCallbacks* cbs) { TJsonReaderConfig config; @@ -530,38 +530,38 @@ namespace NJson { return ReadJson(in, &config, cbs); } - bool ReadJson(IInputStream* in, const TJsonReaderConfig* config, TJsonCallbacks* cbs) { - TJsonCallbacksWrapper wrapper(*cbs); - TInputStreamWrapper is(*in); + bool ReadJson(IInputStream* in, const TJsonReaderConfig* config, TJsonCallbacks* cbs) { + TJsonCallbacksWrapper wrapper(*cbs); + TInputStreamWrapper is(*in); - rapidjson::Reader reader; - auto result = Read(*config, reader, is, wrapper); + rapidjson::Reader reader; + auto result = Read(*config, reader, is, wrapper); - if (result.IsError()) { + if (result.IsError()) { cbs->OnError(result.Offset(), PrintError(result)); - return false; + return false; } - return cbs->OnEnd(); - } - - TJsonValue ReadJsonTree(IInputStream* in, bool throwOnError) { - TJsonValue out; - ReadJsonTree(in, &out, throwOnError); - return out; - } - - TJsonValue ReadJsonTree(IInputStream* in, bool allowComments, bool throwOnError) { - TJsonValue out; - ReadJsonTree(in, allowComments, &out, throwOnError); - return out; - } - - TJsonValue ReadJsonTree(IInputStream* in, const TJsonReaderConfig* config, bool throwOnError) { - TJsonValue out; - ReadJsonTree(in, config, &out, throwOnError); - return out; + return cbs->OnEnd(); + } + + TJsonValue ReadJsonTree(IInputStream* in, bool throwOnError) { + TJsonValue out; + ReadJsonTree(in, &out, throwOnError); + return out; + } + + TJsonValue ReadJsonTree(IInputStream* in, bool allowComments, bool throwOnError) { + TJsonValue out; + ReadJsonTree(in, allowComments, &out, throwOnError); + return out; + } + + TJsonValue ReadJsonTree(IInputStream* in, const TJsonReaderConfig* config, bool throwOnError) { + TJsonValue out; + ReadJsonTree(in, config, &out, throwOnError); + return out; } } diff --git a/library/cpp/json/json_reader.h b/library/cpp/json/json_reader.h index 674b3f6abf..b673788330 100644 --- a/library/cpp/json/json_reader.h +++ b/library/cpp/json/json_reader.h @@ -4,7 +4,7 @@ #include <library/cpp/json/common/defs.h> #include <library/cpp/json/fast_sax/parser.h> - + #include <util/generic/yexception.h> #include <util/stream/input.h> @@ -12,37 +12,37 @@ #include <util/stream/mem.h> namespace NJson { - struct TJsonReaderConfig { - TJsonReaderConfig(); + struct TJsonReaderConfig { + TJsonReaderConfig(); - // js-style comments (both // and /**/) - bool AllowComments = false; - bool DontValidateUtf8 = false; + // js-style comments (both // and /**/) + bool AllowComments = false; + bool DontValidateUtf8 = false; bool AllowEscapedApostrophe = false; - void SetBufferSize(size_t bufferSize); - size_t GetBufferSize() const; + void SetBufferSize(size_t bufferSize); + size_t GetBufferSize() const; - private: - size_t BufferSize; - }; + private: + size_t BufferSize; + }; - bool ReadJsonTree(TStringBuf in, TJsonValue* out, bool throwOnError = false); - bool ReadJsonTree(TStringBuf in, bool allowComments, TJsonValue* out, bool throwOnError = false); - bool ReadJsonTree(TStringBuf in, const TJsonReaderConfig* config, TJsonValue* out, bool throwOnError = false); + bool ReadJsonTree(TStringBuf in, TJsonValue* out, bool throwOnError = false); + bool ReadJsonTree(TStringBuf in, bool allowComments, TJsonValue* out, bool throwOnError = false); + bool ReadJsonTree(TStringBuf in, const TJsonReaderConfig* config, TJsonValue* out, bool throwOnError = false); - bool ReadJsonTree(IInputStream* in, TJsonValue* out, bool throwOnError = false); - bool ReadJsonTree(IInputStream* in, bool allowComments, TJsonValue* out, bool throwOnError = false); - bool ReadJsonTree(IInputStream* in, const TJsonReaderConfig* config, TJsonValue* out, bool throwOnError = false); + bool ReadJsonTree(IInputStream* in, TJsonValue* out, bool throwOnError = false); + bool ReadJsonTree(IInputStream* in, bool allowComments, TJsonValue* out, bool throwOnError = false); + bool ReadJsonTree(IInputStream* in, const TJsonReaderConfig* config, TJsonValue* out, bool throwOnError = false); - TJsonValue ReadJsonTree(IInputStream* in, bool throwOnError = false); - TJsonValue ReadJsonTree(IInputStream* in, bool allowComments, bool throwOnError); - TJsonValue ReadJsonTree(IInputStream* in, const TJsonReaderConfig* config, bool throwOnError = false); + TJsonValue ReadJsonTree(IInputStream* in, bool throwOnError = false); + TJsonValue ReadJsonTree(IInputStream* in, bool allowComments, bool throwOnError); + TJsonValue ReadJsonTree(IInputStream* in, const TJsonReaderConfig* config, bool throwOnError = false); - bool ReadJson(IInputStream* in, TJsonCallbacks* callbacks); - bool ReadJson(IInputStream* in, bool allowComments, TJsonCallbacks* callbacks); + bool ReadJson(IInputStream* in, TJsonCallbacks* callbacks); + bool ReadJson(IInputStream* in, bool allowComments, TJsonCallbacks* callbacks); bool ReadJson(IInputStream* in, bool allowComments, bool allowEscapedApostrophe, TJsonCallbacks* callbacks); - bool ReadJson(IInputStream* in, const TJsonReaderConfig* config, TJsonCallbacks* callbacks); + bool ReadJson(IInputStream* in, const TJsonReaderConfig* config, TJsonCallbacks* callbacks); enum ReaderConfigFlags { COMMENTS = 0b100, @@ -60,79 +60,79 @@ namespace NJson { NOCOMMENTS_NOVALID_ESCAPE = 0b001, }; - inline bool ValidateJson(IInputStream* in, const TJsonReaderConfig* config, bool throwOnError = false) { - TJsonCallbacks c(throwOnError); - return ReadJson(in, config, &c); - } + inline bool ValidateJson(IInputStream* in, const TJsonReaderConfig* config, bool throwOnError = false) { + TJsonCallbacks c(throwOnError); + return ReadJson(in, config, &c); + } - inline bool ValidateJson(TStringBuf in, const TJsonReaderConfig& config = TJsonReaderConfig(), bool throwOnError = false) { + inline bool ValidateJson(TStringBuf in, const TJsonReaderConfig& config = TJsonReaderConfig(), bool throwOnError = false) { TMemoryInput min(in.data(), in.size()); - return ValidateJson(&min, &config, throwOnError); - } + return ValidateJson(&min, &config, throwOnError); + } - inline bool ValidateJsonThrow(IInputStream* in, const TJsonReaderConfig* config) { - return ValidateJson(in, config, true); - } + inline bool ValidateJsonThrow(IInputStream* in, const TJsonReaderConfig* config) { + return ValidateJson(in, config, true); + } - inline bool ValidateJsonThrow(TStringBuf in, const TJsonReaderConfig& config = TJsonReaderConfig()) { - return ValidateJson(in, config, true); - } + inline bool ValidateJsonThrow(TStringBuf in, const TJsonReaderConfig& config = TJsonReaderConfig()) { + return ValidateJson(in, config, true); + } - class TParserCallbacks: public TJsonCallbacks { - public: + class TParserCallbacks: public TJsonCallbacks { + public: TParserCallbacks(TJsonValue& value, bool throwOnError = false, bool notClosedBracketIsError = false); - bool OnNull() override; - bool OnBoolean(bool val) override; - bool OnInteger(long long val) override; - bool OnUInteger(unsigned long long val) override; - bool OnString(const TStringBuf& val) override; - bool OnDouble(double val) override; - bool OnOpenArray() override; - bool OnCloseArray() override; - bool OnOpenMap() override; - bool OnCloseMap() override; - bool OnMapKey(const TStringBuf& val) override; + bool OnNull() override; + bool OnBoolean(bool val) override; + bool OnInteger(long long val) override; + bool OnUInteger(unsigned long long val) override; + bool OnString(const TStringBuf& val) override; + bool OnDouble(double val) override; + bool OnOpenArray() override; + bool OnCloseArray() override; + bool OnOpenMap() override; + bool OnCloseMap() override; + bool OnMapKey(const TStringBuf& val) override; bool OnEnd() override; - protected: - TJsonValue& Value; - TString Key; - TVector<TJsonValue*> ValuesStack; + protected: + TJsonValue& Value; + TString Key; + TVector<TJsonValue*> ValuesStack; bool NotClosedBracketIsError; - enum { - START, - AFTER_MAP_KEY, - IN_MAP, - IN_ARRAY, - FINISH - } CurrentState; - - template <class T> - bool SetValue(const T& value) { - switch (CurrentState) { - case START: - Value.SetValue(value); - break; - case AFTER_MAP_KEY: - ValuesStack.back()->InsertValue(Key, value); - CurrentState = IN_MAP; - break; - case IN_ARRAY: - ValuesStack.back()->AppendValue(value); - break; - case IN_MAP: - case FINISH: - return false; - default: - ythrow yexception() << "TParserCallbacks::SetValue invalid enum"; - } - return true; + enum { + START, + AFTER_MAP_KEY, + IN_MAP, + IN_ARRAY, + FINISH + } CurrentState; + + template <class T> + bool SetValue(const T& value) { + switch (CurrentState) { + case START: + Value.SetValue(value); + break; + case AFTER_MAP_KEY: + ValuesStack.back()->InsertValue(Key, value); + CurrentState = IN_MAP; + break; + case IN_ARRAY: + ValuesStack.back()->AppendValue(value); + break; + case IN_MAP: + case FINISH: + return false; + default: + ythrow yexception() << "TParserCallbacks::SetValue invalid enum"; + } + return true; } - bool OpenComplexValue(EJsonValueType type); - bool CloseComplexValue(); - }; + bool OpenComplexValue(EJsonValueType type); + bool CloseComplexValue(); + }; //// relaxed json, used in library/cpp/scheme bool ReadJsonFastTree(TStringBuf in, TJsonValue* out, bool throwOnError = false, bool notClosedBracketIsError = false); diff --git a/library/cpp/json/json_writer.cpp b/library/cpp/json/json_writer.cpp index 140e1427d3..3d058bae36 100644 --- a/library/cpp/json/json_writer.cpp +++ b/library/cpp/json/json_writer.cpp @@ -6,144 +6,144 @@ #include <util/system/yassert.h> namespace NJson { - TJsonWriter::TJsonWriter(IOutputStream* out, bool formatOutput, bool sortkeys, bool validateUtf8) - : Out(out) - , Buf(NJsonWriter::HEM_UNSAFE) + TJsonWriter::TJsonWriter(IOutputStream* out, bool formatOutput, bool sortkeys, bool validateUtf8) + : Out(out) + , Buf(NJsonWriter::HEM_UNSAFE) , DoubleNDigits(TJsonWriterConfig::DefaultDoubleNDigits) , FloatNDigits(TJsonWriterConfig::DefaultFloatNDigits) , FloatToStringMode(TJsonWriterConfig::DefaultFloatToStringMode) - , SortKeys(sortkeys) - , ValidateUtf8(validateUtf8) - , DontEscapeStrings(false) - , DontFlushInDestructor(false) - { - Buf.SetIndentSpaces(formatOutput ? 2 : 0); - } - - TJsonWriter::TJsonWriter(IOutputStream* out, const TJsonWriterConfig& config, bool DFID) - : Out(config.Unbuffered ? nullptr : out) - , Buf(NJsonWriter::HEM_UNSAFE, config.Unbuffered ? out : nullptr) + , SortKeys(sortkeys) + , ValidateUtf8(validateUtf8) + , DontEscapeStrings(false) + , DontFlushInDestructor(false) + { + Buf.SetIndentSpaces(formatOutput ? 2 : 0); + } + + TJsonWriter::TJsonWriter(IOutputStream* out, const TJsonWriterConfig& config, bool DFID) + : Out(config.Unbuffered ? nullptr : out) + , Buf(NJsonWriter::HEM_UNSAFE, config.Unbuffered ? out : nullptr) , DoubleNDigits(config.DoubleNDigits) , FloatNDigits(config.FloatNDigits) , FloatToStringMode(config.FloatToStringMode) - , SortKeys(config.SortKeys) - , ValidateUtf8(config.ValidateUtf8) - , DontEscapeStrings(config.DontEscapeStrings) - , DontFlushInDestructor(DFID) - { - Buf.SetIndentSpaces(config.FormatOutput ? 2 : 0); - Buf.SetWriteNanAsString(config.WriteNanAsString); - } - - TJsonWriter::~TJsonWriter() { - // if we write to socket it's possible to get exception here - // don't use exceptions in destructors - if (!DontFlushInDestructor) { - try { - Flush(); - } catch (...) { - } - } - } - - void TJsonWriter::Flush() { - if (Out) { - Buf.FlushTo(Out); + , SortKeys(config.SortKeys) + , ValidateUtf8(config.ValidateUtf8) + , DontEscapeStrings(config.DontEscapeStrings) + , DontFlushInDestructor(DFID) + { + Buf.SetIndentSpaces(config.FormatOutput ? 2 : 0); + Buf.SetWriteNanAsString(config.WriteNanAsString); + } + + TJsonWriter::~TJsonWriter() { + // if we write to socket it's possible to get exception here + // don't use exceptions in destructors + if (!DontFlushInDestructor) { + try { + Flush(); + } catch (...) { + } + } + } + + void TJsonWriter::Flush() { + if (Out) { + Buf.FlushTo(Out); } - } + } - void TJsonWriter::OpenMap() { - Buf.BeginObject(); - } + void TJsonWriter::OpenMap() { + Buf.BeginObject(); + } - void TJsonWriter::CloseMap() { - Buf.EndObject(); - } + void TJsonWriter::CloseMap() { + Buf.EndObject(); + } - void TJsonWriter::OpenArray() { - Buf.BeginList(); - } + void TJsonWriter::OpenArray() { + Buf.BeginList(); + } - void TJsonWriter::CloseArray() { - Buf.EndList(); - } + void TJsonWriter::CloseArray() { + Buf.EndList(); + } - void TJsonWriter::Write(const TStringBuf& value) { - if (ValidateUtf8 && !IsUtf(value)) - throw yexception() << "JSON writer: invalid UTF-8"; - if (Buf.KeyExpected()) { - Buf.WriteKey(value); + void TJsonWriter::Write(const TStringBuf& value) { + if (ValidateUtf8 && !IsUtf(value)) + throw yexception() << "JSON writer: invalid UTF-8"; + if (Buf.KeyExpected()) { + Buf.WriteKey(value); } else { - if (DontEscapeStrings) { - Buf.UnsafeWriteValue(TString("\"") + value + '"'); - } else { - Buf.WriteString(value); - } + if (DontEscapeStrings) { + Buf.UnsafeWriteValue(TString("\"") + value + '"'); + } else { + Buf.WriteString(value); + } } } - void TJsonWriter::WriteNull() { - Buf.WriteNull(); - } + void TJsonWriter::WriteNull() { + Buf.WriteNull(); + } - void TJsonWriter::Write(float value) { + void TJsonWriter::Write(float value) { Buf.WriteFloat(value, FloatToStringMode, FloatNDigits); - } + } - void TJsonWriter::Write(double value) { + void TJsonWriter::Write(double value) { Buf.WriteDouble(value, FloatToStringMode, DoubleNDigits); - } + } - void TJsonWriter::Write(long long value) { - Buf.WriteLongLong(value); - } + void TJsonWriter::Write(long long value) { + Buf.WriteLongLong(value); + } - void TJsonWriter::Write(unsigned long long value) { - Buf.WriteULongLong(value); - } + void TJsonWriter::Write(unsigned long long value) { + Buf.WriteULongLong(value); + } - void TJsonWriter::Write(bool value) { - Buf.WriteBool(value); - } + void TJsonWriter::Write(bool value) { + Buf.WriteBool(value); + } - namespace { - struct TLessStrPtr { - bool operator()(const TString* a, const TString* b) const { - return *a < *b; - } - }; - } + namespace { + struct TLessStrPtr { + bool operator()(const TString* a, const TString* b) const { + return *a < *b; + } + }; + } - void TJsonWriter::Write(const TJsonValue* v) { + void TJsonWriter::Write(const TJsonValue* v) { Buf.WriteJsonValue(v, SortKeys, FloatToStringMode, DoubleNDigits); - } + } void TJsonWriter::Write(const TJsonValue& v) { Buf.WriteJsonValue(&v, SortKeys, FloatToStringMode, DoubleNDigits); } - TString WriteJson(const TJsonValue* value, bool formatOutput, bool sortkeys, bool validateUtf8) { - TStringStream ss; - WriteJson(&ss, value, formatOutput, sortkeys, validateUtf8); - return ss.Str(); - } - - TString WriteJson(const TJsonValue& value, bool formatOutput, bool sortkeys, bool validateUtf8) { - TStringStream ss; - WriteJson(&ss, &value, formatOutput, sortkeys, validateUtf8); - return ss.Str(); - } - - void WriteJson(IOutputStream* out, const TJsonValue* val, bool formatOutput, bool sortkeys, bool validateUtf8) { - TJsonWriter w(out, formatOutput, sortkeys, validateUtf8); - w.Write(val); - w.Flush(); - } - - void WriteJson(IOutputStream* out, const TJsonValue* val, const TJsonWriterConfig& config) { - TJsonWriter w(out, config, true); - w.Write(val); - w.Flush(); - } + TString WriteJson(const TJsonValue* value, bool formatOutput, bool sortkeys, bool validateUtf8) { + TStringStream ss; + WriteJson(&ss, value, formatOutput, sortkeys, validateUtf8); + return ss.Str(); + } + + TString WriteJson(const TJsonValue& value, bool formatOutput, bool sortkeys, bool validateUtf8) { + TStringStream ss; + WriteJson(&ss, &value, formatOutput, sortkeys, validateUtf8); + return ss.Str(); + } + + void WriteJson(IOutputStream* out, const TJsonValue* val, bool formatOutput, bool sortkeys, bool validateUtf8) { + TJsonWriter w(out, formatOutput, sortkeys, validateUtf8); + w.Write(val); + w.Flush(); + } + + void WriteJson(IOutputStream* out, const TJsonValue* val, const TJsonWriterConfig& config) { + TJsonWriter w(out, config, true); + w.Write(val); + w.Flush(); + } } diff --git a/library/cpp/json/json_writer.h b/library/cpp/json/json_writer.h index b56ba5e8a7..c7f5c9499a 100644 --- a/library/cpp/json/json_writer.h +++ b/library/cpp/json/json_writer.h @@ -12,148 +12,148 @@ #include <util/generic/strbuf.h> namespace NJson { - struct TJsonWriterConfig { + struct TJsonWriterConfig { constexpr static ui32 DefaultDoubleNDigits = 10; constexpr static ui32 DefaultFloatNDigits = 6; constexpr static EFloatToStringMode DefaultFloatToStringMode = PREC_NDIGITS; - inline TJsonWriterConfig& SetUnbuffered(bool v) noexcept { - Unbuffered = v; - - return *this; - } - - inline TJsonWriterConfig& SetValidateUtf8(bool v) noexcept { - ValidateUtf8 = v; - - return *this; - } - - inline TJsonWriterConfig& SetFormatOutput(bool v) noexcept { - FormatOutput = v; - - return *this; - } - + inline TJsonWriterConfig& SetUnbuffered(bool v) noexcept { + Unbuffered = v; + + return *this; + } + + inline TJsonWriterConfig& SetValidateUtf8(bool v) noexcept { + ValidateUtf8 = v; + + return *this; + } + + inline TJsonWriterConfig& SetFormatOutput(bool v) noexcept { + FormatOutput = v; + + return *this; + } + ui32 DoubleNDigits = DefaultDoubleNDigits; ui32 FloatNDigits = DefaultFloatNDigits; EFloatToStringMode FloatToStringMode = DefaultFloatToStringMode; - bool FormatOutput = false; - bool SortKeys = false; - bool ValidateUtf8 = true; - bool DontEscapeStrings = false; - bool Unbuffered = false; - bool WriteNanAsString = false; // NaN and Inf are not valid json values, so if WriteNanAsString is set, writer would write string intead of throwing exception (default case) - }; - - class TJsonWriter { - IOutputStream* Out; - NJsonWriter::TBuf Buf; + bool FormatOutput = false; + bool SortKeys = false; + bool ValidateUtf8 = true; + bool DontEscapeStrings = false; + bool Unbuffered = false; + bool WriteNanAsString = false; // NaN and Inf are not valid json values, so if WriteNanAsString is set, writer would write string intead of throwing exception (default case) + }; + + class TJsonWriter { + IOutputStream* Out; + NJsonWriter::TBuf Buf; const ui32 DoubleNDigits; const ui32 FloatNDigits; const EFloatToStringMode FloatToStringMode; - const bool SortKeys; - const bool ValidateUtf8; - const bool DontEscapeStrings; - const bool DontFlushInDestructor; - - public: - TJsonWriter(IOutputStream* out, bool formatOutput, bool sortkeys = false, bool validateUtf8 = true); - TJsonWriter(IOutputStream* out, const TJsonWriterConfig& config, bool DontFlushInDestructor = false); - ~TJsonWriter(); - - void Flush(); - - void OpenMap(); - void OpenMap(const TStringBuf& key) { - Buf.WriteKey(key); - OpenMap(); - } - void CloseMap(); - - void OpenArray(); - void OpenArray(const TStringBuf& key) { - Buf.WriteKey(key); - OpenArray(); - } - void CloseArray(); - - void WriteNull(); - - void Write(const TStringBuf& value); - void Write(float value); - void Write(double value); - void Write(bool value); - void Write(const TJsonValue* value); + const bool SortKeys; + const bool ValidateUtf8; + const bool DontEscapeStrings; + const bool DontFlushInDestructor; + + public: + TJsonWriter(IOutputStream* out, bool formatOutput, bool sortkeys = false, bool validateUtf8 = true); + TJsonWriter(IOutputStream* out, const TJsonWriterConfig& config, bool DontFlushInDestructor = false); + ~TJsonWriter(); + + void Flush(); + + void OpenMap(); + void OpenMap(const TStringBuf& key) { + Buf.WriteKey(key); + OpenMap(); + } + void CloseMap(); + + void OpenArray(); + void OpenArray(const TStringBuf& key) { + Buf.WriteKey(key); + OpenArray(); + } + void CloseArray(); + + void WriteNull(); + + void Write(const TStringBuf& value); + void Write(float value); + void Write(double value); + void Write(bool value); + void Write(const TJsonValue* value); void Write(const TJsonValue& value); - // must use all variations of integer types since long - // and long long are different types but with same size - void Write(long long value); - void Write(unsigned long long value); - void Write(long value) { - Write((long long)value); - } - void Write(unsigned long value) { - Write((unsigned long long)value); - } - void Write(int value) { - Write((long long)value); - } - void Write(unsigned int value) { - Write((unsigned long long)value); - } - void Write(short value) { - Write((long long)value); - } - void Write(unsigned short value) { - Write((unsigned long long)value); - } - - void Write(const unsigned char* value) { - Write((const char*)value); - } - void Write(const char* value) { - Write(TStringBuf(value)); - } - void Write(const TString& value) { - Write(TStringBuf(value)); - } - void Write(const std::string& value) { - Write(TStringBuf(value)); - } - - // write raw json without checks - void UnsafeWrite(const TStringBuf& value) { - Buf.UnsafeWriteValue(value); - } - - template <typename T> - void Write(const TStringBuf& key, const T& value) { - Buf.WriteKey(key); - Write(value); - } - - // write raw json without checks - void UnsafeWrite(const TStringBuf& key, const TStringBuf& value) { - Buf.WriteKey(key); - UnsafeWrite(value); - } - - void WriteNull(const TStringBuf& key) { - Buf.WriteKey(key); - WriteNull(); - } - - template <typename T> - void WriteOptional(const TStringBuf& key, const TMaybe<T>& value) { - if (value) { - Write(key, *value); - } - } - - void WriteOptional(const TStringBuf&, const TNothing&) { - // nothing to do + // must use all variations of integer types since long + // and long long are different types but with same size + void Write(long long value); + void Write(unsigned long long value); + void Write(long value) { + Write((long long)value); + } + void Write(unsigned long value) { + Write((unsigned long long)value); + } + void Write(int value) { + Write((long long)value); + } + void Write(unsigned int value) { + Write((unsigned long long)value); + } + void Write(short value) { + Write((long long)value); + } + void Write(unsigned short value) { + Write((unsigned long long)value); + } + + void Write(const unsigned char* value) { + Write((const char*)value); + } + void Write(const char* value) { + Write(TStringBuf(value)); + } + void Write(const TString& value) { + Write(TStringBuf(value)); + } + void Write(const std::string& value) { + Write(TStringBuf(value)); + } + + // write raw json without checks + void UnsafeWrite(const TStringBuf& value) { + Buf.UnsafeWriteValue(value); + } + + template <typename T> + void Write(const TStringBuf& key, const T& value) { + Buf.WriteKey(key); + Write(value); + } + + // write raw json without checks + void UnsafeWrite(const TStringBuf& key, const TStringBuf& value) { + Buf.WriteKey(key); + UnsafeWrite(value); + } + + void WriteNull(const TStringBuf& key) { + Buf.WriteKey(key); + WriteNull(); + } + + template <typename T> + void WriteOptional(const TStringBuf& key, const TMaybe<T>& value) { + if (value) { + Write(key, *value); + } + } + + void WriteOptional(const TStringBuf&, const TNothing&) { + // nothing to do } void WriteKey(const TStringBuf key) { @@ -172,25 +172,25 @@ namespace NJson { WriteKey(TStringBuf{key}); } - void WriteKey(const std::string& key) { - WriteKey(TStringBuf{key}); - } - - NJsonWriter::TBufState State() const { - return Buf.State(); - } + void WriteKey(const std::string& key) { + WriteKey(TStringBuf{key}); + } + + NJsonWriter::TBufState State() const { + return Buf.State(); + } - void Reset(const NJsonWriter::TBufState& from) { - return Buf.Reset(from); - } + void Reset(const NJsonWriter::TBufState& from) { + return Buf.Reset(from); + } - void Reset(NJsonWriter::TBufState&& from) { - return Buf.Reset(std::move(from)); - } - }; + void Reset(NJsonWriter::TBufState&& from) { + return Buf.Reset(std::move(from)); + } + }; - void WriteJson(IOutputStream*, const TJsonValue*, bool formatOutput = false, bool sortkeys = false, bool validateUtf8 = true); - TString WriteJson(const TJsonValue*, bool formatOutput = true, bool sortkeys = false, bool validateUtf8 = false); - TString WriteJson(const TJsonValue&, bool formatOutput = true, bool sortkeys = false, bool validateUtf8 = false); - void WriteJson(IOutputStream*, const TJsonValue*, const TJsonWriterConfig& config); + void WriteJson(IOutputStream*, const TJsonValue*, bool formatOutput = false, bool sortkeys = false, bool validateUtf8 = true); + TString WriteJson(const TJsonValue*, bool formatOutput = true, bool sortkeys = false, bool validateUtf8 = false); + TString WriteJson(const TJsonValue&, bool formatOutput = true, bool sortkeys = false, bool validateUtf8 = false); + void WriteJson(IOutputStream*, const TJsonValue*, const TJsonWriterConfig& config); } diff --git a/library/cpp/json/rapidjson_helpers.h b/library/cpp/json/rapidjson_helpers.h index 6adad9b32f..aeb96ff670 100644 --- a/library/cpp/json/rapidjson_helpers.h +++ b/library/cpp/json/rapidjson_helpers.h @@ -26,7 +26,7 @@ namespace NJson { } }; - struct TInputStreamWrapper : TReadOnlyStreamBase { + struct TInputStreamWrapper : TReadOnlyStreamBase { Ch Peek() const { if (!Eof) { if (Pos >= Sz) { @@ -77,7 +77,7 @@ namespace NJson { size_t Count; }; - struct TStringBufStreamWrapper : TReadOnlyStreamBase { + struct TStringBufStreamWrapper : TReadOnlyStreamBase { Ch Peek() const { return Pos < Data.size() ? Data[Pos] : 0; } diff --git a/library/cpp/json/ut/json_prettifier_ut.cpp b/library/cpp/json/ut/json_prettifier_ut.cpp index e2b51be062..ae5f8dd81a 100644 --- a/library/cpp/json/ut/json_prettifier_ut.cpp +++ b/library/cpp/json/ut/json_prettifier_ut.cpp @@ -36,78 +36,78 @@ Y_UNIT_TEST_SUITE(JsonPrettifier) { Y_UNIT_TEST(PrettifyJsonLong) { UNIT_ASSERT_STRINGS_EQUAL(NJson::PrettifyJson("[{k:v},{a:b}]", false, 2, true), - "[\n" - " {\n" - " 'k' : 'v'\n" - " },\n" - " {\n" - " 'a' : 'b'\n" - " }\n" - "]"); + "[\n" + " {\n" + " 'k' : 'v'\n" + " },\n" + " {\n" + " 'a' : 'b'\n" + " }\n" + "]"); UNIT_ASSERT_STRINGS_EQUAL(NJson::PrettifyJson("{k:v,a:b,x:[1,2,3]}", false, 2, true), - "{\n" - " 'k' : 'v',\n" - " 'a' : 'b',\n" - " 'x' : [\n" - " 1,\n" - " 2,\n" - " 3\n" - " ]\n" - "}"); + "{\n" + " 'k' : 'v',\n" + " 'a' : 'b',\n" + " 'x' : [\n" + " 1,\n" + " 2,\n" + " 3\n" + " ]\n" + "}"); UNIT_ASSERT_STRINGS_EQUAL(NJson::PrettifyJson("{k:v,a:b,x:[1,{f:b},3],m:n}", false, 2, true), - "{\n" - " 'k' : 'v',\n" - " 'a' : 'b',\n" - " 'x' : [\n" - " 1,\n" - " {\n" - " 'f' : 'b'\n" - " },\n" - " 3\n" - " ],\n" - " 'm' : 'n'\n" - "}"); + "{\n" + " 'k' : 'v',\n" + " 'a' : 'b',\n" + " 'x' : [\n" + " 1,\n" + " {\n" + " 'f' : 'b'\n" + " },\n" + " 3\n" + " ],\n" + " 'm' : 'n'\n" + "}"); NJson::TJsonPrettifier prettifierMaxLevel1 = NJson::TJsonPrettifier::Prettifier(false, 2, true); prettifierMaxLevel1.MaxPaddingLevel = 1; UNIT_ASSERT_STRINGS_EQUAL(prettifierMaxLevel1.Prettify("{k:v,a:b,x:[1,{f:b},3],m:n}"), - "{\n" - " 'k' : 'v',\n" - " 'a' : 'b',\n" - " 'x' : [ 1, { 'f' : 'b' }, 3 ],\n" - " 'm' : 'n'\n" - "}"); + "{\n" + " 'k' : 'v',\n" + " 'a' : 'b',\n" + " 'x' : [ 1, { 'f' : 'b' }, 3 ],\n" + " 'm' : 'n'\n" + "}"); UNIT_ASSERT_STRINGS_EQUAL(NJson::PrettifyJson("{g:{x:{a:{b:c,e:f},q:{x:y}},y:fff}}", true, 2), - "{\n" - " g : {\n" - " x : {\n" - " a : {\n" - " b : c,\n" - " e : f\n" - " },\n" - " q : {\n" - " x : y\n" - " }\n" - " },\n" - " y : fff\n" - " }\n" - "}"); + "{\n" + " g : {\n" + " x : {\n" + " a : {\n" + " b : c,\n" + " e : f\n" + " },\n" + " q : {\n" + " x : y\n" + " }\n" + " },\n" + " y : fff\n" + " }\n" + "}"); NJson::TJsonPrettifier prettifierMaxLevel3 = NJson::TJsonPrettifier::Prettifier(true, 2); prettifierMaxLevel3.MaxPaddingLevel = 3; UNIT_ASSERT_STRINGS_EQUAL(prettifierMaxLevel3.Prettify("{g:{x:{a:{b:c,e:f},q:{x:y}},y:fff}}"), - "{\n" - " g : {\n" - " x : {\n" - " a : { b : c, e : f },\n" - " q : { x : y }\n" - " },\n" - " y : fff\n" - " }\n" - "}"); + "{\n" + " g : {\n" + " x : {\n" + " a : { b : c, e : f },\n" + " q : { x : y }\n" + " },\n" + " y : fff\n" + " }\n" + "}"); } Y_UNIT_TEST(PrettifyJsonInvalid) { @@ -144,61 +144,61 @@ Y_UNIT_TEST_SUITE(JsonPrettifier) { Y_UNIT_TEST(CompactifyJsonLong) { UNIT_ASSERT_STRINGS_EQUAL(NJson::CompactifyJson( - "[\n" - " {\n" - " 'k' : 'v'\n" - " },\n" - " {\n" - " 'a' : 'b'\n" - " }\n" - "]", - true), - "[{k:v},{a:b}]"); + "[\n" + " {\n" + " 'k' : 'v'\n" + " },\n" + " {\n" + " 'a' : 'b'\n" + " }\n" + "]", + true), + "[{k:v},{a:b}]"); UNIT_ASSERT_STRINGS_EQUAL(NJson::CompactifyJson( - "{\n" - " 'k' : 'v',\n" - " 'a' : 'b',\n" - " 'x' : [\n" - " 1,\n" - " 2,\n" - " 3\n" - " ]\n" - "}", - true), - "{k:v,a:b,x:[1,2,3]}"); + "{\n" + " 'k' : 'v',\n" + " 'a' : 'b',\n" + " 'x' : [\n" + " 1,\n" + " 2,\n" + " 3\n" + " ]\n" + "}", + true), + "{k:v,a:b,x:[1,2,3]}"); UNIT_ASSERT_STRINGS_EQUAL(NJson::CompactifyJson( - "{\n" - " 'k' : 'v',\n" - " 'a' : 'b',\n" - " 'x' : [\n" - " 1,\n" - " {\n" - " 'f' : 'b'\n" - " },\n" - " 3\n" - " ],\n" - " 'm' : 'n'\n" - "}", - true), - "{k:v,a:b,x:[1,{f:b},3],m:n}"); + "{\n" + " 'k' : 'v',\n" + " 'a' : 'b',\n" + " 'x' : [\n" + " 1,\n" + " {\n" + " 'f' : 'b'\n" + " },\n" + " 3\n" + " ],\n" + " 'm' : 'n'\n" + "}", + true), + "{k:v,a:b,x:[1,{f:b},3],m:n}"); UNIT_ASSERT_STRINGS_EQUAL(NJson::CompactifyJson( - "{\n" - " g : {\n" - " x : {\n" - " a : {\n" - " b : c,\n" - " e : f\n" - " },\n" - " q : {\n" - " x : y\n" - " }\n" - " },\n" - " y : fff\n" - " }\n" - "}", - true), - "{g:{x:{a:{b:c,e:f},q:{x:y}},y:fff}}"); + "{\n" + " g : {\n" + " x : {\n" + " a : {\n" + " b : c,\n" + " e : f\n" + " },\n" + " q : {\n" + " x : y\n" + " }\n" + " },\n" + " y : fff\n" + " }\n" + "}", + true), + "{g:{x:{a:{b:c,e:f},q:{x:y}},y:fff}}"); } } diff --git a/library/cpp/json/ut/json_reader_fast_ut.cpp b/library/cpp/json/ut/json_reader_fast_ut.cpp index 4670975356..60dffc91c7 100644 --- a/library/cpp/json/ut/json_reader_fast_ut.cpp +++ b/library/cpp/json/ut/json_reader_fast_ut.cpp @@ -7,176 +7,176 @@ #include <util/string/printf.h> namespace NJson { - namespace NTest { - enum ETestEvent { - E_NO_EVENT = 0, - E_ERROR = 1, - E_DICT_OPEN, - E_DICT_CLOSE, - E_ARR_OPEN, - E_ARR_CLOSE, - E_NULL, - E_BOOL, - E_FLT, - E_INT, - E_LONG_LONG, - E_STR, - E_KEY - }; - - struct TEvent { - ETestEvent Type = E_NO_EVENT; - - i64 INum = 0; - double DNum = 0; - TString Str; - - TEvent(ETestEvent e = E_NO_EVENT) - : Type(e) - { - } - - TEvent(double v, ETestEvent e) - : Type(e) - , DNum(v) - { - } - - TEvent(i64 v, ETestEvent e) - : Type(e) - , INum(v) - { - } - - TEvent(TStringBuf t, ETestEvent e) - : Type(e) - , Str(NEscJ::EscapeJ<true, false>(t)) - { - } - - TString ToString() const { - switch (Type) { - default: - return "YOUFAILED"; - case E_ERROR: + namespace NTest { + enum ETestEvent { + E_NO_EVENT = 0, + E_ERROR = 1, + E_DICT_OPEN, + E_DICT_CLOSE, + E_ARR_OPEN, + E_ARR_CLOSE, + E_NULL, + E_BOOL, + E_FLT, + E_INT, + E_LONG_LONG, + E_STR, + E_KEY + }; + + struct TEvent { + ETestEvent Type = E_NO_EVENT; + + i64 INum = 0; + double DNum = 0; + TString Str; + + TEvent(ETestEvent e = E_NO_EVENT) + : Type(e) + { + } + + TEvent(double v, ETestEvent e) + : Type(e) + , DNum(v) + { + } + + TEvent(i64 v, ETestEvent e) + : Type(e) + , INum(v) + { + } + + TEvent(TStringBuf t, ETestEvent e) + : Type(e) + , Str(NEscJ::EscapeJ<true, false>(t)) + { + } + + TString ToString() const { + switch (Type) { + default: + return "YOUFAILED"; + case E_ERROR: return Sprintf("error: %s", Str.data()); - case E_DICT_OPEN: - return "{"; - case E_DICT_CLOSE: - return "}"; - case E_ARR_OPEN: - return "["; - case E_ARR_CLOSE: - return "]"; - case E_NULL: - return "null"; - case E_BOOL: - return INum ? "true" : "false"; - case E_INT: - return ::ToString(INum); - case E_FLT: - return ::ToString(DNum); - case E_STR: + case E_DICT_OPEN: + return "{"; + case E_DICT_CLOSE: + return "}"; + case E_ARR_OPEN: + return "["; + case E_ARR_CLOSE: + return "]"; + case E_NULL: + return "null"; + case E_BOOL: + return INum ? "true" : "false"; + case E_INT: + return ::ToString(INum); + case E_FLT: + return ::ToString(DNum); + case E_STR: return Sprintf("%s", Str.data()); - case E_KEY: + case E_KEY: return Sprintf("key: %s", Str.data()); - } - } - }; - - using TEvents = TVector<TEvent>; - - struct TTestHandler : TJsonCallbacks { - TEvents Events; - - bool OnOpenMap() override { - Events.push_back(E_DICT_OPEN); - return true; - } - - bool OnCloseMap() override { - Events.push_back(E_DICT_CLOSE); - return true; - } - - bool OnOpenArray() override { - Events.push_back(E_ARR_OPEN); - return true; - } - - bool OnCloseArray() override { - Events.push_back(E_ARR_CLOSE); - return true; - } - - bool OnNull() override { - Events.push_back(E_NULL); - return true; - } - - bool OnBoolean(bool v) override { - Events.push_back(TEvent((i64)v, E_BOOL)); - return true; - } - - bool OnInteger(long long v) override { - Events.push_back(TEvent((i64)v, E_INT)); - return true; - } - - bool OnUInteger(unsigned long long v) override { - return OnInteger(v); - } - - bool OnDouble(double v) override { - Events.push_back(TEvent(v, E_FLT)); - return true; - } - - bool OnString(const TStringBuf& v) override { - Events.push_back(TEvent(v, E_STR)); - return true; - } - - bool OnMapKey(const TStringBuf& v) override { - Events.push_back(TEvent(v, E_KEY)); - return true; - } - - void OnError(size_t, TStringBuf token) override { - Events.push_back(TEvent(token, E_ERROR)); - } - - void Assert(const TEvents& e, TString str) { - try { - UNIT_ASSERT_VALUES_EQUAL_C(e.size(), Events.size(), str); - - for (ui32 i = 0, sz = e.size(); i < sz; ++i) { + } + } + }; + + using TEvents = TVector<TEvent>; + + struct TTestHandler : TJsonCallbacks { + TEvents Events; + + bool OnOpenMap() override { + Events.push_back(E_DICT_OPEN); + return true; + } + + bool OnCloseMap() override { + Events.push_back(E_DICT_CLOSE); + return true; + } + + bool OnOpenArray() override { + Events.push_back(E_ARR_OPEN); + return true; + } + + bool OnCloseArray() override { + Events.push_back(E_ARR_CLOSE); + return true; + } + + bool OnNull() override { + Events.push_back(E_NULL); + return true; + } + + bool OnBoolean(bool v) override { + Events.push_back(TEvent((i64)v, E_BOOL)); + return true; + } + + bool OnInteger(long long v) override { + Events.push_back(TEvent((i64)v, E_INT)); + return true; + } + + bool OnUInteger(unsigned long long v) override { + return OnInteger(v); + } + + bool OnDouble(double v) override { + Events.push_back(TEvent(v, E_FLT)); + return true; + } + + bool OnString(const TStringBuf& v) override { + Events.push_back(TEvent(v, E_STR)); + return true; + } + + bool OnMapKey(const TStringBuf& v) override { + Events.push_back(TEvent(v, E_KEY)); + return true; + } + + void OnError(size_t, TStringBuf token) override { + Events.push_back(TEvent(token, E_ERROR)); + } + + void Assert(const TEvents& e, TString str) { + try { + UNIT_ASSERT_VALUES_EQUAL_C(e.size(), Events.size(), str); + + for (ui32 i = 0, sz = e.size(); i < sz; ++i) { UNIT_ASSERT_VALUES_EQUAL_C((int)e[i].Type, (int)Events[i].Type, Sprintf("'%s' %u", str.data(), i)); UNIT_ASSERT_VALUES_EQUAL_C(e[i].INum, Events[i].INum, Sprintf("'%s' %u", str.data(), i)); UNIT_ASSERT_VALUES_EQUAL_C(e[i].DNum, Events[i].DNum, Sprintf("'%s' %u", str.data(), i)); UNIT_ASSERT_VALUES_EQUAL_C(e[i].Str, Events[i].Str, Sprintf("'%s' %u", str.data(), i)); - } - } catch (const yexception&) { - Clog << "Exception at '" << str << "'" << Endl; - for (const auto& event : Events) { - Clog << event.ToString() << Endl; - } - - throw; - } + } + } catch (const yexception&) { + Clog << "Exception at '" << str << "'" << Endl; + for (const auto& event : Events) { + Clog << event.ToString() << Endl; + } + + throw; + } } - }; + }; } } -class TFastJsonTest: public TTestBase { - UNIT_TEST_SUITE(TFastJsonTest) +class TFastJsonTest: public TTestBase { + UNIT_TEST_SUITE(TFastJsonTest) UNIT_TEST(TestParse) UNIT_TEST(TestReadJsonFastTree) UNIT_TEST(TestNoInlineComment) - UNIT_TEST_SUITE_END(); - + UNIT_TEST_SUITE_END(); + public: template <bool accept> void DoTestParse(TStringBuf json, ui32 amount, ...) { @@ -188,45 +188,45 @@ public: ETestEvent e = (ETestEvent)va_arg(vl, int); switch ((int)e) { - case E_NO_EVENT: - case E_DICT_OPEN: - case E_DICT_CLOSE: - case E_ARR_OPEN: - case E_ARR_CLOSE: - case E_NULL: - evs.push_back(e); - break; - case E_BOOL: { - bool v = va_arg(vl, int); - evs.push_back(TEvent((i64)v, E_BOOL)); - break; - } - case E_INT: { - i64 i = va_arg(vl, int); - evs.push_back(TEvent(i, E_INT)); - break; - } - case E_LONG_LONG: { - i64 i = va_arg(vl, long long); - evs.push_back(TEvent(i, E_INT)); - break; - } - case E_FLT: { - double f = va_arg(vl, double); - evs.push_back(TEvent(f, E_FLT)); - break; - } - case E_STR: { - const char* s = va_arg(vl, const char*); - evs.push_back(TEvent(TStringBuf(s), E_STR)); - break; - } - case E_KEY: - case E_ERROR: { - const char* s = va_arg(vl, const char*); - evs.push_back(TEvent(TStringBuf(s), e)); - break; - } + case E_NO_EVENT: + case E_DICT_OPEN: + case E_DICT_CLOSE: + case E_ARR_OPEN: + case E_ARR_CLOSE: + case E_NULL: + evs.push_back(e); + break; + case E_BOOL: { + bool v = va_arg(vl, int); + evs.push_back(TEvent((i64)v, E_BOOL)); + break; + } + case E_INT: { + i64 i = va_arg(vl, int); + evs.push_back(TEvent(i, E_INT)); + break; + } + case E_LONG_LONG: { + i64 i = va_arg(vl, long long); + evs.push_back(TEvent(i, E_INT)); + break; + } + case E_FLT: { + double f = va_arg(vl, double); + evs.push_back(TEvent(f, E_FLT)); + break; + } + case E_STR: { + const char* s = va_arg(vl, const char*); + evs.push_back(TEvent(TStringBuf(s), E_STR)); + break; + } + case E_KEY: + case E_ERROR: { + const char* s = va_arg(vl, const char*); + evs.push_back(TEvent(TStringBuf(s), e)); + break; + } } } va_end(vl); @@ -258,25 +258,25 @@ public: DoTestParse<false>("[a,,b]", 3, E_ARR_OPEN, E_STR, "a", E_ERROR, "invalid syntax at token: ','"); DoTestParse<true>("{ k : v }", 4, E_DICT_OPEN, E_KEY, "k", E_STR, "v", E_DICT_CLOSE); DoTestParse<true>("{a:'\\b'/*comment*/, k /*comment*/\n : v }", 6, E_DICT_OPEN, E_KEY, "a", E_STR, "\b", E_KEY, "k", E_STR, "v", E_DICT_CLOSE); - DoTestParse<true>("{a:.15, k : v }", 6, E_DICT_OPEN, E_KEY, "a", E_FLT, .15, E_KEY, "k", E_STR, "v", E_DICT_CLOSE); - DoTestParse<true>("[ a, -.1e+5, 1E-7]", 5, E_ARR_OPEN, E_STR, "a", E_FLT, -.1e+5, E_FLT, 1e-7, E_ARR_CLOSE); + DoTestParse<true>("{a:.15, k : v }", 6, E_DICT_OPEN, E_KEY, "a", E_FLT, .15, E_KEY, "k", E_STR, "v", E_DICT_CLOSE); + DoTestParse<true>("[ a, -.1e+5, 1E-7]", 5, E_ARR_OPEN, E_STR, "a", E_FLT, -.1e+5, E_FLT, 1e-7, E_ARR_CLOSE); DoTestParse<true>("{}", 2, E_DICT_OPEN, E_DICT_CLOSE); - DoTestParse<true>("{ a : x, b : [ c, d, ] }", 9, E_DICT_OPEN, E_KEY, "a", E_STR, "x", E_KEY, "b", E_ARR_OPEN, E_STR, "c", E_STR, "d", E_ARR_CLOSE, E_DICT_CLOSE); - DoTestParse<false>("{ a : x, b : [ c, d,, ] }", 8, E_DICT_OPEN, E_KEY, "a", E_STR, "x", E_KEY, "b", E_ARR_OPEN, E_STR, "c", E_STR, "d", E_ERROR, "invalid syntax at token: ','"); - // DoTestParse<false>("{ a : x : y }", 4, E_DICT_OPEN - // , E_KEY, "a", E_STR, "x" - // , E_ERROR - // , ":"); - // DoTestParse<false>("{queries:{ref:[]},{nonref:[]}}", 8, E_DICT_OPEN - // , E_KEY, "queries", E_DICT_OPEN - // , E_KEY, "ref", E_ARR_OPEN, E_ARR_CLOSE - // , E_DICT_CLOSE, E_ERROR, ""); + DoTestParse<true>("{ a : x, b : [ c, d, ] }", 9, E_DICT_OPEN, E_KEY, "a", E_STR, "x", E_KEY, "b", E_ARR_OPEN, E_STR, "c", E_STR, "d", E_ARR_CLOSE, E_DICT_CLOSE); + DoTestParse<false>("{ a : x, b : [ c, d,, ] }", 8, E_DICT_OPEN, E_KEY, "a", E_STR, "x", E_KEY, "b", E_ARR_OPEN, E_STR, "c", E_STR, "d", E_ERROR, "invalid syntax at token: ','"); + // DoTestParse<false>("{ a : x : y }", 4, E_DICT_OPEN + // , E_KEY, "a", E_STR, "x" + // , E_ERROR + // , ":"); + // DoTestParse<false>("{queries:{ref:[]},{nonref:[]}}", 8, E_DICT_OPEN + // , E_KEY, "queries", E_DICT_OPEN + // , E_KEY, "ref", E_ARR_OPEN, E_ARR_CLOSE + // , E_DICT_CLOSE, E_ERROR, ""); DoTestParse<true>("'100x00'", 1, E_STR, "100x00"); DoTestParse<true>("-1", 1, E_INT, -1); DoTestParse<true>("-9223372036854775808", 1, E_LONG_LONG, (long long)Min<i64>()); DoTestParse<false>("100x00", 1, E_ERROR, "invalid syntax at token: '100x'"); DoTestParse<false>("100 200", 2, E_INT, 100, E_ERROR, "invalid syntax at token: '200'"); - DoTestParse<true>("{g:{x:{a:{b:c,e:f},q:{x:y}},y:fff}}", 22, E_DICT_OPEN, E_KEY, "g", E_DICT_OPEN, E_KEY, "x", E_DICT_OPEN, E_KEY, "a", E_DICT_OPEN, E_KEY, "b", E_STR, "c", E_KEY, "e", E_STR, "f", E_DICT_CLOSE, E_KEY, "q", E_DICT_OPEN, E_KEY, "x", E_STR, "y", E_DICT_CLOSE, E_DICT_CLOSE, E_KEY, "y", E_STR, "fff", E_DICT_CLOSE, E_DICT_CLOSE); + DoTestParse<true>("{g:{x:{a:{b:c,e:f},q:{x:y}},y:fff}}", 22, E_DICT_OPEN, E_KEY, "g", E_DICT_OPEN, E_KEY, "x", E_DICT_OPEN, E_KEY, "a", E_DICT_OPEN, E_KEY, "b", E_STR, "c", E_KEY, "e", E_STR, "f", E_DICT_CLOSE, E_KEY, "q", E_DICT_OPEN, E_KEY, "x", E_STR, "y", E_DICT_CLOSE, E_DICT_CLOSE, E_KEY, "y", E_STR, "fff", E_DICT_CLOSE, E_DICT_CLOSE); } void TestReadJsonFastTree() { diff --git a/library/cpp/json/ut/json_reader_ut.cpp b/library/cpp/json/ut/json_reader_ut.cpp index 958ed19730..cd31afa0b8 100644 --- a/library/cpp/json/ut/json_reader_ut.cpp +++ b/library/cpp/json/ut/json_reader_ut.cpp @@ -7,12 +7,12 @@ using namespace NJson; class TReformatCallbacks: public TJsonCallbacks { - TJsonWriter& Writer; - + TJsonWriter& Writer; + public: - TReformatCallbacks(TJsonWriter& writer) - : Writer(writer) - { + TReformatCallbacks(TJsonWriter& writer) + : Writer(writer) + { } bool OnBoolean(bool val) override { @@ -30,7 +30,7 @@ public: return true; } - bool OnString(const TStringBuf& val) override { + bool OnString(const TStringBuf& val) override { Writer.Write(val); return true; } @@ -60,7 +60,7 @@ public: return true; } - bool OnMapKey(const TStringBuf& val) override { + bool OnMapKey(const TStringBuf& val) override { Writer.Write(val); return true; } @@ -145,7 +145,7 @@ Y_UNIT_TEST_SUITE(TJsonReaderTest) { UNIT_ASSERT_VALUES_EQUAL(value["array"].GetStringRobust(), "[1,2,3,\"TString\"]"); UNIT_ASSERT_VALUES_EQUAL(value["null value"].GetStringRobust(), "null"); - const TJsonValue::TArray* array; + const TJsonValue::TArray* array; UNIT_ASSERT(GetArrayPointer(value, "array", &array)); UNIT_ASSERT_VALUES_EQUAL(value["array"].GetArray().size(), array->size()); UNIT_ASSERT_VALUES_EQUAL(value["array"][0].GetInteger(), (*array)[0].GetInteger()); @@ -353,7 +353,7 @@ Y_UNIT_TEST_SUITE(TJsonReaderTest) { UNIT_ASSERT_EQUAL(value["test"].GetDouble(), 0.0); UNIT_ASSERT_EQUAL(value["test"].GetDoubleRobust(), static_cast<double>(Max<ui64>())); } // Max<ui64>() - } // TJsonDoubleTest + } // TJsonDoubleTest Y_UNIT_TEST(TJsonInvalidTest) { { @@ -397,34 +397,34 @@ Y_UNIT_TEST_SUITE(TJsonReaderTest) { UNIT_ASSERT_VALUES_EQUAL("", v.GetMap().begin()->second.GetString()); } } - - -static const TString YANDEX_STREAMING_JSON("{\"a\":1}//d{\"b\":2}"); - - -Y_UNIT_TEST_SUITE(TCompareReadJsonFast) { - Y_UNIT_TEST(NoEndl) { - NJson::TJsonValue parsed; - - bool success = NJson::ReadJsonTree(YANDEX_STREAMING_JSON, &parsed, false); - bool fast_success = NJson::ReadJsonFastTree(YANDEX_STREAMING_JSON, &parsed, false); - UNIT_ASSERT(success == fast_success); - } - Y_UNIT_TEST(WithEndl) { - NJson::TJsonValue parsed1; - NJson::TJsonValue parsed2; - - bool success = NJson::ReadJsonTree(YANDEX_STREAMING_JSON + "\n", &parsed1, false); - bool fast_success = NJson::ReadJsonFastTree(YANDEX_STREAMING_JSON + "\n", &parsed2, false); - - UNIT_ASSERT_VALUES_EQUAL(success, fast_success); - } - Y_UNIT_TEST(NoQuotes) { - TString streamingJson = "{a:1}"; - NJson::TJsonValue parsed; - - bool success = NJson::ReadJsonTree(streamingJson, &parsed, false); - bool fast_success = NJson::ReadJsonFastTree(streamingJson, &parsed, false); - UNIT_ASSERT(success != fast_success); - } -} + + +static const TString YANDEX_STREAMING_JSON("{\"a\":1}//d{\"b\":2}"); + + +Y_UNIT_TEST_SUITE(TCompareReadJsonFast) { + Y_UNIT_TEST(NoEndl) { + NJson::TJsonValue parsed; + + bool success = NJson::ReadJsonTree(YANDEX_STREAMING_JSON, &parsed, false); + bool fast_success = NJson::ReadJsonFastTree(YANDEX_STREAMING_JSON, &parsed, false); + UNIT_ASSERT(success == fast_success); + } + Y_UNIT_TEST(WithEndl) { + NJson::TJsonValue parsed1; + NJson::TJsonValue parsed2; + + bool success = NJson::ReadJsonTree(YANDEX_STREAMING_JSON + "\n", &parsed1, false); + bool fast_success = NJson::ReadJsonFastTree(YANDEX_STREAMING_JSON + "\n", &parsed2, false); + + UNIT_ASSERT_VALUES_EQUAL(success, fast_success); + } + Y_UNIT_TEST(NoQuotes) { + TString streamingJson = "{a:1}"; + NJson::TJsonValue parsed; + + bool success = NJson::ReadJsonTree(streamingJson, &parsed, false); + bool fast_success = NJson::ReadJsonFastTree(streamingJson, &parsed, false); + UNIT_ASSERT(success != fast_success); + } +} diff --git a/library/cpp/json/ut/json_writer_ut.cpp b/library/cpp/json/ut/json_writer_ut.cpp index 0fe747d704..ca11d34dad 100644 --- a/library/cpp/json/ut/json_writer_ut.cpp +++ b/library/cpp/json/ut/json_writer_ut.cpp @@ -8,7 +8,7 @@ using namespace NJson; Y_UNIT_TEST_SUITE(TJsonWriterTest) { Y_UNIT_TEST(SimpleWriteTest) { TString expected1 = "{\"key1\":1,\"key2\":2,\"key3\":3"; - TString expected2 = expected1 + ",\"array\":[\"stroka\",false]"; + TString expected2 = expected1 + ",\"array\":[\"stroka\",false]"; TString expected3 = expected2 + "}"; TStringStream out; @@ -120,7 +120,7 @@ Y_UNIT_TEST_SUITE(TJsonWriterTest) { WriteJson(&out, &v); UNIT_ASSERT_VALUES_EQUAL(out.Str(), expected); } // 18446744073709551615 - } // SimpleUnsignedIntegerWriteTest + } // SimpleUnsignedIntegerWriteTest Y_UNIT_TEST(WriteOptionalTest) { { diff --git a/library/cpp/json/ut/ya.make b/library/cpp/json/ut/ya.make index 5f3a2d8510..8e0362d84b 100644 --- a/library/cpp/json/ut/ya.make +++ b/library/cpp/json/ut/ya.make @@ -2,10 +2,10 @@ OWNER(velavokr) UNITTEST_FOR(library/cpp/json) -PEERDIR( +PEERDIR( library/cpp/string_utils/relaxed_escaper -) - +) + SRCS( json_reader_fast_ut.cpp json_reader_ut.cpp diff --git a/library/cpp/json/writer/json.cpp b/library/cpp/json/writer/json.cpp index 6bad7cf3a9..02370c2d79 100644 --- a/library/cpp/json/writer/json.cpp +++ b/library/cpp/json/writer/json.cpp @@ -1,94 +1,94 @@ #include "json.h" - + #include <library/cpp/json/json_value.h> - + #include <util/string/cast.h> -#include <util/string/strspn.h> +#include <util/string/strspn.h> #include <util/generic/algorithm.h> #include <util/generic/ymath.h> -#include <util/generic/singleton.h> +#include <util/generic/singleton.h> namespace NJsonWriter { - TBuf::TBuf(EHtmlEscapeMode mode, IOutputStream* stream) - : Stream(stream) - , NeedComma(false) - , NeedNewline(false) - , EscapeMode(mode) - , IndentSpaces(0) - , WriteNanAsString(false) - { - Y_ASSERT(mode == HEM_DONT_ESCAPE_HTML || - mode == HEM_ESCAPE_HTML || - mode == HEM_RELAXED || - mode == HEM_UNSAFE); - if (!Stream) { - StringStream.Reset(new TStringStream); - Stream = StringStream.Get(); - } - - Stack.reserve(64); // should be enough for most cases - StackPush(JE_OUTER_SPACE); - } - - static const char* EntityToStr(EJsonEntity e) { - switch (e) { - case JE_OUTER_SPACE: - return "JE_OUTER_SPACE"; - case JE_LIST: - return "JE_LIST"; - case JE_OBJECT: - return "JE_OBJECT"; - case JE_PAIR: - return "JE_PAIR"; - default: - return "JE_unknown"; - } - } - - inline void TBuf::StackPush(EJsonEntity e) { - Stack.push_back(e); - } - - inline EJsonEntity TBuf::StackTop() const { - return Stack.back(); - } - - inline void TBuf::StackPop() { - Y_ASSERT(!Stack.empty()); - const EJsonEntity current = StackTop(); - Stack.pop_back(); - switch (current) { - case JE_OUTER_SPACE: - ythrow TError() << "JSON writer: stack empty"; - case JE_LIST: - PrintIndentation(true); - RawWriteChar(']'); - break; - case JE_OBJECT: - PrintIndentation(true); - RawWriteChar('}'); - break; - case JE_PAIR: - break; - } - NeedComma = true; - NeedNewline = true; - } - - inline void TBuf::CheckAndPop(EJsonEntity e) { - if (Y_UNLIKELY(StackTop() != e)) { - ythrow TError() << "JSON writer: unexpected value " - << EntityToStr(StackTop()) << " on the stack"; - } - StackPop(); - } - - void TBuf::PrintIndentation(bool closing) { - if (!IndentSpaces) - return; - const int indentation = IndentSpaces * (Stack.size() - 1); - if (!indentation && !closing) - return; + TBuf::TBuf(EHtmlEscapeMode mode, IOutputStream* stream) + : Stream(stream) + , NeedComma(false) + , NeedNewline(false) + , EscapeMode(mode) + , IndentSpaces(0) + , WriteNanAsString(false) + { + Y_ASSERT(mode == HEM_DONT_ESCAPE_HTML || + mode == HEM_ESCAPE_HTML || + mode == HEM_RELAXED || + mode == HEM_UNSAFE); + if (!Stream) { + StringStream.Reset(new TStringStream); + Stream = StringStream.Get(); + } + + Stack.reserve(64); // should be enough for most cases + StackPush(JE_OUTER_SPACE); + } + + static const char* EntityToStr(EJsonEntity e) { + switch (e) { + case JE_OUTER_SPACE: + return "JE_OUTER_SPACE"; + case JE_LIST: + return "JE_LIST"; + case JE_OBJECT: + return "JE_OBJECT"; + case JE_PAIR: + return "JE_PAIR"; + default: + return "JE_unknown"; + } + } + + inline void TBuf::StackPush(EJsonEntity e) { + Stack.push_back(e); + } + + inline EJsonEntity TBuf::StackTop() const { + return Stack.back(); + } + + inline void TBuf::StackPop() { + Y_ASSERT(!Stack.empty()); + const EJsonEntity current = StackTop(); + Stack.pop_back(); + switch (current) { + case JE_OUTER_SPACE: + ythrow TError() << "JSON writer: stack empty"; + case JE_LIST: + PrintIndentation(true); + RawWriteChar(']'); + break; + case JE_OBJECT: + PrintIndentation(true); + RawWriteChar('}'); + break; + case JE_PAIR: + break; + } + NeedComma = true; + NeedNewline = true; + } + + inline void TBuf::CheckAndPop(EJsonEntity e) { + if (Y_UNLIKELY(StackTop() != e)) { + ythrow TError() << "JSON writer: unexpected value " + << EntityToStr(StackTop()) << " on the stack"; + } + StackPop(); + } + + void TBuf::PrintIndentation(bool closing) { + if (!IndentSpaces) + return; + const int indentation = IndentSpaces * (Stack.size() - 1); + if (!indentation && !closing) + return; PrintWhitespaces(Max(0, indentation), true); } @@ -107,258 +107,258 @@ namespace NJsonWriter { } while (count > 0); } - inline void TBuf::WriteComma() { - if (NeedComma) { - RawWriteChar(','); - } - NeedComma = true; - - if (NeedNewline) { - PrintIndentation(false); - } - NeedNewline = true; - } - - inline void TBuf::BeginValue() { - if (Y_UNLIKELY(KeyExpected())) { - ythrow TError() << "JSON writer: value written, " - "but expected a key:value pair"; - } - WriteComma(); - } - - inline void TBuf::BeginKey() { - if (Y_UNLIKELY(!KeyExpected())) { - ythrow TError() << "JSON writer: key written outside of an object"; - } - WriteComma(); - StackPush(JE_PAIR); - NeedComma = false; - NeedNewline = false; - } - - inline void TBuf::EndValue() { - if (StackTop() == JE_PAIR) { - StackPop(); - } - } - - TValueContext TBuf::BeginList() { - NeedNewline = true; - BeginValue(); - RawWriteChar('['); - StackPush(JE_LIST); - NeedComma = false; - return TValueContext(*this); - } - - TPairContext TBuf::BeginObject() { - NeedNewline = true; - BeginValue(); - RawWriteChar('{'); - StackPush(JE_OBJECT); - NeedComma = false; - return TPairContext(*this); - } - - TAfterColonContext TBuf::UnsafeWriteKey(const TStringBuf& s) { - BeginKey(); - RawWriteChar('"'); - UnsafeWriteRawBytes(s); - UnsafeWriteRawBytes("\":", 2); - return TAfterColonContext(*this); - } - - TAfterColonContext TBuf::WriteKey(const TStringBuf& s) { - // use the default escaping mode for this object - return WriteKey(s, EscapeMode); - } - - TAfterColonContext TBuf::WriteKey(const TStringBuf& s, EHtmlEscapeMode hem) { - BeginKey(); - WriteBareString(s, hem); - RawWriteChar(':'); - return TAfterColonContext(*this); - } - - TAfterColonContext TBuf::CompatWriteKeyWithoutQuotes(const TStringBuf& s) { - BeginKey(); - Y_ASSERT(AllOf(s, [](char x) { return 'a' <= x && x <= 'z'; })); - UnsafeWriteRawBytes(s); - RawWriteChar(':'); - return TAfterColonContext(*this); - } - - TBuf& TBuf::EndList() { - CheckAndPop(JE_LIST); - EndValue(); - return *this; - } - - TBuf& TBuf::EndObject() { - CheckAndPop(JE_OBJECT); - EndValue(); - return *this; - } - - TValueContext TBuf::WriteString(const TStringBuf& s) { - // use the default escaping mode for this object - return WriteString(s, EscapeMode); - } - - TValueContext TBuf::WriteString(const TStringBuf& s, EHtmlEscapeMode hem) { - BeginValue(); - WriteBareString(s, hem); - EndValue(); - return TValueContext(*this); - } - - TValueContext TBuf::WriteNull() { + inline void TBuf::WriteComma() { + if (NeedComma) { + RawWriteChar(','); + } + NeedComma = true; + + if (NeedNewline) { + PrintIndentation(false); + } + NeedNewline = true; + } + + inline void TBuf::BeginValue() { + if (Y_UNLIKELY(KeyExpected())) { + ythrow TError() << "JSON writer: value written, " + "but expected a key:value pair"; + } + WriteComma(); + } + + inline void TBuf::BeginKey() { + if (Y_UNLIKELY(!KeyExpected())) { + ythrow TError() << "JSON writer: key written outside of an object"; + } + WriteComma(); + StackPush(JE_PAIR); + NeedComma = false; + NeedNewline = false; + } + + inline void TBuf::EndValue() { + if (StackTop() == JE_PAIR) { + StackPop(); + } + } + + TValueContext TBuf::BeginList() { + NeedNewline = true; + BeginValue(); + RawWriteChar('['); + StackPush(JE_LIST); + NeedComma = false; + return TValueContext(*this); + } + + TPairContext TBuf::BeginObject() { + NeedNewline = true; + BeginValue(); + RawWriteChar('{'); + StackPush(JE_OBJECT); + NeedComma = false; + return TPairContext(*this); + } + + TAfterColonContext TBuf::UnsafeWriteKey(const TStringBuf& s) { + BeginKey(); + RawWriteChar('"'); + UnsafeWriteRawBytes(s); + UnsafeWriteRawBytes("\":", 2); + return TAfterColonContext(*this); + } + + TAfterColonContext TBuf::WriteKey(const TStringBuf& s) { + // use the default escaping mode for this object + return WriteKey(s, EscapeMode); + } + + TAfterColonContext TBuf::WriteKey(const TStringBuf& s, EHtmlEscapeMode hem) { + BeginKey(); + WriteBareString(s, hem); + RawWriteChar(':'); + return TAfterColonContext(*this); + } + + TAfterColonContext TBuf::CompatWriteKeyWithoutQuotes(const TStringBuf& s) { + BeginKey(); + Y_ASSERT(AllOf(s, [](char x) { return 'a' <= x && x <= 'z'; })); + UnsafeWriteRawBytes(s); + RawWriteChar(':'); + return TAfterColonContext(*this); + } + + TBuf& TBuf::EndList() { + CheckAndPop(JE_LIST); + EndValue(); + return *this; + } + + TBuf& TBuf::EndObject() { + CheckAndPop(JE_OBJECT); + EndValue(); + return *this; + } + + TValueContext TBuf::WriteString(const TStringBuf& s) { + // use the default escaping mode for this object + return WriteString(s, EscapeMode); + } + + TValueContext TBuf::WriteString(const TStringBuf& s, EHtmlEscapeMode hem) { + BeginValue(); + WriteBareString(s, hem); + EndValue(); + return TValueContext(*this); + } + + TValueContext TBuf::WriteNull() { UnsafeWriteValue(TStringBuf("null")); - return TValueContext(*this); - } + return TValueContext(*this); + } - TValueContext TBuf::WriteBool(bool b) { + TValueContext TBuf::WriteBool(bool b) { constexpr TStringBuf trueVal = "true"; constexpr TStringBuf falseVal = "false"; UnsafeWriteValue(b ? trueVal : falseVal); - return TValueContext(*this); - } - - TValueContext TBuf::WriteInt(int i) { - char buf[22]; // enough to hold any 64-bit number - size_t len = ToString(i, buf, sizeof(buf)); - UnsafeWriteValue(buf, len); - return TValueContext(*this); - } - - TValueContext TBuf::WriteLongLong(long long i) { - static_assert(sizeof(long long) <= 8, "expect sizeof(long long) <= 8"); - char buf[22]; // enough to hold any 64-bit number - size_t len = ToString(i, buf, sizeof(buf)); - UnsafeWriteValue(buf, len); - return TValueContext(*this); - } - - TValueContext TBuf::WriteULongLong(unsigned long long i) { - char buf[22]; // enough to hold any 64-bit number - size_t len = ToString(i, buf, sizeof(buf)); - UnsafeWriteValue(buf, len); - return TValueContext(*this); - } - - template <class TFloat> - TValueContext TBuf::WriteFloatImpl(TFloat f, EFloatToStringMode mode, int ndigits) { - char buf[512]; // enough to hold most floats, the same buffer is used in FloatToString implementation - if (Y_UNLIKELY(!IsValidFloat(f))) { - if (WriteNanAsString) { - const size_t size = FloatToString(f, buf, Y_ARRAY_SIZE(buf)); - WriteString(TStringBuf(buf, size)); - return TValueContext(*this); - } else { - ythrow TError() << "JSON writer: invalid float value: " << FloatToString(f); - } + return TValueContext(*this); + } + + TValueContext TBuf::WriteInt(int i) { + char buf[22]; // enough to hold any 64-bit number + size_t len = ToString(i, buf, sizeof(buf)); + UnsafeWriteValue(buf, len); + return TValueContext(*this); + } + + TValueContext TBuf::WriteLongLong(long long i) { + static_assert(sizeof(long long) <= 8, "expect sizeof(long long) <= 8"); + char buf[22]; // enough to hold any 64-bit number + size_t len = ToString(i, buf, sizeof(buf)); + UnsafeWriteValue(buf, len); + return TValueContext(*this); + } + + TValueContext TBuf::WriteULongLong(unsigned long long i) { + char buf[22]; // enough to hold any 64-bit number + size_t len = ToString(i, buf, sizeof(buf)); + UnsafeWriteValue(buf, len); + return TValueContext(*this); + } + + template <class TFloat> + TValueContext TBuf::WriteFloatImpl(TFloat f, EFloatToStringMode mode, int ndigits) { + char buf[512]; // enough to hold most floats, the same buffer is used in FloatToString implementation + if (Y_UNLIKELY(!IsValidFloat(f))) { + if (WriteNanAsString) { + const size_t size = FloatToString(f, buf, Y_ARRAY_SIZE(buf)); + WriteString(TStringBuf(buf, size)); + return TValueContext(*this); + } else { + ythrow TError() << "JSON writer: invalid float value: " << FloatToString(f); + } } - size_t len = FloatToString(f, buf, Y_ARRAY_SIZE(buf), mode, ndigits); - UnsafeWriteValue(buf, len); - return TValueContext(*this); - } - - TValueContext TBuf::WriteFloat(float f, EFloatToStringMode mode, int ndigits) { - return WriteFloatImpl(f, mode, ndigits); - } - - TValueContext TBuf::WriteDouble(double f, EFloatToStringMode mode, int ndigits) { - return WriteFloatImpl(f, mode, ndigits); - } - - namespace { - struct TFinder: public TCompactStrSpn { - inline TFinder() - : TCompactStrSpn("\xe2\\\"\b\n\f\r\t<>&\'/") - { - for (ui8 ch = 0; ch < 0x20; ++ch) { - Set(ch); - } - } - }; - } - - inline void TBuf::WriteBareString(const TStringBuf s, EHtmlEscapeMode hem) { - RawWriteChar('"'); - const auto& specialChars = *Singleton<TFinder>(); - const char* b = s.begin(); - const char* e = s.end(); - const char* i = b; - while ((i = specialChars.FindFirstOf(i, e)) != e) { - // U+2028 (line separator) and U+2029 (paragraph separator) are valid string - // contents in JSON, but are treated as line breaks in JavaScript, breaking JSONP. - // In UTF-8, U+2028 is "\xe2\x80\xa8" and U+2029 is "\xe2\x80\xa9". - if (Y_UNLIKELY(e - i >= 3 && i[0] == '\xe2' && i[1] == '\x80' && (i[2] | 1) == '\xa9')) { - UnsafeWriteRawBytes(b, i - b); - UnsafeWriteRawBytes(i[2] == '\xa9' ? "\\u2029" : "\\u2028", 6); - b = i = i + 3; - } else if (EscapedWriteChar(b, i, hem)) { - b = ++i; - } else { - ++i; - } - } - UnsafeWriteRawBytes(b, e - b); - RawWriteChar('"'); - } - - inline void TBuf::RawWriteChar(char c) { - Stream->Write(c); - } - - void TBuf::WriteHexEscape(unsigned char c) { - Y_ASSERT(c < 0x80); - UnsafeWriteRawBytes("\\u00", 4); - static const char hexDigits[] = "0123456789ABCDEF"; - RawWriteChar(hexDigits[(c & 0xf0) >> 4]); - RawWriteChar(hexDigits[(c & 0x0f)]); - } - -#define MATCH(sym, string) \ - case sym: \ - UnsafeWriteRawBytes(beg, cur - beg); \ + size_t len = FloatToString(f, buf, Y_ARRAY_SIZE(buf), mode, ndigits); + UnsafeWriteValue(buf, len); + return TValueContext(*this); + } + + TValueContext TBuf::WriteFloat(float f, EFloatToStringMode mode, int ndigits) { + return WriteFloatImpl(f, mode, ndigits); + } + + TValueContext TBuf::WriteDouble(double f, EFloatToStringMode mode, int ndigits) { + return WriteFloatImpl(f, mode, ndigits); + } + + namespace { + struct TFinder: public TCompactStrSpn { + inline TFinder() + : TCompactStrSpn("\xe2\\\"\b\n\f\r\t<>&\'/") + { + for (ui8 ch = 0; ch < 0x20; ++ch) { + Set(ch); + } + } + }; + } + + inline void TBuf::WriteBareString(const TStringBuf s, EHtmlEscapeMode hem) { + RawWriteChar('"'); + const auto& specialChars = *Singleton<TFinder>(); + const char* b = s.begin(); + const char* e = s.end(); + const char* i = b; + while ((i = specialChars.FindFirstOf(i, e)) != e) { + // U+2028 (line separator) and U+2029 (paragraph separator) are valid string + // contents in JSON, but are treated as line breaks in JavaScript, breaking JSONP. + // In UTF-8, U+2028 is "\xe2\x80\xa8" and U+2029 is "\xe2\x80\xa9". + if (Y_UNLIKELY(e - i >= 3 && i[0] == '\xe2' && i[1] == '\x80' && (i[2] | 1) == '\xa9')) { + UnsafeWriteRawBytes(b, i - b); + UnsafeWriteRawBytes(i[2] == '\xa9' ? "\\u2029" : "\\u2028", 6); + b = i = i + 3; + } else if (EscapedWriteChar(b, i, hem)) { + b = ++i; + } else { + ++i; + } + } + UnsafeWriteRawBytes(b, e - b); + RawWriteChar('"'); + } + + inline void TBuf::RawWriteChar(char c) { + Stream->Write(c); + } + + void TBuf::WriteHexEscape(unsigned char c) { + Y_ASSERT(c < 0x80); + UnsafeWriteRawBytes("\\u00", 4); + static const char hexDigits[] = "0123456789ABCDEF"; + RawWriteChar(hexDigits[(c & 0xf0) >> 4]); + RawWriteChar(hexDigits[(c & 0x0f)]); + } + +#define MATCH(sym, string) \ + case sym: \ + UnsafeWriteRawBytes(beg, cur - beg); \ UnsafeWriteRawBytes(TStringBuf(string)); \ - return true - - inline bool TBuf::EscapedWriteChar(const char* beg, const char* cur, EHtmlEscapeMode hem) { - unsigned char c = *cur; - if (hem == HEM_ESCAPE_HTML) { - switch (c) { - MATCH('"', """); - MATCH('\'', "'"); - MATCH('<', "<"); - MATCH('>', ">"); - MATCH('&', "&"); - } - //for other characters, we fall through to the non-HTML-escaped part + return true + + inline bool TBuf::EscapedWriteChar(const char* beg, const char* cur, EHtmlEscapeMode hem) { + unsigned char c = *cur; + if (hem == HEM_ESCAPE_HTML) { + switch (c) { + MATCH('"', """); + MATCH('\'', "'"); + MATCH('<', "<"); + MATCH('>', ">"); + MATCH('&', "&"); + } + //for other characters, we fall through to the non-HTML-escaped part } - if (hem == HEM_RELAXED && c == '/') - return false; - - if (hem != HEM_UNSAFE) { - switch (c) { - case '/': - UnsafeWriteRawBytes(beg, cur - beg); - UnsafeWriteRawBytes("\\/", 2); - return true; - case '<': - case '>': - case '\'': - UnsafeWriteRawBytes(beg, cur - beg); - WriteHexEscape(c); - return true; - } - // for other characters, fall through to the non-escaped part + if (hem == HEM_RELAXED && c == '/') + return false; + + if (hem != HEM_UNSAFE) { + switch (c) { + case '/': + UnsafeWriteRawBytes(beg, cur - beg); + UnsafeWriteRawBytes("\\/", 2); + return true; + case '<': + case '>': + case '\'': + UnsafeWriteRawBytes(beg, cur - beg); + WriteHexEscape(c); + return true; + } + // for other characters, fall through to the non-escaped part } - switch (c) { + switch (c) { MATCH('"', "\\\""); MATCH('\\', "\\\\"); MATCH('\b', "\\b"); @@ -366,152 +366,152 @@ namespace NJsonWriter { MATCH('\n', "\\n"); MATCH('\r', "\\r"); MATCH('\t', "\\t"); - } - if (c < 0x20) { - UnsafeWriteRawBytes(beg, cur - beg); - WriteHexEscape(c); - return true; - } - - return false; + } + if (c < 0x20) { + UnsafeWriteRawBytes(beg, cur - beg); + WriteHexEscape(c); + return true; + } + + return false; } #undef MATCH - static bool LessStrPtr(const TString* a, const TString* b) { - return *a < *b; - } + static bool LessStrPtr(const TString* a, const TString* b) { + return *a < *b; + } TValueContext TBuf::WriteJsonValue(const NJson::TJsonValue* v, bool sortKeys, EFloatToStringMode mode, int ndigits) { - using namespace NJson; - switch (v->GetType()) { - default: - case JSON_NULL: - WriteNull(); - break; - case JSON_BOOLEAN: - WriteBool(v->GetBoolean()); - break; - case JSON_DOUBLE: + using namespace NJson; + switch (v->GetType()) { + default: + case JSON_NULL: + WriteNull(); + break; + case JSON_BOOLEAN: + WriteBool(v->GetBoolean()); + break; + case JSON_DOUBLE: WriteDouble(v->GetDouble(), mode, ndigits); - break; - case JSON_INTEGER: - WriteLongLong(v->GetInteger()); - break; - case JSON_UINTEGER: - WriteULongLong(v->GetUInteger()); - break; - case JSON_STRING: - WriteString(v->GetString()); - break; - case JSON_ARRAY: { - BeginList(); - const TJsonValue::TArray& arr = v->GetArray(); - for (const auto& it : arr) + break; + case JSON_INTEGER: + WriteLongLong(v->GetInteger()); + break; + case JSON_UINTEGER: + WriteULongLong(v->GetUInteger()); + break; + case JSON_STRING: + WriteString(v->GetString()); + break; + case JSON_ARRAY: { + BeginList(); + const TJsonValue::TArray& arr = v->GetArray(); + for (const auto& it : arr) WriteJsonValue(&it, sortKeys, mode, ndigits); - EndList(); - break; + EndList(); + break; } - case JSON_MAP: { - BeginObject(); - const TJsonValue::TMapType& map = v->GetMap(); - if (sortKeys) { - const size_t oldsz = Keys.size(); - Keys.reserve(map.size() + oldsz); - for (const auto& it : map) { - Keys.push_back(&(it.first)); - } - Sort(Keys.begin() + oldsz, Keys.end(), LessStrPtr); - for (size_t i = oldsz, sz = Keys.size(); i < sz; ++i) { - TJsonValue::TMapType::const_iterator kv = map.find(*Keys[i]); - WriteKey(kv->first); + case JSON_MAP: { + BeginObject(); + const TJsonValue::TMapType& map = v->GetMap(); + if (sortKeys) { + const size_t oldsz = Keys.size(); + Keys.reserve(map.size() + oldsz); + for (const auto& it : map) { + Keys.push_back(&(it.first)); + } + Sort(Keys.begin() + oldsz, Keys.end(), LessStrPtr); + for (size_t i = oldsz, sz = Keys.size(); i < sz; ++i) { + TJsonValue::TMapType::const_iterator kv = map.find(*Keys[i]); + WriteKey(kv->first); WriteJsonValue(&kv->second, sortKeys, mode, ndigits); - } - Keys.resize(oldsz); - } else { - for (const auto& it : map) { - WriteKey(it.first); + } + Keys.resize(oldsz); + } else { + for (const auto& it : map) { + WriteKey(it.first); WriteJsonValue(&it.second, sortKeys, mode, ndigits); - } - } - EndObject(); - break; + } + } + EndObject(); + break; } } - return TValueContext(*this); + return TValueContext(*this); } - - TPairContext TBuf::UnsafeWritePair(const TStringBuf& s) { - if (Y_UNLIKELY(StackTop() != JE_OBJECT)) { - ythrow TError() << "JSON writer: key:value pair written outside of an object"; - } - WriteComma(); - UnsafeWriteRawBytes(s); - return TPairContext(*this); + + TPairContext TBuf::UnsafeWritePair(const TStringBuf& s) { + if (Y_UNLIKELY(StackTop() != JE_OBJECT)) { + ythrow TError() << "JSON writer: key:value pair written outside of an object"; + } + WriteComma(); + UnsafeWriteRawBytes(s); + return TPairContext(*this); } - void TBuf::UnsafeWriteValue(const TStringBuf& s) { - BeginValue(); - UnsafeWriteRawBytes(s); - EndValue(); + void TBuf::UnsafeWriteValue(const TStringBuf& s) { + BeginValue(); + UnsafeWriteRawBytes(s); + EndValue(); } - void TBuf::UnsafeWriteValue(const char* s, size_t len) { - BeginValue(); - UnsafeWriteRawBytes(s, len); - EndValue(); - } + void TBuf::UnsafeWriteValue(const char* s, size_t len) { + BeginValue(); + UnsafeWriteRawBytes(s, len); + EndValue(); + } - void TBuf::UnsafeWriteRawBytes(const char* src, size_t len) { - Stream->Write(src, len); - } + void TBuf::UnsafeWriteRawBytes(const char* src, size_t len) { + Stream->Write(src, len); + } - void TBuf::UnsafeWriteRawBytes(const TStringBuf& s) { + void TBuf::UnsafeWriteRawBytes(const TStringBuf& s) { UnsafeWriteRawBytes(s.data(), s.size()); - } - - const TString& TBuf::Str() const { - if (!StringStream) { - ythrow TError() << "JSON writer: Str() called " - "but writing to an external stream"; - } - if (!(Stack.size() == 1 && StackTop() == JE_OUTER_SPACE)) { - ythrow TError() << "JSON writer: incomplete object converted to string"; - } - return StringStream->Str(); - } - - void TBuf::FlushTo(IOutputStream* stream) { - if (!StringStream) { - ythrow TError() << "JSON writer: FlushTo() called " - "but writing to an external stream"; - } - stream->Write(StringStream->Str()); - StringStream->Clear(); - } - - TString WrapJsonToCallback(const TBuf& buf, TStringBuf callback) { - if (!callback) { - return buf.Str(); - } else { - return TString::Join(callback, "(", buf.Str(), ")"); - } - } - - TBufState TBuf::State() const { - return TBufState{NeedComma, NeedNewline, Stack}; - } - - void TBuf::Reset(const TBufState& from) { - NeedComma = from.NeedComma; - NeedNewline = from.NeedNewline; - Stack = from.Stack; - } - - void TBuf::Reset(TBufState&& from) { - NeedComma = from.NeedComma; - NeedNewline = from.NeedNewline; - Stack.swap(from.Stack); - } + } + + const TString& TBuf::Str() const { + if (!StringStream) { + ythrow TError() << "JSON writer: Str() called " + "but writing to an external stream"; + } + if (!(Stack.size() == 1 && StackTop() == JE_OUTER_SPACE)) { + ythrow TError() << "JSON writer: incomplete object converted to string"; + } + return StringStream->Str(); + } + + void TBuf::FlushTo(IOutputStream* stream) { + if (!StringStream) { + ythrow TError() << "JSON writer: FlushTo() called " + "but writing to an external stream"; + } + stream->Write(StringStream->Str()); + StringStream->Clear(); + } + + TString WrapJsonToCallback(const TBuf& buf, TStringBuf callback) { + if (!callback) { + return buf.Str(); + } else { + return TString::Join(callback, "(", buf.Str(), ")"); + } + } + + TBufState TBuf::State() const { + return TBufState{NeedComma, NeedNewline, Stack}; + } + + void TBuf::Reset(const TBufState& from) { + NeedComma = from.NeedComma; + NeedNewline = from.NeedNewline; + Stack = from.Stack; + } + + void TBuf::Reset(TBufState&& from) { + NeedComma = from.NeedComma; + NeedNewline = from.NeedNewline; + Stack.swap(from.Stack); + } } diff --git a/library/cpp/json/writer/json.h b/library/cpp/json/writer/json.h index eca04a510a..0aae2531b9 100644 --- a/library/cpp/json/writer/json.h +++ b/library/cpp/json/writer/json.h @@ -39,7 +39,7 @@ namespace NJsonWriter { TVector<EJsonEntity> Stack; }; - class TBuf : TNonCopyable { + class TBuf : TNonCopyable { public: TBuf(EHtmlEscapeMode mode = HEM_DONT_ESCAPE_HTML, IOutputStream* stream = nullptr); @@ -183,8 +183,8 @@ namespace NJsonWriter { protected: TValueWriter(TBuf& buf) : Buf(buf) - { - } + { + } friend class TBuf; protected: @@ -196,25 +196,25 @@ namespace NJsonWriter { TBuf& EndList() { return Buf.EndList(); } - TString Str() const { - return Buf.Str(); - } - + TString Str() const { + return Buf.Str(); + } + private: TValueContext(TBuf& buf) : TValueWriter<TValueContext>(buf) - { - } + { + } friend class TBuf; friend class TValueWriter<TValueContext>; }; class TAfterColonContext: public TValueWriter<TPairContext> { private: - TAfterColonContext(TBuf& iBuf) - : TValueWriter<TPairContext>(iBuf) - { - } + TAfterColonContext(TBuf& iBuf) + : TValueWriter<TPairContext>(iBuf) + { + } friend class TBuf; friend class TPairContext; }; @@ -275,15 +275,15 @@ namespace NJsonWriter { JSON_VALUE_WRITER_WRAP(UnsafeWriteValue, (const TStringBuf& arg), (arg)) #undef JSON_VALUE_WRITER_WRAP - template <typename TOutContext> - TValueContext TValueWriter<TOutContext>::BeginList() { + template <typename TOutContext> + TValueContext TValueWriter<TOutContext>::BeginList() { return Buf.BeginList(); } - template <typename TOutContext> - TPairContext TValueWriter<TOutContext>::BeginObject() { + template <typename TOutContext> + TPairContext TValueWriter<TOutContext>::BeginObject() { return Buf.BeginObject(); } - TString WrapJsonToCallback(const TBuf& buf, TStringBuf callback); + TString WrapJsonToCallback(const TBuf& buf, TStringBuf callback); } diff --git a/library/cpp/json/writer/json_ut.cpp b/library/cpp/json/writer/json_ut.cpp index e8d0be3566..9980555683 100644 --- a/library/cpp/json/writer/json_ut.cpp +++ b/library/cpp/json/writer/json_ut.cpp @@ -16,12 +16,12 @@ Y_UNIT_TEST_SUITE(JsonWriter) { .UnsafeWritePair("\"xk\":13") .WriteKey("key2") .BeginList() - .BeginObject() - .EndObject() - .BeginObject() - .EndObject() + .BeginObject() + .EndObject() + .BeginObject() + .EndObject() .EndList() - .EndObject(); + .EndObject(); w.WriteInt(43); w.UnsafeWriteValue("\"x\""); w.WriteString("..."); @@ -75,11 +75,11 @@ Y_UNIT_TEST_SUITE(JsonWriter) { Y_UNIT_TEST(BareKey) { NJsonWriter::TBuf w; w.BeginObject() - .CompatWriteKeyWithoutQuotes("p") - .WriteInt(1) - .CompatWriteKeyWithoutQuotes("n") - .WriteInt(0) - .EndObject(); + .CompatWriteKeyWithoutQuotes("p") + .WriteInt(1) + .CompatWriteKeyWithoutQuotes("n") + .WriteInt(0) + .EndObject(); TString ws = w.Str(); const char* exp = "{p:1,n:0}"; UNIT_ASSERT_STRINGS_EQUAL(ws.c_str(), exp); @@ -108,12 +108,12 @@ Y_UNIT_TEST_SUITE(JsonWriter) { .WriteInt(1) .WriteString("hello") .BeginObject() - .WriteKey("abc") - .WriteInt(3) - .WriteKey("def") - .WriteInt(4) + .WriteKey("abc") + .WriteInt(3) + .WriteKey("def") + .WriteInt(4) .EndObject() - .EndList(); + .EndList(); const char* exp = "[\n" " 1,\n" " \"hello\",\n" @@ -196,12 +196,12 @@ Y_UNIT_TEST_SUITE(JsonWriter) { .WriteFloat(244.13854, PREC_NDIGITS, 4) .WriteFloat(10385.8324, PREC_POINT_DIGITS, 2) .BeginObject() - .WriteKey("1") - .WriteDouble(1111.71, PREC_POINT_DIGITS, 0) - .WriteKey("2") - .WriteDouble(1111.71, PREC_NDIGITS, 1) + .WriteKey("1") + .WriteDouble(1111.71, PREC_POINT_DIGITS, 0) + .WriteKey("2") + .WriteDouble(1111.71, PREC_NDIGITS, 1) .EndObject() - .EndList(); + .EndList(); const char exp[] = "[0.123457,0.1234567899,0.316,244.1,10385.83,{\"1\":1112,\"2\":1e+03}]"; UNIT_ASSERT_STRINGS_EQUAL(exp, buf.Str()); } @@ -238,17 +238,17 @@ Y_UNIT_TEST_SUITE(JsonWriter) { buf.SetWriteNanAsString(); buf.BeginObject() - .WriteKey("nanvalue") - .WriteFloat(std::numeric_limits<double>::quiet_NaN()) - .WriteKey("infvalue") - .WriteFloat(std::numeric_limits<double>::infinity()) - .WriteKey("minus_infvalue") - .WriteFloat(-std::numeric_limits<float>::infinity()) + .WriteKey("nanvalue") + .WriteFloat(std::numeric_limits<double>::quiet_NaN()) + .WriteKey("infvalue") + .WriteFloat(std::numeric_limits<double>::infinity()) + .WriteKey("minus_infvalue") + .WriteFloat(-std::numeric_limits<float>::infinity()) .WriteKey("l") - .BeginList() - .WriteFloat(std::numeric_limits<float>::quiet_NaN()) - .EndList() - .EndObject(); + .BeginList() + .WriteFloat(std::numeric_limits<float>::quiet_NaN()) + .EndList() + .EndObject(); UNIT_ASSERT_STRINGS_EQUAL(buf.Str(), R"raw_json({"nanvalue":"nan","infvalue":"inf","minus_infvalue":"-inf","l":["nan"]})raw_json"); } @@ -256,11 +256,11 @@ Y_UNIT_TEST_SUITE(JsonWriter) { { NJsonWriter::TBuf buf; buf.BeginObject() - .WriteKey("<>&") - .WriteString("Ololo") - .UnsafeWriteKey("<>&") - .WriteString("Ololo2") - .EndObject(); + .WriteKey("<>&") + .WriteString("Ololo") + .UnsafeWriteKey("<>&") + .WriteString("Ololo2") + .EndObject(); UNIT_ASSERT_STRINGS_EQUAL(buf.Str(), R"({"\u003C\u003E&":"Ololo","<>&":"Ololo2"})"); } diff --git a/library/cpp/json/writer/json_value.cpp b/library/cpp/json/writer/json_value.cpp index 4e85a6bc08..c61e8d1dc4 100644 --- a/library/cpp/json/writer/json_value.cpp +++ b/library/cpp/json/writer/json_value.cpp @@ -1,12 +1,12 @@ #include "json_value.h" #include "json.h" -#include <util/generic/ymath.h> +#include <util/generic/ymath.h> #include <util/generic/ylimits.h> #include <util/generic/utility.h> -#include <util/generic/singleton.h> +#include <util/generic/singleton.h> #include <util/stream/str.h> -#include <util/stream/output.h> +#include <util/stream/output.h> #include <util/string/cast.h> #include <util/string/type.h> #include <util/string/vector.h> @@ -59,7 +59,7 @@ AreJsonArraysEqual(const NJson::TJsonValue& lhs, const NJson::TJsonValue& rhs) { return false; for (TArray::const_iterator lhsIt = lhsArray.begin(), rhsIt = rhsArray.begin(); - lhsIt != lhsArray.end(); ++lhsIt, ++rhsIt) { + lhsIt != lhsArray.end(); ++lhsIt, ++rhsIt) { if (*lhsIt != *rhsIt) return false; } @@ -68,926 +68,926 @@ AreJsonArraysEqual(const NJson::TJsonValue& lhs, const NJson::TJsonValue& rhs) { } namespace NJson { - const TJsonValue TJsonValue::UNDEFINED{}; - - TJsonValue::TJsonValue(const EJsonValueType type) { - SetType(type); - } - - TJsonValue::TJsonValue(TJsonValue&& vval) noexcept - : Type(JSON_UNDEFINED) - { - vval.SwapWithUndefined(*this); - Zero(vval.Value); - } - - TJsonValue::TJsonValue(const TJsonValue& val) - : Type(val.Type) - { - switch (Type) { - case JSON_STRING: - new (&Value.String) TString(val.GetString()); - break; - case JSON_MAP: - Value.Map = new TMapType(val.GetMap()); - break; - case JSON_ARRAY: - Value.Array = new TArray(val.GetArray()); - break; - case JSON_UNDEFINED: - case JSON_NULL: - case JSON_BOOLEAN: - case JSON_INTEGER: - case JSON_UINTEGER: - case JSON_DOUBLE: - std::memcpy(&Value, &val.Value, sizeof(Value)); - break; - } - } - - TJsonValue& TJsonValue::operator=(const TJsonValue& val) { - if (this == &val) - return *this; - TJsonValue tmp(val); - tmp.Swap(*this); + const TJsonValue TJsonValue::UNDEFINED{}; + + TJsonValue::TJsonValue(const EJsonValueType type) { + SetType(type); + } + + TJsonValue::TJsonValue(TJsonValue&& vval) noexcept + : Type(JSON_UNDEFINED) + { + vval.SwapWithUndefined(*this); + Zero(vval.Value); + } + + TJsonValue::TJsonValue(const TJsonValue& val) + : Type(val.Type) + { + switch (Type) { + case JSON_STRING: + new (&Value.String) TString(val.GetString()); + break; + case JSON_MAP: + Value.Map = new TMapType(val.GetMap()); + break; + case JSON_ARRAY: + Value.Array = new TArray(val.GetArray()); + break; + case JSON_UNDEFINED: + case JSON_NULL: + case JSON_BOOLEAN: + case JSON_INTEGER: + case JSON_UINTEGER: + case JSON_DOUBLE: + std::memcpy(&Value, &val.Value, sizeof(Value)); + break; + } + } + + TJsonValue& TJsonValue::operator=(const TJsonValue& val) { + if (this == &val) + return *this; + TJsonValue tmp(val); + tmp.Swap(*this); return *this; - } + } - TJsonValue& TJsonValue::operator=(TJsonValue&& val) noexcept { - if (this == &val) - return *this; - TJsonValue tmp(std::move(val)); - tmp.Swap(*this); + TJsonValue& TJsonValue::operator=(TJsonValue&& val) noexcept { + if (this == &val) + return *this; + TJsonValue tmp(std::move(val)); + tmp.Swap(*this); return *this; - } - - TJsonValue::TJsonValue(const bool value) noexcept { - SetType(JSON_BOOLEAN); - Value.Boolean = value; - } - - TJsonValue::TJsonValue(const long long value) noexcept { - SetType(JSON_INTEGER); - Value.Integer = value; - } - - TJsonValue::TJsonValue(const unsigned long long value) noexcept { - SetType(JSON_UINTEGER); - Value.UInteger = value; - } - - TJsonValue::TJsonValue(const int value) noexcept { - SetType(JSON_INTEGER); - Value.Integer = value; - } - - TJsonValue::TJsonValue(const unsigned int value) noexcept { - SetType(JSON_UINTEGER); - Value.UInteger = value; - } - - TJsonValue::TJsonValue(const long value) noexcept { - SetType(JSON_INTEGER); - Value.Integer = value; - } - - TJsonValue::TJsonValue(const unsigned long value) noexcept { - SetType(JSON_UINTEGER); - Value.UInteger = value; - } - - TJsonValue::TJsonValue(const double value) noexcept { - SetType(JSON_DOUBLE); - Value.Double = value; - } + } + + TJsonValue::TJsonValue(const bool value) noexcept { + SetType(JSON_BOOLEAN); + Value.Boolean = value; + } + + TJsonValue::TJsonValue(const long long value) noexcept { + SetType(JSON_INTEGER); + Value.Integer = value; + } + + TJsonValue::TJsonValue(const unsigned long long value) noexcept { + SetType(JSON_UINTEGER); + Value.UInteger = value; + } + + TJsonValue::TJsonValue(const int value) noexcept { + SetType(JSON_INTEGER); + Value.Integer = value; + } + + TJsonValue::TJsonValue(const unsigned int value) noexcept { + SetType(JSON_UINTEGER); + Value.UInteger = value; + } + + TJsonValue::TJsonValue(const long value) noexcept { + SetType(JSON_INTEGER); + Value.Integer = value; + } + + TJsonValue::TJsonValue(const unsigned long value) noexcept { + SetType(JSON_UINTEGER); + Value.UInteger = value; + } + + TJsonValue::TJsonValue(const double value) noexcept { + SetType(JSON_DOUBLE); + Value.Double = value; + } TJsonValue::TJsonValue(TString value) { - SetType(JSON_STRING); - Value.String = std::move(value); - } - - TJsonValue::TJsonValue(const TStringBuf value) { - SetType(JSON_STRING); - Value.String = value; - } - - TJsonValue::TJsonValue(const char* value) { - SetType(JSON_STRING); - Value.String = value; - } - - EJsonValueType TJsonValue::GetType() const noexcept { - return Type; - } - - TJsonValue& TJsonValue::SetType(const EJsonValueType type) { - if (Type == type) - return *this; - - Clear(); - Type = type; - - switch (Type) { - case JSON_STRING: - new (&Value.String) TString(); - break; - case JSON_MAP: - Value.Map = new TMapType(); - break; - case JSON_ARRAY: - Value.Array = new TArray(); - break; - case JSON_UNDEFINED: - case JSON_NULL: - case JSON_BOOLEAN: - case JSON_INTEGER: - case JSON_UINTEGER: - case JSON_DOUBLE: - break; - } - - return *this; - } - - TJsonValue& TJsonValue::SetValue(const TJsonValue& value) { - return *this = value; - } - - TJsonValue& TJsonValue::SetValue(TJsonValue&& value) { - *this = std::move(value); - return *this; - } - - TJsonValue& TJsonValue::InsertValue(const TString& key, const TJsonValue& value) { - SetType(JSON_MAP); - return (*Value.Map)[key] = value; - } - - TJsonValue& TJsonValue::InsertValue(const TStringBuf key, const TJsonValue& value) { - SetType(JSON_MAP); - return (*Value.Map)[key] = value; - } - - TJsonValue& TJsonValue::InsertValue(const char* key, const TJsonValue& value) { - SetType(JSON_MAP); - return (*Value.Map)[key] = value; - } - - TJsonValue& TJsonValue::InsertValue(const TString& key, TJsonValue&& value) { - SetType(JSON_MAP); - return (*Value.Map)[key] = std::move(value); - } - - TJsonValue& TJsonValue::InsertValue(const TStringBuf key, TJsonValue&& value) { - SetType(JSON_MAP); - return (*Value.Map)[key] = std::move(value); - } - - TJsonValue& TJsonValue::InsertValue(const char* key, TJsonValue&& value) { - SetType(JSON_MAP); - return (*Value.Map)[key] = std::move(value); - } - - TJsonValue& TJsonValue::Back() { + SetType(JSON_STRING); + Value.String = std::move(value); + } + + TJsonValue::TJsonValue(const TStringBuf value) { + SetType(JSON_STRING); + Value.String = value; + } + + TJsonValue::TJsonValue(const char* value) { + SetType(JSON_STRING); + Value.String = value; + } + + EJsonValueType TJsonValue::GetType() const noexcept { + return Type; + } + + TJsonValue& TJsonValue::SetType(const EJsonValueType type) { + if (Type == type) + return *this; + + Clear(); + Type = type; + + switch (Type) { + case JSON_STRING: + new (&Value.String) TString(); + break; + case JSON_MAP: + Value.Map = new TMapType(); + break; + case JSON_ARRAY: + Value.Array = new TArray(); + break; + case JSON_UNDEFINED: + case JSON_NULL: + case JSON_BOOLEAN: + case JSON_INTEGER: + case JSON_UINTEGER: + case JSON_DOUBLE: + break; + } + + return *this; + } + + TJsonValue& TJsonValue::SetValue(const TJsonValue& value) { + return *this = value; + } + + TJsonValue& TJsonValue::SetValue(TJsonValue&& value) { + *this = std::move(value); + return *this; + } + + TJsonValue& TJsonValue::InsertValue(const TString& key, const TJsonValue& value) { + SetType(JSON_MAP); + return (*Value.Map)[key] = value; + } + + TJsonValue& TJsonValue::InsertValue(const TStringBuf key, const TJsonValue& value) { + SetType(JSON_MAP); + return (*Value.Map)[key] = value; + } + + TJsonValue& TJsonValue::InsertValue(const char* key, const TJsonValue& value) { + SetType(JSON_MAP); + return (*Value.Map)[key] = value; + } + + TJsonValue& TJsonValue::InsertValue(const TString& key, TJsonValue&& value) { + SetType(JSON_MAP); + return (*Value.Map)[key] = std::move(value); + } + + TJsonValue& TJsonValue::InsertValue(const TStringBuf key, TJsonValue&& value) { + SetType(JSON_MAP); + return (*Value.Map)[key] = std::move(value); + } + + TJsonValue& TJsonValue::InsertValue(const char* key, TJsonValue&& value) { + SetType(JSON_MAP); + return (*Value.Map)[key] = std::move(value); + } + + TJsonValue& TJsonValue::Back() { BackChecks(); return Value.Array->back(); } const TJsonValue& TJsonValue::Back() const { BackChecks(); - return Value.Array->back(); - } - - TJsonValue& TJsonValue::AppendValue(const TJsonValue& value) { - SetType(JSON_ARRAY); - Value.Array->push_back(value); - return Value.Array->back(); - } - - TJsonValue& TJsonValue::AppendValue(TJsonValue&& value) { - SetType(JSON_ARRAY); - Value.Array->push_back(std::move(value)); - return Value.Array->back(); - } - - void TJsonValue::EraseValue(const TStringBuf key) { - if (IsMap()) { - TMapType::iterator it = Value.Map->find(key); - if (it != Value.Map->end()) - Value.Map->erase(it); - } - } - - void TJsonValue::EraseValue(const size_t index) { - if (IsArray()) { - if (index >= Value.Array->size()) { - return; - } - TArray::iterator it = Value.Array->begin() + index; - Value.Array->erase(it); - } - } - - void TJsonValue::Clear() noexcept { - switch (Type) { - case JSON_STRING: - Value.String.~TString(); - break; - case JSON_MAP: - delete Value.Map; - break; - case JSON_ARRAY: - delete Value.Array; - break; - case JSON_UNDEFINED: - case JSON_NULL: - case JSON_BOOLEAN: - case JSON_INTEGER: - case JSON_UINTEGER: - case JSON_DOUBLE: - break; + return Value.Array->back(); + } + + TJsonValue& TJsonValue::AppendValue(const TJsonValue& value) { + SetType(JSON_ARRAY); + Value.Array->push_back(value); + return Value.Array->back(); + } + + TJsonValue& TJsonValue::AppendValue(TJsonValue&& value) { + SetType(JSON_ARRAY); + Value.Array->push_back(std::move(value)); + return Value.Array->back(); + } + + void TJsonValue::EraseValue(const TStringBuf key) { + if (IsMap()) { + TMapType::iterator it = Value.Map->find(key); + if (it != Value.Map->end()) + Value.Map->erase(it); } - Zero(Value); - Type = JSON_UNDEFINED; } - TJsonValue& TJsonValue::operator[](const size_t idx) { - SetType(JSON_ARRAY); - if (Value.Array->size() <= idx) - Value.Array->resize(idx + 1); - return (*Value.Array)[idx]; - } + void TJsonValue::EraseValue(const size_t index) { + if (IsArray()) { + if (index >= Value.Array->size()) { + return; + } + TArray::iterator it = Value.Array->begin() + index; + Value.Array->erase(it); + } + } - TJsonValue& TJsonValue::operator[](const TStringBuf& key) { - SetType(JSON_MAP); - return (*Value.Map)[key]; + void TJsonValue::Clear() noexcept { + switch (Type) { + case JSON_STRING: + Value.String.~TString(); + break; + case JSON_MAP: + delete Value.Map; + break; + case JSON_ARRAY: + delete Value.Array; + break; + case JSON_UNDEFINED: + case JSON_NULL: + case JSON_BOOLEAN: + case JSON_INTEGER: + case JSON_UINTEGER: + case JSON_DOUBLE: + break; + } + Zero(Value); + Type = JSON_UNDEFINED; } - namespace { - struct TDefaultsHolder { - const TString String{}; - const TJsonValue::TMapType Map{}; - const TJsonValue::TArray Array{}; - const TJsonValue Value{}; - }; - } + TJsonValue& TJsonValue::operator[](const size_t idx) { + SetType(JSON_ARRAY); + if (Value.Array->size() <= idx) + Value.Array->resize(idx + 1); + return (*Value.Array)[idx]; + } - const TJsonValue& TJsonValue::operator[](const size_t idx) const noexcept { - const TJsonValue* ret = nullptr; - if (GetValuePointer(idx, &ret)) - return *ret; + TJsonValue& TJsonValue::operator[](const TStringBuf& key) { + SetType(JSON_MAP); + return (*Value.Map)[key]; + } - return Singleton<TDefaultsHolder>()->Value; - } + namespace { + struct TDefaultsHolder { + const TString String{}; + const TJsonValue::TMapType Map{}; + const TJsonValue::TArray Array{}; + const TJsonValue Value{}; + }; + } - const TJsonValue& TJsonValue::operator[](const TStringBuf& key) const noexcept { - const TJsonValue* ret = nullptr; - if (GetValuePointer(key, &ret)) - return *ret; + const TJsonValue& TJsonValue::operator[](const size_t idx) const noexcept { + const TJsonValue* ret = nullptr; + if (GetValuePointer(idx, &ret)) + return *ret; - return Singleton<TDefaultsHolder>()->Value; - } + return Singleton<TDefaultsHolder>()->Value; + } - bool TJsonValue::GetBoolean() const { - return Type != JSON_BOOLEAN ? false : Value.Boolean; - } + const TJsonValue& TJsonValue::operator[](const TStringBuf& key) const noexcept { + const TJsonValue* ret = nullptr; + if (GetValuePointer(key, &ret)) + return *ret; - long long TJsonValue::GetInteger() const { - if (!IsInteger()) - return 0; + return Singleton<TDefaultsHolder>()->Value; + } - switch (Type) { - case JSON_INTEGER: - return Value.Integer; + bool TJsonValue::GetBoolean() const { + return Type != JSON_BOOLEAN ? false : Value.Boolean; + } - case JSON_UINTEGER: - return Value.UInteger; + long long TJsonValue::GetInteger() const { + if (!IsInteger()) + return 0; - case JSON_DOUBLE: - return Value.Double; + switch (Type) { + case JSON_INTEGER: + return Value.Integer; + + case JSON_UINTEGER: + return Value.UInteger; + + case JSON_DOUBLE: + return Value.Double; - default: - Y_ASSERT(false && "Unexpected type."); - return 0; - } + default: + Y_ASSERT(false && "Unexpected type."); + return 0; + } } - unsigned long long TJsonValue::GetUInteger() const { - if (!IsUInteger()) - return 0; + unsigned long long TJsonValue::GetUInteger() const { + if (!IsUInteger()) + return 0; - switch (Type) { - case JSON_UINTEGER: - return Value.UInteger; + switch (Type) { + case JSON_UINTEGER: + return Value.UInteger; - case JSON_INTEGER: - return Value.Integer; + case JSON_INTEGER: + return Value.Integer; - case JSON_DOUBLE: - return Value.Double; + case JSON_DOUBLE: + return Value.Double; - default: - Y_ASSERT(false && "Unexpected type."); - return 0; - } + default: + Y_ASSERT(false && "Unexpected type."); + return 0; + } } - double TJsonValue::GetDouble() const { - if (!IsDouble()) - return 0.0; + double TJsonValue::GetDouble() const { + if (!IsDouble()) + return 0.0; - switch (Type) { - case JSON_DOUBLE: - return Value.Double; + switch (Type) { + case JSON_DOUBLE: + return Value.Double; - case JSON_INTEGER: - return Value.Integer; + case JSON_INTEGER: + return Value.Integer; - case JSON_UINTEGER: - return Value.UInteger; + case JSON_UINTEGER: + return Value.UInteger; - default: - Y_ASSERT(false && "Unexpected type."); - return 0.0; - } + default: + Y_ASSERT(false && "Unexpected type."); + return 0.0; + } } - const TString& TJsonValue::GetString() const { - return Type != JSON_STRING ? Singleton<TDefaultsHolder>()->String : Value.String; - } + const TString& TJsonValue::GetString() const { + return Type != JSON_STRING ? Singleton<TDefaultsHolder>()->String : Value.String; + } - const TJsonValue::TMapType& TJsonValue::GetMap() const { - return Type != JSON_MAP ? Singleton<TDefaultsHolder>()->Map : *Value.Map; - } + const TJsonValue::TMapType& TJsonValue::GetMap() const { + return Type != JSON_MAP ? Singleton<TDefaultsHolder>()->Map : *Value.Map; + } - const TJsonValue::TArray& TJsonValue::GetArray() const { - return (Type != JSON_ARRAY) ? Singleton<TDefaultsHolder>()->Array : *Value.Array; - } + const TJsonValue::TArray& TJsonValue::GetArray() const { + return (Type != JSON_ARRAY) ? Singleton<TDefaultsHolder>()->Array : *Value.Array; + } - bool TJsonValue::GetBooleanSafe() const { - if (Type != JSON_BOOLEAN) - ythrow TJsonException() << "Not a boolean"; + bool TJsonValue::GetBooleanSafe() const { + if (Type != JSON_BOOLEAN) + ythrow TJsonException() << "Not a boolean"; - return Value.Boolean; - } + return Value.Boolean; + } - long long TJsonValue::GetIntegerSafe() const { - if (!IsInteger()) - ythrow TJsonException() << "Not an integer"; + long long TJsonValue::GetIntegerSafe() const { + if (!IsInteger()) + ythrow TJsonException() << "Not an integer"; - return GetInteger(); - } + return GetInteger(); + } - unsigned long long TJsonValue::GetUIntegerSafe() const { - if (!IsUInteger()) - ythrow TJsonException() << "Not an unsigned integer"; + unsigned long long TJsonValue::GetUIntegerSafe() const { + if (!IsUInteger()) + ythrow TJsonException() << "Not an unsigned integer"; - return GetUInteger(); - } + return GetUInteger(); + } - double TJsonValue::GetDoubleSafe() const { - if (!IsDouble()) - ythrow TJsonException() << "Not a double"; + double TJsonValue::GetDoubleSafe() const { + if (!IsDouble()) + ythrow TJsonException() << "Not a double"; - return GetDouble(); - } + return GetDouble(); + } - const TString& TJsonValue::GetStringSafe() const { - if (Type != JSON_STRING) - ythrow TJsonException() << "Not a string"; + const TString& TJsonValue::GetStringSafe() const { + if (Type != JSON_STRING) + ythrow TJsonException() << "Not a string"; - return Value.String; - } + return Value.String; + } - bool TJsonValue::GetBooleanSafe(const bool defaultValue) const { - if (Type == JSON_UNDEFINED) - return defaultValue; + bool TJsonValue::GetBooleanSafe(const bool defaultValue) const { + if (Type == JSON_UNDEFINED) + return defaultValue; - return GetBooleanSafe(); - } + return GetBooleanSafe(); + } - long long TJsonValue::GetIntegerSafe(const long long defaultValue) const { - if (Type == JSON_UNDEFINED) - return defaultValue; + long long TJsonValue::GetIntegerSafe(const long long defaultValue) const { + if (Type == JSON_UNDEFINED) + return defaultValue; - return GetIntegerSafe(); - } + return GetIntegerSafe(); + } - unsigned long long TJsonValue::GetUIntegerSafe(const unsigned long long defaultValue) const { - if (Type == JSON_UNDEFINED) - return defaultValue; + unsigned long long TJsonValue::GetUIntegerSafe(const unsigned long long defaultValue) const { + if (Type == JSON_UNDEFINED) + return defaultValue; - return GetUIntegerSafe(); - } + return GetUIntegerSafe(); + } - double TJsonValue::GetDoubleSafe(const double defaultValue) const { - if (Type == JSON_UNDEFINED) - return defaultValue; + double TJsonValue::GetDoubleSafe(const double defaultValue) const { + if (Type == JSON_UNDEFINED) + return defaultValue; - return GetDoubleSafe(); - } + return GetDoubleSafe(); + } - TString TJsonValue::GetStringSafe(const TString& defaultValue) const { - if (Type == JSON_UNDEFINED) - return defaultValue; + TString TJsonValue::GetStringSafe(const TString& defaultValue) const { + if (Type == JSON_UNDEFINED) + return defaultValue; - return GetStringSafe(); - } + return GetStringSafe(); + } - const TJsonValue::TMapType& TJsonValue::GetMapSafe() const { - if (Type != JSON_MAP) - ythrow TJsonException() << "Not a map"; + const TJsonValue::TMapType& TJsonValue::GetMapSafe() const { + if (Type != JSON_MAP) + ythrow TJsonException() << "Not a map"; - return *Value.Map; - } + return *Value.Map; + } - TJsonValue::TMapType& TJsonValue::GetMapSafe() { - return const_cast<TJsonValue::TMapType&>(const_cast<const TJsonValue*>(this)->GetMapSafe()); - } + TJsonValue::TMapType& TJsonValue::GetMapSafe() { + return const_cast<TJsonValue::TMapType&>(const_cast<const TJsonValue*>(this)->GetMapSafe()); + } - const TJsonValue::TArray& TJsonValue::GetArraySafe() const { - if (Type != JSON_ARRAY) - ythrow TJsonException() << "Not an array"; + const TJsonValue::TArray& TJsonValue::GetArraySafe() const { + if (Type != JSON_ARRAY) + ythrow TJsonException() << "Not an array"; - return *Value.Array; - } + return *Value.Array; + } - TJsonValue::TArray& TJsonValue::GetArraySafe() { - return const_cast<TJsonValue::TArray&>(const_cast<const TJsonValue*>(this)->GetArraySafe()); - } + TJsonValue::TArray& TJsonValue::GetArraySafe() { + return const_cast<TJsonValue::TArray&>(const_cast<const TJsonValue*>(this)->GetArraySafe()); + } - bool TJsonValue::GetBooleanRobust() const noexcept { - switch (Type) { - case JSON_ARRAY: - return !Value.Array->empty(); - case JSON_MAP: - return !Value.Map->empty(); - case JSON_INTEGER: - case JSON_UINTEGER: - case JSON_DOUBLE: - return GetIntegerRobust(); - case JSON_STRING: - return GetIntegerRobust() || IsTrue(Value.String); - case JSON_NULL: - case JSON_UNDEFINED: - default: + bool TJsonValue::GetBooleanRobust() const noexcept { + switch (Type) { + case JSON_ARRAY: + return !Value.Array->empty(); + case JSON_MAP: + return !Value.Map->empty(); + case JSON_INTEGER: + case JSON_UINTEGER: + case JSON_DOUBLE: + return GetIntegerRobust(); + case JSON_STRING: + return GetIntegerRobust() || IsTrue(Value.String); + case JSON_NULL: + case JSON_UNDEFINED: + default: return false; - case JSON_BOOLEAN: - return Value.Boolean; - } - } - - long long TJsonValue::GetIntegerRobust() const noexcept { - switch (Type) { - case JSON_ARRAY: - return Value.Array->size(); - case JSON_MAP: - return Value.Map->size(); - case JSON_BOOLEAN: - return Value.Boolean; - case JSON_DOUBLE: - return GetDoubleRobust(); - case JSON_STRING: - try { - i64 res = 0; - if (Value.String && TryFromString(Value.String, res)) { - return res; - } - } catch (const yexception&) { - } - return 0; - case JSON_NULL: - case JSON_UNDEFINED: - default: - return 0; - case JSON_INTEGER: - case JSON_UINTEGER: - return Value.Integer; - } - } - - unsigned long long TJsonValue::GetUIntegerRobust() const noexcept { - switch (Type) { - case JSON_ARRAY: - return Value.Array->size(); - case JSON_MAP: - return Value.Map->size(); - case JSON_BOOLEAN: - return Value.Boolean; - case JSON_DOUBLE: - return GetDoubleRobust(); - case JSON_STRING: - try { - ui64 res = 0; - if (Value.String && TryFromString(Value.String, res)) { - return res; - } - } catch (const yexception&) { - } - return 0; - case JSON_NULL: - case JSON_UNDEFINED: - default: - return 0; - case JSON_INTEGER: - case JSON_UINTEGER: - return Value.UInteger; - } - } - - double TJsonValue::GetDoubleRobust() const noexcept { - switch (Type) { - case JSON_ARRAY: - return Value.Array->size(); - case JSON_MAP: - return Value.Map->size(); - case JSON_BOOLEAN: - return Value.Boolean; - case JSON_INTEGER: - return Value.Integer; - case JSON_UINTEGER: - return Value.UInteger; - case JSON_STRING: - try { - double res = 0; - if (Value.String && TryFromString(Value.String, res)) { - return res; - } - } catch (const yexception&) { - } - return 0; - case JSON_NULL: - case JSON_UNDEFINED: - default: - return 0; - case JSON_DOUBLE: - return Value.Double; - } - } - - TString TJsonValue::GetStringRobust() const { - switch (Type) { - case JSON_ARRAY: - case JSON_MAP: - case JSON_BOOLEAN: - case JSON_DOUBLE: - case JSON_INTEGER: - case JSON_UINTEGER: - case JSON_NULL: - case JSON_UNDEFINED: - default: { - NJsonWriter::TBuf sout; - sout.WriteJsonValue(this); - return sout.Str(); - } - case JSON_STRING: - return Value.String; - } - } - - bool TJsonValue::GetBoolean(bool* value) const noexcept { - if (Type != JSON_BOOLEAN) - return false; - - *value = Value.Boolean; - return true; - } - - bool TJsonValue::GetInteger(long long* value) const noexcept { - if (!IsInteger()) - return false; - - *value = GetInteger(); - return true; - } - - bool TJsonValue::GetUInteger(unsigned long long* value) const noexcept { - if (!IsUInteger()) - return false; - - *value = GetUInteger(); - return true; - } - - bool TJsonValue::GetDouble(double* value) const noexcept { - if (!IsDouble()) - return false; - - *value = GetDouble(); - return true; - } - - bool TJsonValue::GetString(TString* value) const { - if (Type != JSON_STRING) - return false; - - *value = Value.String; - return true; - } - - bool TJsonValue::GetMap(TJsonValue::TMapType* value) const { - if (Type != JSON_MAP) - return false; - - *value = *Value.Map; - return true; - } - - bool TJsonValue::GetArray(TJsonValue::TArray* value) const { - if (Type != JSON_ARRAY) - return false; - - *value = *Value.Array; - return true; - } - - bool TJsonValue::GetMapPointer(const TJsonValue::TMapType** value) const noexcept { - if (Type != JSON_MAP) - return false; - - *value = Value.Map; - return true; - } - - bool TJsonValue::GetArrayPointer(const TJsonValue::TArray** value) const noexcept { - if (Type != JSON_ARRAY) - return false; - - *value = Value.Array; + case JSON_BOOLEAN: + return Value.Boolean; + } + } + + long long TJsonValue::GetIntegerRobust() const noexcept { + switch (Type) { + case JSON_ARRAY: + return Value.Array->size(); + case JSON_MAP: + return Value.Map->size(); + case JSON_BOOLEAN: + return Value.Boolean; + case JSON_DOUBLE: + return GetDoubleRobust(); + case JSON_STRING: + try { + i64 res = 0; + if (Value.String && TryFromString(Value.String, res)) { + return res; + } + } catch (const yexception&) { + } + return 0; + case JSON_NULL: + case JSON_UNDEFINED: + default: + return 0; + case JSON_INTEGER: + case JSON_UINTEGER: + return Value.Integer; + } + } + + unsigned long long TJsonValue::GetUIntegerRobust() const noexcept { + switch (Type) { + case JSON_ARRAY: + return Value.Array->size(); + case JSON_MAP: + return Value.Map->size(); + case JSON_BOOLEAN: + return Value.Boolean; + case JSON_DOUBLE: + return GetDoubleRobust(); + case JSON_STRING: + try { + ui64 res = 0; + if (Value.String && TryFromString(Value.String, res)) { + return res; + } + } catch (const yexception&) { + } + return 0; + case JSON_NULL: + case JSON_UNDEFINED: + default: + return 0; + case JSON_INTEGER: + case JSON_UINTEGER: + return Value.UInteger; + } + } + + double TJsonValue::GetDoubleRobust() const noexcept { + switch (Type) { + case JSON_ARRAY: + return Value.Array->size(); + case JSON_MAP: + return Value.Map->size(); + case JSON_BOOLEAN: + return Value.Boolean; + case JSON_INTEGER: + return Value.Integer; + case JSON_UINTEGER: + return Value.UInteger; + case JSON_STRING: + try { + double res = 0; + if (Value.String && TryFromString(Value.String, res)) { + return res; + } + } catch (const yexception&) { + } + return 0; + case JSON_NULL: + case JSON_UNDEFINED: + default: + return 0; + case JSON_DOUBLE: + return Value.Double; + } + } + + TString TJsonValue::GetStringRobust() const { + switch (Type) { + case JSON_ARRAY: + case JSON_MAP: + case JSON_BOOLEAN: + case JSON_DOUBLE: + case JSON_INTEGER: + case JSON_UINTEGER: + case JSON_NULL: + case JSON_UNDEFINED: + default: { + NJsonWriter::TBuf sout; + sout.WriteJsonValue(this); + return sout.Str(); + } + case JSON_STRING: + return Value.String; + } + } + + bool TJsonValue::GetBoolean(bool* value) const noexcept { + if (Type != JSON_BOOLEAN) + return false; + + *value = Value.Boolean; + return true; + } + + bool TJsonValue::GetInteger(long long* value) const noexcept { + if (!IsInteger()) + return false; + + *value = GetInteger(); + return true; + } + + bool TJsonValue::GetUInteger(unsigned long long* value) const noexcept { + if (!IsUInteger()) + return false; + + *value = GetUInteger(); + return true; + } + + bool TJsonValue::GetDouble(double* value) const noexcept { + if (!IsDouble()) + return false; + + *value = GetDouble(); + return true; + } + + bool TJsonValue::GetString(TString* value) const { + if (Type != JSON_STRING) + return false; + + *value = Value.String; return true; } - bool TJsonValue::GetValue(const size_t index, TJsonValue* value) const { - const TJsonValue* tmp = nullptr; - if (GetValuePointer(index, &tmp)) { - *value = *tmp; - return true; - } - return false; + bool TJsonValue::GetMap(TJsonValue::TMapType* value) const { + if (Type != JSON_MAP) + return false; + + *value = *Value.Map; + return true; } - bool TJsonValue::GetValue(const TStringBuf key, TJsonValue* value) const { - const TJsonValue* tmp = nullptr; - if (GetValuePointer(key, &tmp)) { - *value = *tmp; - return true; - } - return false; + bool TJsonValue::GetArray(TJsonValue::TArray* value) const { + if (Type != JSON_ARRAY) + return false; + + *value = *Value.Array; + return true; } - bool TJsonValue::GetValuePointer(const size_t index, const TJsonValue** value) const noexcept { - if (Type == JSON_ARRAY && index < Value.Array->size()) { - *value = &(*Value.Array)[index]; + bool TJsonValue::GetMapPointer(const TJsonValue::TMapType** value) const noexcept { + if (Type != JSON_MAP) + return false; + + *value = Value.Map; + return true; + } + + bool TJsonValue::GetArrayPointer(const TJsonValue::TArray** value) const noexcept { + if (Type != JSON_ARRAY) + return false; + + *value = Value.Array; + return true; + } + + bool TJsonValue::GetValue(const size_t index, TJsonValue* value) const { + const TJsonValue* tmp = nullptr; + if (GetValuePointer(index, &tmp)) { + *value = *tmp; return true; } - return false; + return false; } - bool TJsonValue::GetValuePointer(const TStringBuf key, const TJsonValue** value) const noexcept { - if (Type == JSON_MAP) { - const TMapType::const_iterator it = Value.Map->find(key); - if (it != Value.Map->end()) { - *value = &(it->second); - return true; - } - } - return false; - } + bool TJsonValue::GetValue(const TStringBuf key, TJsonValue* value) const { + const TJsonValue* tmp = nullptr; + if (GetValuePointer(key, &tmp)) { + *value = *tmp; + return true; + } + return false; + } - bool TJsonValue::GetValuePointer(const TStringBuf key, TJsonValue** value) noexcept { - return static_cast<const TJsonValue*>(this)->GetValuePointer(key, const_cast<const TJsonValue**>(value)); - } + bool TJsonValue::GetValuePointer(const size_t index, const TJsonValue** value) const noexcept { + if (Type == JSON_ARRAY && index < Value.Array->size()) { + *value = &(*Value.Array)[index]; + return true; + } + return false; + } - bool TJsonValue::IsNull() const noexcept { - return Type == JSON_NULL; - } + bool TJsonValue::GetValuePointer(const TStringBuf key, const TJsonValue** value) const noexcept { + if (Type == JSON_MAP) { + const TMapType::const_iterator it = Value.Map->find(key); + if (it != Value.Map->end()) { + *value = &(it->second); + return true; + } + } + return false; + } - bool TJsonValue::IsBoolean() const noexcept { - return Type == JSON_BOOLEAN; - } + bool TJsonValue::GetValuePointer(const TStringBuf key, TJsonValue** value) noexcept { + return static_cast<const TJsonValue*>(this)->GetValuePointer(key, const_cast<const TJsonValue**>(value)); + } + + bool TJsonValue::IsNull() const noexcept { + return Type == JSON_NULL; + } - bool TJsonValue::IsInteger() const noexcept { - switch (Type) { - case JSON_INTEGER: - return true; + bool TJsonValue::IsBoolean() const noexcept { + return Type == JSON_BOOLEAN; + } - case JSON_UINTEGER: - return (Value.UInteger <= static_cast<unsigned long long>(Max<long long>())); + bool TJsonValue::IsInteger() const noexcept { + switch (Type) { + case JSON_INTEGER: + return true; - case JSON_DOUBLE: - return ((long long)Value.Double == Value.Double); - - default: - return false; - } + case JSON_UINTEGER: + return (Value.UInteger <= static_cast<unsigned long long>(Max<long long>())); + + case JSON_DOUBLE: + return ((long long)Value.Double == Value.Double); + + default: + return false; + } } - bool TJsonValue::IsUInteger() const noexcept { - switch (Type) { - case JSON_UINTEGER: - return true; + bool TJsonValue::IsUInteger() const noexcept { + switch (Type) { + case JSON_UINTEGER: + return true; - case JSON_INTEGER: - return (Value.Integer >= 0); + case JSON_INTEGER: + return (Value.Integer >= 0); - case JSON_DOUBLE: - return ((unsigned long long)Value.Double == Value.Double); + case JSON_DOUBLE: + return ((unsigned long long)Value.Double == Value.Double); - default: - return false; - } + default: + return false; + } } - bool TJsonValue::IsDouble() const noexcept { - // Check whether we can convert integer to floating-point - // without precision loss. - switch (Type) { - case JSON_DOUBLE: - return true; + bool TJsonValue::IsDouble() const noexcept { + // Check whether we can convert integer to floating-point + // without precision loss. + switch (Type) { + case JSON_DOUBLE: + return true; - case JSON_INTEGER: + case JSON_INTEGER: return (1ll << std::numeric_limits<double>::digits) >= Abs(Value.Integer); - case JSON_UINTEGER: + case JSON_UINTEGER: return (1ull << std::numeric_limits<double>::digits) >= Value.UInteger; - default: - return false; - } - } - - namespace { - template <class TPtr, class T> - TPtr* CreateOrNullptr(TPtr* p, T key, std::true_type /*create*/) { - return &(*p)[key]; - } - - template <class TPtr, class T> - TPtr* CreateOrNullptr(const TPtr* p, T key, std::false_type /*create*/) noexcept { - const TPtr* const next = &(*p)[key]; - return next->IsDefined() ? const_cast<TPtr*>(next) : nullptr; - } - - template <bool Create, class TJsonPtr> - TJsonPtr GetValuePtrByPath(TJsonPtr currentJson, TStringBuf path, char delimiter) noexcept(!Create) { - static_assert( - !(Create && std::is_const<std::remove_pointer_t<TJsonPtr>>::value), - "TJsonPtr must be a `TJsonValue*` if `Create` is true"); - constexpr std::integral_constant<bool, Create> create_tag{}; - - while (!path.empty()) { - size_t index = 0; - const TStringBuf step = path.NextTok(delimiter); - if (step.size() > 2 && *step.begin() == '[' && step.back() == ']' && TryFromString(step.substr(1, step.size() - 2), index)) { - currentJson = CreateOrNullptr(currentJson, index, create_tag); - } else { - currentJson = CreateOrNullptr(currentJson, step, create_tag); - } - - if (!currentJson) { - return nullptr; - } + default: + return false; + } + } + + namespace { + template <class TPtr, class T> + TPtr* CreateOrNullptr(TPtr* p, T key, std::true_type /*create*/) { + return &(*p)[key]; + } + + template <class TPtr, class T> + TPtr* CreateOrNullptr(const TPtr* p, T key, std::false_type /*create*/) noexcept { + const TPtr* const next = &(*p)[key]; + return next->IsDefined() ? const_cast<TPtr*>(next) : nullptr; + } + + template <bool Create, class TJsonPtr> + TJsonPtr GetValuePtrByPath(TJsonPtr currentJson, TStringBuf path, char delimiter) noexcept(!Create) { + static_assert( + !(Create && std::is_const<std::remove_pointer_t<TJsonPtr>>::value), + "TJsonPtr must be a `TJsonValue*` if `Create` is true"); + constexpr std::integral_constant<bool, Create> create_tag{}; + + while (!path.empty()) { + size_t index = 0; + const TStringBuf step = path.NextTok(delimiter); + if (step.size() > 2 && *step.begin() == '[' && step.back() == ']' && TryFromString(step.substr(1, step.size() - 2), index)) { + currentJson = CreateOrNullptr(currentJson, index, create_tag); + } else { + currentJson = CreateOrNullptr(currentJson, step, create_tag); + } + + if (!currentJson) { + return nullptr; + } } - return currentJson; + return currentJson; } - } // anonymous namespace + } // anonymous namespace - bool TJsonValue::GetValueByPath(const TStringBuf path, TJsonValue& result, char delimiter) const { - const TJsonValue* const ptr = GetValuePtrByPath<false>(this, path, delimiter); - if (ptr) { - result = *ptr; - return true; - } - return false; + bool TJsonValue::GetValueByPath(const TStringBuf path, TJsonValue& result, char delimiter) const { + const TJsonValue* const ptr = GetValuePtrByPath<false>(this, path, delimiter); + if (ptr) { + result = *ptr; + return true; + } + return false; } - bool TJsonValue::SetValueByPath(const TStringBuf path, const TJsonValue& value, char delimiter) { - TJsonValue* const ptr = GetValuePtrByPath<true>(this, path, delimiter); - if (ptr) { - *ptr = value; - return true; - } - return false; + bool TJsonValue::SetValueByPath(const TStringBuf path, const TJsonValue& value, char delimiter) { + TJsonValue* const ptr = GetValuePtrByPath<true>(this, path, delimiter); + if (ptr) { + *ptr = value; + return true; + } + return false; } - bool TJsonValue::SetValueByPath(const TStringBuf path, TJsonValue&& value, char delimiter) { - TJsonValue* const ptr = GetValuePtrByPath<true>(this, path, delimiter); - if (ptr) { - *ptr = std::move(value); - return true; - } - return false; + bool TJsonValue::SetValueByPath(const TStringBuf path, TJsonValue&& value, char delimiter) { + TJsonValue* const ptr = GetValuePtrByPath<true>(this, path, delimiter); + if (ptr) { + *ptr = std::move(value); + return true; + } + return false; } - const TJsonValue* TJsonValue::GetValueByPath(const TStringBuf key, char delim) const noexcept { - return GetValuePtrByPath<false>(this, key, delim); + const TJsonValue* TJsonValue::GetValueByPath(const TStringBuf key, char delim) const noexcept { + return GetValuePtrByPath<false>(this, key, delim); } - TJsonValue* TJsonValue::GetValueByPath(const TStringBuf key, char delim) noexcept { - return GetValuePtrByPath<false>(this, key, delim); + TJsonValue* TJsonValue::GetValueByPath(const TStringBuf key, char delim) noexcept { + return GetValuePtrByPath<false>(this, key, delim); } - void TJsonValue::DoScan(const TString& path, TJsonValue* parent, IScanCallback& callback) { - if (!callback.Do(path, parent, *this)) { - return; + void TJsonValue::DoScan(const TString& path, TJsonValue* parent, IScanCallback& callback) { + if (!callback.Do(path, parent, *this)) { + return; } - - if (Type == JSON_MAP) { - for (auto&& i : *Value.Map) { + + if (Type == JSON_MAP) { + for (auto&& i : *Value.Map) { i.second.DoScan(!!path ? TString::Join(path, ".", i.first) : i.first, this, callback); - } - } else if (Type == JSON_ARRAY) { - for (ui32 i = 0; i < Value.Array->size(); ++i) { + } + } else if (Type == JSON_ARRAY) { + for (ui32 i = 0; i < Value.Array->size(); ++i) { (*Value.Array)[i].DoScan(TString::Join(path, "[", ToString(i), "]"), this, callback); - } + } } } - void TJsonValue::Scan(IScanCallback& callback) { - DoScan("", nullptr, callback); + void TJsonValue::Scan(IScanCallback& callback) { + DoScan("", nullptr, callback); } - bool TJsonValue::IsString() const noexcept { - return Type == JSON_STRING; + bool TJsonValue::IsString() const noexcept { + return Type == JSON_STRING; } - bool TJsonValue::IsMap() const noexcept { - return Type == JSON_MAP; + bool TJsonValue::IsMap() const noexcept { + return Type == JSON_MAP; } - bool TJsonValue::IsArray() const noexcept { - return Type == JSON_ARRAY; + bool TJsonValue::IsArray() const noexcept { + return Type == JSON_ARRAY; } - bool TJsonValue::Has(const TStringBuf& key) const noexcept { + bool TJsonValue::Has(const TStringBuf& key) const noexcept { return Type == JSON_MAP && Value.Map->contains(key); } - bool TJsonValue::Has(size_t key) const noexcept { - return Type == JSON_ARRAY && Value.Array->size() > key; - } - - bool TJsonValue::operator==(const TJsonValue& rhs) const { - switch (Type) { - case JSON_UNDEFINED: { - return (rhs.GetType() == JSON_UNDEFINED); - } - - case JSON_NULL: { - return rhs.IsNull(); - } - - case JSON_BOOLEAN: { - return (rhs.IsBoolean() && Value.Boolean == rhs.Value.Boolean); - } - - case JSON_INTEGER: { - return (rhs.IsInteger() && GetInteger() == rhs.GetInteger()); - } - - case JSON_UINTEGER: { - return (rhs.IsUInteger() && GetUInteger() == rhs.GetUInteger()); - } - - case JSON_STRING: { - return (rhs.IsString() && Value.String == rhs.Value.String); - } - - case JSON_DOUBLE: { - return (rhs.IsDouble() && fabs(GetDouble() - rhs.GetDouble()) <= FLT_EPSILON); - } - - case JSON_MAP: - return AreJsonMapsEqual(*this, rhs); - - case JSON_ARRAY: - return AreJsonArraysEqual(*this, rhs); - - default: - Y_ASSERT(false && "Unknown type."); - return false; - } - } - - void TJsonValue::SwapWithUndefined(TJsonValue& output) noexcept { - if (Type == JSON_STRING) { - static_assert(std::is_nothrow_move_constructible<TString>::value, "noexcept violation! Add some try {} catch (...) logic"); - new (&output.Value.String) TString(std::move(Value.String)); - Value.String.~TString(); - } else { - std::memcpy(&output.Value, &Value, sizeof(Value)); - } - - output.Type = Type; - Type = JSON_UNDEFINED; - } - - void TJsonValue::Swap(TJsonValue& rhs) noexcept { - TJsonValue tmp(std::move(*this)); - rhs.SwapWithUndefined(*this); - tmp.SwapWithUndefined(rhs); - } + bool TJsonValue::Has(size_t key) const noexcept { + return Type == JSON_ARRAY && Value.Array->size() > key; + } + + bool TJsonValue::operator==(const TJsonValue& rhs) const { + switch (Type) { + case JSON_UNDEFINED: { + return (rhs.GetType() == JSON_UNDEFINED); + } + + case JSON_NULL: { + return rhs.IsNull(); + } + + case JSON_BOOLEAN: { + return (rhs.IsBoolean() && Value.Boolean == rhs.Value.Boolean); + } + + case JSON_INTEGER: { + return (rhs.IsInteger() && GetInteger() == rhs.GetInteger()); + } + + case JSON_UINTEGER: { + return (rhs.IsUInteger() && GetUInteger() == rhs.GetUInteger()); + } + + case JSON_STRING: { + return (rhs.IsString() && Value.String == rhs.Value.String); + } + + case JSON_DOUBLE: { + return (rhs.IsDouble() && fabs(GetDouble() - rhs.GetDouble()) <= FLT_EPSILON); + } + + case JSON_MAP: + return AreJsonMapsEqual(*this, rhs); + + case JSON_ARRAY: + return AreJsonArraysEqual(*this, rhs); + + default: + Y_ASSERT(false && "Unknown type."); + return false; + } + } + + void TJsonValue::SwapWithUndefined(TJsonValue& output) noexcept { + if (Type == JSON_STRING) { + static_assert(std::is_nothrow_move_constructible<TString>::value, "noexcept violation! Add some try {} catch (...) logic"); + new (&output.Value.String) TString(std::move(Value.String)); + Value.String.~TString(); + } else { + std::memcpy(&output.Value, &Value, sizeof(Value)); + } + + output.Type = Type; + Type = JSON_UNDEFINED; + } + + void TJsonValue::Swap(TJsonValue& rhs) noexcept { + TJsonValue tmp(std::move(*this)); + rhs.SwapWithUndefined(*this); + tmp.SwapWithUndefined(rhs); + } void TJsonValue::Save(IOutputStream* s) const { ::Save(s, static_cast<ui8>(Type)); @@ -1051,43 +1051,43 @@ namespace NJson { } } - //**************************************************************** + //**************************************************************** - bool GetMapPointer(const TJsonValue& jv, const size_t index, const TJsonValue::TMapType** value) { - const TJsonValue* v; - if (!jv.GetValuePointer(index, &v) || !v->IsMap()) - return false; + bool GetMapPointer(const TJsonValue& jv, const size_t index, const TJsonValue::TMapType** value) { + const TJsonValue* v; + if (!jv.GetValuePointer(index, &v) || !v->IsMap()) + return false; - *value = &v->GetMap(); - return true; - } + *value = &v->GetMap(); + return true; + } - bool GetArrayPointer(const TJsonValue& jv, const size_t index, const TJsonValue::TArray** value) { - const TJsonValue* v; - if (!jv.GetValuePointer(index, &v) || !v->IsArray()) - return false; + bool GetArrayPointer(const TJsonValue& jv, const size_t index, const TJsonValue::TArray** value) { + const TJsonValue* v; + if (!jv.GetValuePointer(index, &v) || !v->IsArray()) + return false; - *value = &v->GetArray(); - return true; - } + *value = &v->GetArray(); + return true; + } - bool GetMapPointer(const TJsonValue& jv, const TStringBuf key, const TJsonValue::TMapType** value) { - const TJsonValue* v; - if (!jv.GetValuePointer(key, &v) || !v->IsMap()) - return false; + bool GetMapPointer(const TJsonValue& jv, const TStringBuf key, const TJsonValue::TMapType** value) { + const TJsonValue* v; + if (!jv.GetValuePointer(key, &v) || !v->IsMap()) + return false; - *value = &v->GetMap(); - return true; - } + *value = &v->GetMap(); + return true; + } - bool GetArrayPointer(const TJsonValue& jv, const TStringBuf key, const TJsonValue::TArray** value) { - const TJsonValue* v; - if (!jv.GetValuePointer(key, &v) || !v->IsArray()) - return false; + bool GetArrayPointer(const TJsonValue& jv, const TStringBuf key, const TJsonValue::TArray** value) { + const TJsonValue* v; + if (!jv.GetValuePointer(key, &v) || !v->IsArray()) + return false; - *value = &v->GetArray(); - return true; - } + *value = &v->GetArray(); + return true; + } void TJsonValue::BackChecks() const { if (Type != JSON_ARRAY) @@ -1098,8 +1098,8 @@ namespace NJson { } } -template <> +template <> void Out<NJson::TJsonValue>(IOutputStream& out, const NJson::TJsonValue& v) { NJsonWriter::TBuf buf(NJsonWriter::HEM_DONT_ESCAPE_HTML, &out); buf.WriteJsonValue(&v); -} +} diff --git a/library/cpp/json/writer/json_value.h b/library/cpp/json/writer/json_value.h index 721453f001..3f0f50bc4c 100644 --- a/library/cpp/json/writer/json_value.h +++ b/library/cpp/json/writer/json_value.h @@ -1,189 +1,189 @@ #pragma once #include <library/cpp/json/common/defs.h> - + #include <util/generic/string.h> #include <util/generic/hash.h> #include <util/generic/vector.h> -#include <util/generic/deque.h> +#include <util/generic/deque.h> #include <util/generic/utility.h> #include <util/generic/yexception.h> namespace NJson { - enum EJsonValueType { - JSON_UNDEFINED /* "Undefined" */, - JSON_NULL /* "Null" */, - JSON_BOOLEAN /* "Boolean" */, - JSON_INTEGER /* "Integer" */, - JSON_DOUBLE /* "Double" */, - JSON_STRING /* "String" */, - JSON_MAP /* "Map" */, - JSON_ARRAY /* "Array" */, - JSON_UINTEGER /* "UInteger" */ - }; - - class TJsonValue; - - class IScanCallback { - public: + enum EJsonValueType { + JSON_UNDEFINED /* "Undefined" */, + JSON_NULL /* "Null" */, + JSON_BOOLEAN /* "Boolean" */, + JSON_INTEGER /* "Integer" */, + JSON_DOUBLE /* "Double" */, + JSON_STRING /* "String" */, + JSON_MAP /* "Map" */, + JSON_ARRAY /* "Array" */, + JSON_UINTEGER /* "UInteger" */ + }; + + class TJsonValue; + + class IScanCallback { + public: virtual ~IScanCallback() = default; - virtual bool Do(const TString& path, TJsonValue* parent, TJsonValue& value) = 0; - }; - - class TJsonValue { - void Clear() noexcept; - - public: - typedef THashMap<TString, TJsonValue> TMapType; - typedef TDeque<TJsonValue> TArray; - - TJsonValue() noexcept = default; - TJsonValue(EJsonValueType type); - TJsonValue(bool value) noexcept; - TJsonValue(int value) noexcept; - TJsonValue(unsigned int value) noexcept; - TJsonValue(long value) noexcept; - TJsonValue(unsigned long value) noexcept; - TJsonValue(long long value) noexcept; - TJsonValue(unsigned long long value) noexcept; - TJsonValue(double value) noexcept; + virtual bool Do(const TString& path, TJsonValue* parent, TJsonValue& value) = 0; + }; + + class TJsonValue { + void Clear() noexcept; + + public: + typedef THashMap<TString, TJsonValue> TMapType; + typedef TDeque<TJsonValue> TArray; + + TJsonValue() noexcept = default; + TJsonValue(EJsonValueType type); + TJsonValue(bool value) noexcept; + TJsonValue(int value) noexcept; + TJsonValue(unsigned int value) noexcept; + TJsonValue(long value) noexcept; + TJsonValue(unsigned long value) noexcept; + TJsonValue(long long value) noexcept; + TJsonValue(unsigned long long value) noexcept; + TJsonValue(double value) noexcept; TJsonValue(TString value); - TJsonValue(const char* value); - template <class T> - TJsonValue(const T*) = delete; - TJsonValue(TStringBuf value); - - TJsonValue(const std::string& s) - : TJsonValue(TStringBuf(s)) - { - } - - TJsonValue(const TJsonValue& vval); - TJsonValue(TJsonValue&& vval) noexcept; - - TJsonValue& operator=(const TJsonValue& val); - TJsonValue& operator=(TJsonValue&& val) noexcept; - - ~TJsonValue() { - Clear(); - } - - EJsonValueType GetType() const noexcept; - TJsonValue& SetType(EJsonValueType type); - - TJsonValue& SetValue(const TJsonValue& value); - TJsonValue& SetValue(TJsonValue&& value); - - // for Map - TJsonValue& InsertValue(const TString& key, const TJsonValue& value); - TJsonValue& InsertValue(TStringBuf key, const TJsonValue& value); - TJsonValue& InsertValue(const char* key, const TJsonValue& value); - TJsonValue& InsertValue(const TString& key, TJsonValue&& value); - TJsonValue& InsertValue(TStringBuf key, TJsonValue&& value); - TJsonValue& InsertValue(const char* key, TJsonValue&& value); - - // for Array - TJsonValue& AppendValue(const TJsonValue& value); - TJsonValue& AppendValue(TJsonValue&& value); - TJsonValue& Back(); + TJsonValue(const char* value); + template <class T> + TJsonValue(const T*) = delete; + TJsonValue(TStringBuf value); + + TJsonValue(const std::string& s) + : TJsonValue(TStringBuf(s)) + { + } + + TJsonValue(const TJsonValue& vval); + TJsonValue(TJsonValue&& vval) noexcept; + + TJsonValue& operator=(const TJsonValue& val); + TJsonValue& operator=(TJsonValue&& val) noexcept; + + ~TJsonValue() { + Clear(); + } + + EJsonValueType GetType() const noexcept; + TJsonValue& SetType(EJsonValueType type); + + TJsonValue& SetValue(const TJsonValue& value); + TJsonValue& SetValue(TJsonValue&& value); + + // for Map + TJsonValue& InsertValue(const TString& key, const TJsonValue& value); + TJsonValue& InsertValue(TStringBuf key, const TJsonValue& value); + TJsonValue& InsertValue(const char* key, const TJsonValue& value); + TJsonValue& InsertValue(const TString& key, TJsonValue&& value); + TJsonValue& InsertValue(TStringBuf key, TJsonValue&& value); + TJsonValue& InsertValue(const char* key, TJsonValue&& value); + + // for Array + TJsonValue& AppendValue(const TJsonValue& value); + TJsonValue& AppendValue(TJsonValue&& value); + TJsonValue& Back(); const TJsonValue& Back() const; - bool GetValueByPath(TStringBuf path, TJsonValue& result, char delimiter = '.') const; - bool SetValueByPath(TStringBuf path, const TJsonValue& value, char delimiter = '.'); - bool SetValueByPath(TStringBuf path, TJsonValue&& value, char delimiter = '.'); - - // returns NULL on failure - const TJsonValue* GetValueByPath(TStringBuf path, char delimiter = '.') const noexcept; - TJsonValue* GetValueByPath(TStringBuf path, char delimiter = '.') noexcept; - - void EraseValue(TStringBuf key); - void EraseValue(size_t index); - - TJsonValue& operator[](size_t idx); - TJsonValue& operator[](const TStringBuf& key); - const TJsonValue& operator[](size_t idx) const noexcept; - const TJsonValue& operator[](const TStringBuf& key) const noexcept; - - bool GetBoolean() const; - long long GetInteger() const; - unsigned long long GetUInteger() const; - double GetDouble() const; - const TString& GetString() const; - const TMapType& GetMap() const; - const TArray& GetArray() const; - - //throwing TJsonException possible - bool GetBooleanSafe() const; - long long GetIntegerSafe() const; - unsigned long long GetUIntegerSafe() const; - double GetDoubleSafe() const; - const TString& GetStringSafe() const; - const TMapType& GetMapSafe() const; - TMapType& GetMapSafe(); - const TArray& GetArraySafe() const; - TArray& GetArraySafe(); - - bool GetBooleanSafe(bool defaultValue) const; - long long GetIntegerSafe(long long defaultValue) const; - unsigned long long GetUIntegerSafe(unsigned long long defaultValue) const; - double GetDoubleSafe(double defaultValue) const; - TString GetStringSafe(const TString& defaultValue) const; - - bool GetBooleanRobust() const noexcept; - long long GetIntegerRobust() const noexcept; - unsigned long long GetUIntegerRobust() const noexcept; - double GetDoubleRobust() const noexcept; - TString GetStringRobust() const; - - // Exception-free accessors - bool GetBoolean(bool* value) const noexcept; - bool GetInteger(long long* value) const noexcept; - bool GetUInteger(unsigned long long* value) const noexcept; - bool GetDouble(double* value) const noexcept; - bool GetMapPointer(const TMapType** value) const noexcept; - bool GetArrayPointer(const TArray** value) const noexcept; - - bool GetString(TString* value) const; - bool GetMap(TMapType* value) const; - bool GetArray(TArray* value) const; - bool GetValue(size_t index, TJsonValue* value) const; - bool GetValue(TStringBuf key, TJsonValue* value) const; - bool GetValuePointer(size_t index, const TJsonValue** value) const noexcept; - bool GetValuePointer(TStringBuf key, const TJsonValue** value) const noexcept; - bool GetValuePointer(TStringBuf key, TJsonValue** value) noexcept; - - // Checking for defined non-null value - bool IsDefined() const noexcept { - return Type != JSON_UNDEFINED && Type != JSON_NULL; - } - - bool IsNull() const noexcept; - bool IsBoolean() const noexcept; - bool IsDouble() const noexcept; - bool IsString() const noexcept; - bool IsMap() const noexcept; - bool IsArray() const noexcept; - - /// @return true if JSON_INTEGER or (JSON_UINTEGER and Value <= Max<long long>) - bool IsInteger() const noexcept; - - /// @return true if JSON_UINTEGER or (JSON_INTEGER and Value >= 0) - bool IsUInteger() const noexcept; - - bool Has(const TStringBuf& key) const noexcept; - bool Has(size_t key) const noexcept; - - void Scan(IScanCallback& callback); - - /// Non-robust comparison. - bool operator==(const TJsonValue& rhs) const; - - bool operator!=(const TJsonValue& rhs) const { - return !(*this == rhs); - } - - void Swap(TJsonValue& rhs) noexcept; + bool GetValueByPath(TStringBuf path, TJsonValue& result, char delimiter = '.') const; + bool SetValueByPath(TStringBuf path, const TJsonValue& value, char delimiter = '.'); + bool SetValueByPath(TStringBuf path, TJsonValue&& value, char delimiter = '.'); + + // returns NULL on failure + const TJsonValue* GetValueByPath(TStringBuf path, char delimiter = '.') const noexcept; + TJsonValue* GetValueByPath(TStringBuf path, char delimiter = '.') noexcept; + + void EraseValue(TStringBuf key); + void EraseValue(size_t index); + + TJsonValue& operator[](size_t idx); + TJsonValue& operator[](const TStringBuf& key); + const TJsonValue& operator[](size_t idx) const noexcept; + const TJsonValue& operator[](const TStringBuf& key) const noexcept; + + bool GetBoolean() const; + long long GetInteger() const; + unsigned long long GetUInteger() const; + double GetDouble() const; + const TString& GetString() const; + const TMapType& GetMap() const; + const TArray& GetArray() const; + + //throwing TJsonException possible + bool GetBooleanSafe() const; + long long GetIntegerSafe() const; + unsigned long long GetUIntegerSafe() const; + double GetDoubleSafe() const; + const TString& GetStringSafe() const; + const TMapType& GetMapSafe() const; + TMapType& GetMapSafe(); + const TArray& GetArraySafe() const; + TArray& GetArraySafe(); + + bool GetBooleanSafe(bool defaultValue) const; + long long GetIntegerSafe(long long defaultValue) const; + unsigned long long GetUIntegerSafe(unsigned long long defaultValue) const; + double GetDoubleSafe(double defaultValue) const; + TString GetStringSafe(const TString& defaultValue) const; + + bool GetBooleanRobust() const noexcept; + long long GetIntegerRobust() const noexcept; + unsigned long long GetUIntegerRobust() const noexcept; + double GetDoubleRobust() const noexcept; + TString GetStringRobust() const; + + // Exception-free accessors + bool GetBoolean(bool* value) const noexcept; + bool GetInteger(long long* value) const noexcept; + bool GetUInteger(unsigned long long* value) const noexcept; + bool GetDouble(double* value) const noexcept; + bool GetMapPointer(const TMapType** value) const noexcept; + bool GetArrayPointer(const TArray** value) const noexcept; + + bool GetString(TString* value) const; + bool GetMap(TMapType* value) const; + bool GetArray(TArray* value) const; + bool GetValue(size_t index, TJsonValue* value) const; + bool GetValue(TStringBuf key, TJsonValue* value) const; + bool GetValuePointer(size_t index, const TJsonValue** value) const noexcept; + bool GetValuePointer(TStringBuf key, const TJsonValue** value) const noexcept; + bool GetValuePointer(TStringBuf key, TJsonValue** value) noexcept; + + // Checking for defined non-null value + bool IsDefined() const noexcept { + return Type != JSON_UNDEFINED && Type != JSON_NULL; + } + + bool IsNull() const noexcept; + bool IsBoolean() const noexcept; + bool IsDouble() const noexcept; + bool IsString() const noexcept; + bool IsMap() const noexcept; + bool IsArray() const noexcept; + + /// @return true if JSON_INTEGER or (JSON_UINTEGER and Value <= Max<long long>) + bool IsInteger() const noexcept; + + /// @return true if JSON_UINTEGER or (JSON_INTEGER and Value >= 0) + bool IsUInteger() const noexcept; + + bool Has(const TStringBuf& key) const noexcept; + bool Has(size_t key) const noexcept; + + void Scan(IScanCallback& callback); + + /// Non-robust comparison. + bool operator==(const TJsonValue& rhs) const; + + bool operator!=(const TJsonValue& rhs) const { + return !(*this == rhs); + } + + void Swap(TJsonValue& rhs) noexcept; // save using util/ysaveload.h serialization (not to JSON stream) void Save(IOutputStream* s) const; @@ -191,28 +191,28 @@ namespace NJson { // load using util/ysaveload.h serialization (not as JSON stream) void Load(IInputStream* s); - static const TJsonValue UNDEFINED; + static const TJsonValue UNDEFINED; - private: - EJsonValueType Type = JSON_UNDEFINED; - union TValueUnion { - bool Boolean; - long long Integer; - unsigned long long UInteger; - double Double; - TString String; - TMapType* Map; - TArray* Array; + private: + EJsonValueType Type = JSON_UNDEFINED; + union TValueUnion { + bool Boolean; + long long Integer; + unsigned long long UInteger; + double Double; + TString String; + TMapType* Map; + TArray* Array; - TValueUnion() noexcept { + TValueUnion() noexcept { Zero(*this); - } - ~TValueUnion() noexcept { - } - }; - TValueUnion Value; - void DoScan(const TString& path, TJsonValue* parent, IScanCallback& callback); - void SwapWithUndefined(TJsonValue& output) noexcept; + } + ~TValueUnion() noexcept { + } + }; + TValueUnion Value; + void DoScan(const TString& path, TJsonValue* parent, IScanCallback& callback); + void SwapWithUndefined(TJsonValue& output) noexcept; /** @throw yexception if Back shouldn't be called on the object. @@ -220,51 +220,51 @@ namespace NJson { void BackChecks() const; }; - inline bool GetBoolean(const TJsonValue& jv, size_t index, bool* value) noexcept { - return jv[index].GetBoolean(value); - } + inline bool GetBoolean(const TJsonValue& jv, size_t index, bool* value) noexcept { + return jv[index].GetBoolean(value); + } - inline bool GetInteger(const TJsonValue& jv, size_t index, long long* value) noexcept { - return jv[index].GetInteger(value); - } + inline bool GetInteger(const TJsonValue& jv, size_t index, long long* value) noexcept { + return jv[index].GetInteger(value); + } - inline bool GetUInteger(const TJsonValue& jv, size_t index, unsigned long long* value) noexcept { - return jv[index].GetUInteger(value); - } + inline bool GetUInteger(const TJsonValue& jv, size_t index, unsigned long long* value) noexcept { + return jv[index].GetUInteger(value); + } - inline bool GetDouble(const TJsonValue& jv, size_t index, double* value) noexcept { - return jv[index].GetDouble(value); - } + inline bool GetDouble(const TJsonValue& jv, size_t index, double* value) noexcept { + return jv[index].GetDouble(value); + } - inline bool GetString(const TJsonValue& jv, size_t index, TString* value) { - return jv[index].GetString(value); - } + inline bool GetString(const TJsonValue& jv, size_t index, TString* value) { + return jv[index].GetString(value); + } - bool GetMapPointer(const TJsonValue& jv, size_t index, const TJsonValue::TMapType** value); - bool GetArrayPointer(const TJsonValue& jv, size_t index, const TJsonValue::TArray** value); + bool GetMapPointer(const TJsonValue& jv, size_t index, const TJsonValue::TMapType** value); + bool GetArrayPointer(const TJsonValue& jv, size_t index, const TJsonValue::TArray** value); - inline bool GetBoolean(const TJsonValue& jv, TStringBuf key, bool* value) noexcept { - return jv[key].GetBoolean(value); - } + inline bool GetBoolean(const TJsonValue& jv, TStringBuf key, bool* value) noexcept { + return jv[key].GetBoolean(value); + } - inline bool GetInteger(const TJsonValue& jv, TStringBuf key, long long* value) noexcept { - return jv[key].GetInteger(value); - } + inline bool GetInteger(const TJsonValue& jv, TStringBuf key, long long* value) noexcept { + return jv[key].GetInteger(value); + } - inline bool GetUInteger(const TJsonValue& jv, TStringBuf key, unsigned long long* value) noexcept { - return jv[key].GetUInteger(value); - } + inline bool GetUInteger(const TJsonValue& jv, TStringBuf key, unsigned long long* value) noexcept { + return jv[key].GetUInteger(value); + } - inline bool GetDouble(const TJsonValue& jv, TStringBuf key, double* value) noexcept { - return jv[key].GetDouble(value); - } + inline bool GetDouble(const TJsonValue& jv, TStringBuf key, double* value) noexcept { + return jv[key].GetDouble(value); + } - inline bool GetString(const TJsonValue& jv, TStringBuf key, TString* value) { - return jv[key].GetString(value); - } + inline bool GetString(const TJsonValue& jv, TStringBuf key, TString* value) { + return jv[key].GetString(value); + } - bool GetMapPointer(const TJsonValue& jv, const TStringBuf key, const TJsonValue::TMapType** value); - bool GetArrayPointer(const TJsonValue& jv, const TStringBuf key, const TJsonValue::TArray** value); + bool GetMapPointer(const TJsonValue& jv, const TStringBuf key, const TJsonValue::TMapType** value); + bool GetArrayPointer(const TJsonValue& jv, const TStringBuf key, const TJsonValue::TArray** value); class TJsonMap: public TJsonValue { public: diff --git a/library/cpp/json/writer/json_value_ut.cpp b/library/cpp/json/writer/json_value_ut.cpp index d3f3c42bea..dc7f6affdf 100644 --- a/library/cpp/json/writer/json_value_ut.cpp +++ b/library/cpp/json/writer/json_value_ut.cpp @@ -18,7 +18,7 @@ Y_UNIT_TEST_SUITE(TJsonValueTest) { TJsonValue emptyMap(JSON_MAP); UNIT_ASSERT(!undef.IsDefined()); - UNIT_ASSERT(!null.IsDefined()); // json NULL is undefined too! + UNIT_ASSERT(!null.IsDefined()); // json NULL is undefined too! UNIT_ASSERT(_false.IsDefined()); UNIT_ASSERT(zeroInt.IsDefined()); UNIT_ASSERT(zeroDouble.IsDefined()); @@ -259,7 +259,7 @@ Y_UNIT_TEST_SUITE(TJsonValueTest) { UNIT_ASSERT_EQUAL(lhs.GetValueByPath("l/a/c/e/x", '/'), NULL); UNIT_ASSERT_EQUAL(lhs.GetValueByPath("a/c/e/x", '/'), NULL); UNIT_ASSERT_EQUAL(lhs.GetValueByPath("nokey", '/'), NULL); - UNIT_ASSERT_EQUAL(*lhs.GetValueByPath("", '/'), lhs); // itself + UNIT_ASSERT_EQUAL(*lhs.GetValueByPath("", '/'), lhs); // itself TJsonValue array; TJsonValue third; @@ -325,7 +325,7 @@ Y_UNIT_TEST_SUITE(TJsonValueTest) { } { const TJsonValue* result = lhs.GetValueByPath("", '/'); - UNIT_ASSERT_EQUAL(*result, lhs); // itself + UNIT_ASSERT_EQUAL(*result, lhs); // itself } TJsonValue array; @@ -335,8 +335,8 @@ Y_UNIT_TEST_SUITE(TJsonValueTest) { third["t"] = array; UNIT_ASSERT(array.GetValueByPath("[0].e", '.')->GetStringRobust() == "f"); - UNIT_ASSERT(third.GetValueByPath("t.[0].e", '.')->GetStringRobust() == "f"); - UNIT_ASSERT(third.GetValueByPath("t.[1].c.e", '.')->GetStringRobust() == "f"); + UNIT_ASSERT(third.GetValueByPath("t.[0].e", '.')->GetStringRobust() == "f"); + UNIT_ASSERT(third.GetValueByPath("t.[1].c.e", '.')->GetStringRobust() == "f"); } Y_UNIT_TEST(EraseValueFromArray) { @@ -385,7 +385,7 @@ Y_UNIT_TEST_SUITE(TJsonValueTest) { value1.AppendValue(1); value1.AppendValue(2); src.InsertValue("key", value1); - src.InsertValue("key1", "HI!"); + src.InsertValue("key1", "HI!"); TJsonValue dst; TJsonValue value2; @@ -426,7 +426,7 @@ Y_UNIT_TEST_SUITE(TJsonValueTest) { dst.InsertValue("arr", arr2); src["arr"].AppendValue(value1); - for (auto& node : src["arr"].GetArraySafe()) { + for (auto& node : src["arr"].GetArraySafe()) { node.InsertValue("yek", "eulav"); } UNIT_ASSERT(src == dst); @@ -550,7 +550,7 @@ Y_UNIT_TEST_SUITE(TJsonValueTest) { outer.AppendValue(json); } - const TJsonValue::TArray* array = nullptr; + const TJsonValue::TArray* array = nullptr; GetArrayPointer(outer, 0, &array); UNIT_ASSERT_VALUES_EQUAL((*array)[1], 2); } @@ -565,7 +565,7 @@ Y_UNIT_TEST_SUITE(TJsonValueTest) { outer.InsertValue("x", json); } - const TJsonValue::TArray* array = nullptr; + const TJsonValue::TArray* array = nullptr; GetArrayPointer(outer, "x", &array); UNIT_ASSERT_VALUES_EQUAL((*array)[1], 2); } @@ -580,7 +580,7 @@ Y_UNIT_TEST_SUITE(TJsonValueTest) { outer.AppendValue(json); } - const TJsonValue::TMapType* map = nullptr; + const TJsonValue::TMapType* map = nullptr; GetMapPointer(outer, 0, &map); UNIT_ASSERT_VALUES_EQUAL((*map).at("b"), 2); } @@ -595,7 +595,7 @@ Y_UNIT_TEST_SUITE(TJsonValueTest) { outer.InsertValue("x", json); } - const TJsonValue::TMapType* map = nullptr; + const TJsonValue::TMapType* map = nullptr; GetMapPointer(outer, "x", &map); UNIT_ASSERT_VALUES_EQUAL((*map).at("b"), 2); } @@ -617,7 +617,7 @@ Y_UNIT_TEST_SUITE(TJsonValueTest) { const char* longTestString = "Testing TJsonValue& operator=(TJsonValue&&) subpart self moving " - "after TJsonValue was constrcuted from TString&&."; + "after TJsonValue was constrcuted from TString&&."; json["hello"] = TString{longTestString}; json = std::move(json["hello"]); diff --git a/library/cpp/json/writer/ya.make b/library/cpp/json/writer/ya.make index 1f1e2df08e..3989ff3504 100644 --- a/library/cpp/json/writer/ya.make +++ b/library/cpp/json/writer/ya.make @@ -5,8 +5,8 @@ OWNER( myltsev pg ) - -PEERDIR( + +PEERDIR( library/cpp/json/common ) diff --git a/library/cpp/json/ya.make b/library/cpp/json/ya.make index d46147f269..d58eead8ec 100644 --- a/library/cpp/json/ya.make +++ b/library/cpp/json/ya.make @@ -8,7 +8,7 @@ OWNER( SRCS( json_writer.cpp json_reader.cpp - json_prettifier.cpp + json_prettifier.cpp rapidjson_helpers.cpp ) |