#pragma once #include #include "value.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace NYql::NJsonPath { using TJsonNodes = TSmallVec; class TResult { public: TResult(TJsonNodes&& nodes); TResult(const TJsonNodes& nodes); TResult(TIssue&& issue); const TJsonNodes& GetNodes() const; TJsonNodes& GetNodes(); const TIssue& GetError() const; bool IsError() const; private: std::variant Result; }; class TArraySubscript { public: TArraySubscript(i64 from, TPosition fromPos) : From(from) , FromPos(fromPos) , HasTo(false) { } TArraySubscript(i64 from, TPosition fromPos, i64 to, TPosition toPos) : From(from) , FromPos(fromPos) , To(to) , ToPos(toPos) , HasTo(true) { } i64 GetFrom() const { return From; } TPosition GetFromPos() const { return FromPos; } i64 GetTo() const { YQL_ENSURE(IsRange()); return To; } TPosition GetToPos() const { return ToPos; } bool IsRange() const { return HasTo; } private: i64 From = 0; TPosition FromPos; i64 To = 0; TPosition ToPos; bool HasTo; }; using TVariablesMap = THashMap; class TExecutor { public: TExecutor( const TJsonPathPtr path, const TJsonNodes& input, const TVariablesMap& variables, const NUdf::IValueBuilder* valueBuilder); TResult Execute(); private: constexpr static double EPSILON = 1e-20; static bool IsZero(double value); static bool IsEqual(double a, double b); static bool IsLess(double a, double b); static bool IsGreater(double a, double b); bool IsStrict() const; bool IsLax() const; TResult Execute(const TJsonPathItem& item); TResult ContextObject(); TResult Variable(const TJsonPathItem& item); TResult LastArrayIndex(const TJsonPathItem& item); TResult NumberLiteral(const TJsonPathItem& item); TResult MemberAccess(const TJsonPathItem& item); TResult WildcardMemberAccess(const TJsonPathItem& item); TMaybe EnsureSingleSubscript(TPosition pos, const TJsonNodes& index, i64& result); TMaybe EnsureArraySubscripts(const TJsonPathItem& item, TVector& result); TResult ArrayAccess(const TJsonPathItem& item); TResult WildcardArrayAccess(const TJsonPathItem& item); TResult UnaryArithmeticOp(const TJsonPathItem& item); TMaybe EnsureBinaryArithmeticOpArgument(TPosition pos, const TJsonNodes& nodes, double& result); TResult BinaryArithmeticOp(const TJsonPathItem& item); TMaybe EnsureLogicalOpArgument(TPosition pos, const TJsonNodes& nodes, TMaybe& result); TResult BinaryLogicalOp(const TJsonPathItem& item); TResult UnaryLogicalOp(const TJsonPathItem& item); TResult BooleanLiteral(const TJsonPathItem& item); TResult NullLiteral(); TResult StringLiteral(const TJsonPathItem& item); TMaybe CompareValues(const TValue& left, const TValue& right, EJsonPathItemType operation); TResult CompareOp(const TJsonPathItem& item); TResult FilterObject(const TJsonPathItem& item); TResult FilterPredicate(const TJsonPathItem& item); TResult NumericMethod(const TJsonPathItem& item); TResult DoubleMethod(const TJsonPathItem& item); TResult TypeMethod(const TJsonPathItem& item); TResult SizeMethod(const TJsonPathItem& item); TResult KeyValueMethod(const TJsonPathItem& item); TResult StartsWithPredicate(const TJsonPathItem& item); TResult IsUnknownPredicate(const TJsonPathItem& item); TResult ExistsPredicate(const TJsonPathItem& item); TResult LikeRegexPredicate(const TJsonPathItem& item); TJsonNodes OptionalUnwrapArrays(const TJsonNodes& input); TJsonNodes OptionalArrayWrapNodes(const TJsonNodes& input); TStack ArraySubscriptSource; TStack CurrentFilterObject; TJsonPathReader Reader; TJsonNodes Input; const TVariablesMap& Variables; const NUdf::IValueBuilder* ValueBuilder; }; }