123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- #include "value.h"
- #include <yql/essentials/minikql/dom/node.h>
- namespace NYql::NJsonPath {
- using namespace NUdf;
- using namespace NDom;
- using namespace NKikimr;
- using namespace NKikimr::NBinaryJson;
- TArrayIterator::TArrayIterator()
- : Iterator(TEmptyMarker())
- {
- }
- TArrayIterator::TArrayIterator(const TUnboxedValue& iterator)
- : Iterator(iterator)
- {
- }
- TArrayIterator::TArrayIterator(TUnboxedValue&& iterator)
- : Iterator(std::move(iterator))
- {
- }
- TArrayIterator::TArrayIterator(const NBinaryJson::TArrayIterator& iterator)
- : Iterator(iterator)
- {
- }
- TArrayIterator::TArrayIterator(NBinaryJson::TArrayIterator&& iterator)
- : Iterator(std::move(iterator))
- {
- }
- bool TArrayIterator::Next(TValue& value) {
- if (std::holds_alternative<TEmptyMarker>(Iterator)) {
- return false;
- } else if (auto* iterator = std::get_if<NBinaryJson::TArrayIterator>(&Iterator)) {
- if (!iterator->HasNext()) {
- return false;
- }
- value = TValue(iterator->Next());
- return true;
- } else if (auto* iterator = std::get_if<TUnboxedValue>(&Iterator)) {
- TUnboxedValue result;
- const bool success = iterator->Next(result);
- if (success) {
- value = TValue(result);
- }
- return success;
- } else {
- Y_ABORT("Unexpected variant case in Next");
- }
- }
- TObjectIterator::TObjectIterator()
- : Iterator(TEmptyMarker())
- {
- }
- TObjectIterator::TObjectIterator(const TUnboxedValue& iterator)
- : Iterator(iterator)
- {
- }
- TObjectIterator::TObjectIterator(TUnboxedValue&& iterator)
- : Iterator(std::move(iterator))
- {
- }
- TObjectIterator::TObjectIterator(const NBinaryJson::TObjectIterator& iterator)
- : Iterator(iterator)
- {
- }
- TObjectIterator::TObjectIterator(NBinaryJson::TObjectIterator&& iterator)
- : Iterator(std::move(iterator))
- {
- }
- bool TObjectIterator::Next(TValue& key, TValue& value) {
- if (std::holds_alternative<TEmptyMarker>(Iterator)) {
- return false;
- } else if (auto* iterator = std::get_if<NBinaryJson::TObjectIterator>(&Iterator)) {
- if (!iterator->HasNext()) {
- return false;
- }
- const auto [itKey, itValue] = iterator->Next();
- key = TValue(itKey);
- value = TValue(itValue);
- return true;
- } else if (auto* iterator = std::get_if<TUnboxedValue>(&Iterator)) {
- TUnboxedValue itKey;
- TUnboxedValue itValue;
- const bool success = iterator->NextPair(itKey, itValue);
- if (success) {
- key = TValue(itKey);
- value = TValue(itValue);
- }
- return success;
- } else {
- Y_ABORT("Unexpected variant case in Next");
- }
- }
- TValue::TValue()
- : Value(MakeEntity())
- {
- }
- TValue::TValue(const TUnboxedValue& value)
- : Value(value)
- {
- }
- TValue::TValue(TUnboxedValue&& value)
- : Value(std::move(value))
- {
- }
- TValue::TValue(const TEntryCursor& value)
- : Value(value)
- {
- UnpackInnerValue();
- }
- TValue::TValue(TEntryCursor&& value)
- : Value(std::move(value))
- {
- UnpackInnerValue();
- }
- TValue::TValue(const TContainerCursor& value)
- : Value(value)
- {
- UnpackInnerValue();
- }
- TValue::TValue(TContainerCursor&& value)
- : Value(std::move(value))
- {
- UnpackInnerValue();
- }
- EValueType TValue::GetType() const {
- if (const auto* value = std::get_if<TEntryCursor>(&Value)) {
- switch (value->GetType()) {
- case EEntryType::BoolFalse:
- case EEntryType::BoolTrue:
- return EValueType::Bool;
- case EEntryType::Null:
- return EValueType::Null;
- case EEntryType::Number:
- return EValueType::Number;
- case EEntryType::String:
- return EValueType::String;
- case EEntryType::Container:
- Y_ABORT("Logical error: TEntryCursor with Container type must be converted to TContainerCursor");
- }
- } else if (const auto* value = std::get_if<TContainerCursor>(&Value)) {
- switch (value->GetType()) {
- case EContainerType::Array:
- return EValueType::Array;
- case EContainerType::Object:
- return EValueType::Object;
- case EContainerType::TopLevelScalar:
- Y_ABORT("Logical error: TContainerCursor with TopLevelScalar type must be converted to TEntryCursor");
- }
- } else if (const auto* value = std::get_if<TUnboxedValue>(&Value)) {
- switch (GetNodeType(*value)) {
- case ENodeType::Bool:
- return EValueType::Bool;
- case ENodeType::Double:
- case ENodeType::Int64:
- case ENodeType::Uint64:
- return EValueType::Number;
- case ENodeType::Dict:
- case ENodeType::Attr:
- return EValueType::Object;
- case ENodeType::List:
- return EValueType::Array;
- case ENodeType::String:
- return EValueType::String;
- case ENodeType::Entity:
- return EValueType::Null;
- }
- } else {
- Y_ABORT("Unexpected variant case in GetType");
- }
- }
- bool TValue::Is(EValueType type) const {
- return GetType() == type;
- }
- bool TValue::IsBool() const {
- return Is(EValueType::Bool);
- }
- bool TValue::IsNumber() const {
- return Is(EValueType::Number);
- }
- bool TValue::IsString() const {
- return Is(EValueType::String);
- }
- bool TValue::IsNull() const {
- return Is(EValueType::Null);
- }
- bool TValue::IsObject() const {
- return Is(EValueType::Object);
- }
- bool TValue::IsArray() const {
- return Is(EValueType::Array);
- }
- double TValue::GetNumber() const {
- Y_DEBUG_ABORT_UNLESS(IsNumber());
- if (const auto* value = std::get_if<TEntryCursor>(&Value)) {
- return value->GetNumber();
- } else if (const auto* value = std::get_if<TUnboxedValue>(&Value)) {
- if (IsNodeType(*value, ENodeType::Double)) {
- return value->Get<double>();
- } else if (IsNodeType(*value, ENodeType::Int64)) {
- return static_cast<double>(value->Get<i64>());
- } else {
- return static_cast<double>(value->Get<ui64>());
- }
- } else {
- Y_ABORT("Unexpected variant case in GetNumber");
- }
- }
- bool TValue::GetBool() const {
- Y_DEBUG_ABORT_UNLESS(IsBool());
- if (const auto* value = std::get_if<TEntryCursor>(&Value)) {
- return value->GetType() == EEntryType::BoolTrue;
- } else if (const auto* value = std::get_if<TUnboxedValue>(&Value)) {
- return value->Get<bool>();
- } else {
- Y_ABORT("Unexpected variant case in GetBool");
- }
- }
- const TStringBuf TValue::GetString() const {
- Y_DEBUG_ABORT_UNLESS(IsString());
- if (const auto* value = std::get_if<TEntryCursor>(&Value)) {
- return value->GetString();
- } else if (const auto* value = std::get_if<TUnboxedValue>(&Value)) {
- return value->AsStringRef();
- } else {
- Y_ABORT("Unexpected variant case in GetString");
- }
- }
- ui32 TValue::GetSize() const {
- Y_DEBUG_ABORT_UNLESS(IsArray() || IsObject());
- if (const auto* value = std::get_if<TContainerCursor>(&Value)) {
- return value->GetSize();
- } else if (const auto* value = std::get_if<TUnboxedValue>(&Value)) {
- if (value->IsEmbedded()) {
- return 0;
- }
- if (IsNodeType(*value, ENodeType::List)) {
- return value->GetListLength();
- } else {
- return value->GetDictLength();
- }
- } else {
- Y_ABORT("Unexpected variant case in GetSize");
- }
- }
- TValue TValue::GetElement(ui32 index) const {
- Y_DEBUG_ABORT_UNLESS(IsArray());
- if (const auto* value = std::get_if<TContainerCursor>(&Value)) {
- return TValue(value->GetElement(index));
- } else if (const auto* value = std::get_if<TUnboxedValue>(&Value)) {
- return TValue(value->Lookup(TUnboxedValuePod(index)));
- } else {
- Y_ABORT("Unexpected variant case in GetElement");
- }
- }
- TArrayIterator TValue::GetArrayIterator() const {
- Y_DEBUG_ABORT_UNLESS(IsArray());
- if (const auto* value = std::get_if<TContainerCursor>(&Value)) {
- return TArrayIterator(value->GetArrayIterator());
- } else if (const auto* value = std::get_if<TUnboxedValue>(&Value)) {
- if (value->IsEmbedded()) {
- return TArrayIterator();
- }
- return TArrayIterator(value->GetListIterator());
- } else {
- Y_ABORT("Unexpected variant case in GetArrayIterator");
- }
- }
- TMaybe<TValue> TValue::Lookup(const TStringBuf key) const {
- Y_DEBUG_ABORT_UNLESS(IsObject());
- if (const auto* value = std::get_if<TContainerCursor>(&Value)) {
- const auto payload = value->Lookup(key);
- if (!payload.Defined()) {
- return Nothing();
- }
- return TValue(*payload);
- } else if (const auto* value = std::get_if<TUnboxedValue>(&Value)) {
- if (value->IsEmbedded()) {
- return Nothing();
- }
- // Lookup on TUnboxedValue can be performed only with TUnboxedValue key.
- // To avoid allocating new string we use our custom Lookup method defined
- // on underlying TMapNode that accepts TStringRef
- const auto* dict = static_cast<const TMapNode*>(value->AsBoxed().Get());
- if (const auto payload = dict->Lookup(key)) {
- return {TValue(payload)};
- } else {
- return Nothing();
- }
- } else {
- Y_ABORT("Unexpected variant case in Lookup");
- }
- }
- TObjectIterator TValue::GetObjectIterator() const {
- Y_DEBUG_ABORT_UNLESS(IsObject());
- if (const auto* value = std::get_if<TContainerCursor>(&Value)) {
- return TObjectIterator(value->GetObjectIterator());
- } else if (const auto* value = std::get_if<TUnboxedValue>(&Value)) {
- if (value->IsEmbedded()) {
- return TObjectIterator();
- }
- return TObjectIterator(value->GetDictIterator());
- } else {
- Y_ABORT("Unexpected variant case in GetObjectIterator");
- }
- }
- TUnboxedValue TValue::ConvertToUnboxedValue(const NUdf::IValueBuilder* valueBuilder) const {
- if (const auto* value = std::get_if<TEntryCursor>(&Value)) {
- return ReadElementToJsonDom(*value, valueBuilder);
- } else if (const auto* value = std::get_if<TContainerCursor>(&Value)) {
- return ReadContainerToJsonDom(*value, valueBuilder);
- } else if (const auto* value = std::get_if<TUnboxedValue>(&Value)) {
- return *value;
- } else {
- Y_ABORT("Unexpected variant case in ConvertToUnboxedValue");
- }
- }
- void TValue::UnpackInnerValue() {
- // If TEntryCursor points to container, we need to extract TContainerCursor
- if (const auto* value = std::get_if<TEntryCursor>(&Value)) {
- if (value->GetType() == EEntryType::Container) {
- Value = value->GetContainer();
- }
- }
- // If TContainerCursor points to top level scalar, we need to extract TEntryCursor
- if (const auto* value = std::get_if<TContainerCursor>(&Value)) {
- if (value->GetType() == EContainerType::TopLevelScalar) {
- Value = value->GetElement(0);
- }
- }
- }
- }
|