#include "mkql_builtins_impl.h" // Y_IGNORE namespace NKikimr { namespace NMiniKQL { namespace { template NUdf::TUnboxedValuePod Find(const NUdf::TUnboxedValuePod haystack, const NUdf::TUnboxedValuePod needle, std::string_view::size_type pos) { const std::string_view& one(haystack.AsStringRef()); const std::string_view& two(needle.AsStringRef()); const auto f = Reverse ? one.rfind(two, pos): one.find(two, pos); return std::string_view::npos == f ? NUdf::TUnboxedValuePod() : NUdf::TUnboxedValuePod(ui32(f)); } template struct TFind { static constexpr std::string_view::size_type DefaultPos = Reverse ? std::string_view::npos : 0; static NUdf::TUnboxedValuePod Execute(NUdf::TUnboxedValuePod string, NUdf::TUnboxedValuePod sub, NUdf::TUnboxedValuePod pos) { return Find(string, sub, PosOptional && !pos ? DefaultPos : std::string_view::size_type(pos.Get())); } #ifndef MKQL_DISABLE_CODEGEN static Value* Generate(Value* string, Value* sub, Value* p, const TCodegenContext& ctx, BasicBlock*& block) { auto& context = ctx.Codegen.GetContext(); const auto doFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(Find)); const auto pos = PosOptional ? SelectInst::Create( IsEmpty(p, block, context), ConstantInt::get(GetTypeFor(context), DefaultPos), StaticCast(GetterFor(p, context, block), context, block), "pos", block): StaticCast(GetterFor(p, context, block), context, block); const auto funType = FunctionType::get(string->getType(), {string->getType(), sub->getType(), pos->getType()}, false); const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "func", block); const auto result = CallInst::Create(funType, funcPtr, {string, sub, pos}, "find", block); return result; } #endif }; template void RegisterFindOpt(IBuiltinFunctionRegistry& registry, const char* name) { RegisterFunctionImpl, TTernaryArgs, TInput, TInput, NUdf::TDataType, false, false, false, true>, TTernaryWrap>(registry, name); RegisterFunctionImpl, TTernaryArgs, TInput, TInput, NUdf::TDataType, true, false, false, true>, TTernaryWrap>(registry, name); RegisterFunctionImpl, TTernaryArgs, TInput, TInput, NUdf::TDataType, false, false, true, true>, TTernaryWrap>(registry, name); RegisterFunctionImpl, TTernaryArgs, TInput, TInput, NUdf::TDataType, true, false, true, true>, TTernaryWrap>(registry, name); } } void RegisterFind(IBuiltinFunctionRegistry& registry) { RegisterFindOpt, false>(registry, "Find"); RegisterFindOpt, false>(registry, "Find"); RegisterFindOpt, true>(registry, "RFind"); RegisterFindOpt, true>(registry, "RFind"); } } // namespace NMiniKQL } // namespace NKikimr