#include "string.h" #include #include #include namespace NYT::NYson { //////////////////////////////////////////////////////////////////////////////// TYsonStringBuf::TYsonStringBuf() { Type_ = EYsonType::Node; // fake Null_ = true; } TYsonStringBuf::TYsonStringBuf(const TYsonString& ysonString) { if (ysonString) { Data_ = ysonString.AsStringBuf(); Type_ = ysonString.GetType(); Null_ = false; } else { Type_ = EYsonType::Node; // fake Null_ = true; } } TYsonStringBuf::TYsonStringBuf(const TString& data, EYsonType type) : TYsonStringBuf(TStringBuf(data), type) { } TYsonStringBuf::TYsonStringBuf(TStringBuf data, EYsonType type) : Data_(data) , Type_(type) , Null_(false) { } TYsonStringBuf::TYsonStringBuf(const char* data, EYsonType type) : TYsonStringBuf(TStringBuf(data), type) { } TYsonStringBuf::operator bool() const { return !Null_; } TStringBuf TYsonStringBuf::AsStringBuf() const { YT_VERIFY(*this); return Data_; } EYsonType TYsonStringBuf::GetType() const { YT_VERIFY(*this); return Type_; } //////////////////////////////////////////////////////////////////////////////// TYsonString::TYsonString() { Begin_ = nullptr; Size_ = 0; Type_ = EYsonType::Node; // fake } TYsonString::TYsonString(const TYsonStringBuf& ysonStringBuf) { if (ysonStringBuf) { auto data = ysonStringBuf.AsStringBuf(); auto holder = NDetail::TYsonStringHolder::Allocate(data.length()); ::memcpy(holder->GetData(), data.data(), data.length()); Begin_ = holder->GetData(); Size_ = data.Size(); Type_ = ysonStringBuf.GetType(); Payload_ = std::move(holder); } else { Begin_ = nullptr; Size_ = 0; Type_ = EYsonType::Node; // fake } } TYsonString::TYsonString( TStringBuf data, EYsonType type) : TYsonString(TYsonStringBuf(data, type)) { } #ifdef TSTRING_IS_STD_STRING TYsonString::TYsonString( const TString& data, EYsonType type) : TYsonString(TYsonStringBuf(data, type)) { } #else TYsonString::TYsonString( const TString& data, EYsonType type) { // NOTE: CoW TString implementation is assumed // Moving the payload MUST NOT invalidate its internal pointers Payload_ = data; Begin_ = data.data(); Size_ = data.length(); Type_ = type; } #endif TYsonString::TYsonString( const TSharedRef& data, EYsonType type) { Payload_ = data.GetHolder(); Begin_ = data.Begin(); Size_ = data.Size(); Type_ = type; } TYsonString::operator bool() const { return !std::holds_alternative(Payload_); } EYsonType TYsonString::GetType() const { YT_VERIFY(*this); return Type_; } TStringBuf TYsonString::AsStringBuf() const { YT_VERIFY(*this); return TStringBuf(Begin_, Begin_ + Size_); } TString TYsonString::ToString() const { return Visit( Payload_, [] (const TNullPayload&) -> TString { YT_ABORT(); }, [&] (const TSharedRangeHolderPtr&) { return TString(AsStringBuf()); }, [] (const TString& payload) { return payload; }); } TSharedRef TYsonString::ToSharedRef() const { return Visit( Payload_, [] (const TNullPayload&) -> TSharedRef { YT_ABORT(); }, [&] (const TSharedRangeHolderPtr& holder) { return TSharedRef(Begin_, Size_, holder); }, [] (const TString& payload) { return TSharedRef::FromString(payload); }); } size_t TYsonString::ComputeHash() const { return THash()(TStringBuf(Begin_, Begin_ + Size_)); } void TYsonString::Save(IOutputStream* s) const { EYsonType type = Type_; if (*this) { ::SaveMany(s, type, ToSharedRef()); } else { ::SaveMany(s, type, TString()); } } void TYsonString::Load(IInputStream* s) { EYsonType type; TString data; ::LoadMany(s, type, data); if (data) { *this = TYsonString(data, type); } else { *this = TYsonString(); } } //////////////////////////////////////////////////////////////////////////////// TString ToString(const TYsonString& yson) { return yson.ToString(); } TString ToString(const TYsonStringBuf& yson) { return TString(yson.AsStringBuf()); } //////////////////////////////////////////////////////////////////////////////// } // namespace NYT::NYson