mkql_builtins_find.cpp 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. #include "mkql_builtins_impl.h" // Y_IGNORE
  2. namespace NKikimr {
  3. namespace NMiniKQL {
  4. namespace {
  5. template<bool Reverse>
  6. NUdf::TUnboxedValuePod Find(const NUdf::TUnboxedValuePod haystack, const NUdf::TUnboxedValuePod needle, std::string_view::size_type pos) {
  7. const std::string_view& one(haystack.AsStringRef());
  8. const std::string_view& two(needle.AsStringRef());
  9. const auto f = Reverse ? one.rfind(two, pos): one.find(two, pos);
  10. return std::string_view::npos == f ? NUdf::TUnboxedValuePod() : NUdf::TUnboxedValuePod(ui32(f));
  11. }
  12. template <bool PosOptional, bool Reverse>
  13. struct TFind {
  14. static constexpr std::string_view::size_type DefaultPos = Reverse ? std::string_view::npos : 0;
  15. static NUdf::TUnboxedValuePod Execute(NUdf::TUnboxedValuePod string, NUdf::TUnboxedValuePod sub, NUdf::TUnboxedValuePod pos)
  16. {
  17. return Find<Reverse>(string, sub, PosOptional && !pos ? DefaultPos : std::string_view::size_type(pos.Get<ui32>()));
  18. }
  19. #ifndef MKQL_DISABLE_CODEGEN
  20. static Value* Generate(Value* string, Value* sub, Value* p, const TCodegenContext& ctx, BasicBlock*& block)
  21. {
  22. auto& context = ctx.Codegen.GetContext();
  23. const auto doFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(Find<Reverse>));
  24. const auto pos = PosOptional ?
  25. SelectInst::Create(
  26. IsEmpty(p, block, context),
  27. ConstantInt::get(GetTypeFor<std::string_view::size_type>(context), DefaultPos),
  28. StaticCast<ui32, std::string_view::size_type>(GetterFor<ui32>(p, context, block), context, block),
  29. "pos", block):
  30. StaticCast<ui32, std::string_view::size_type>(GetterFor<ui32>(p, context, block), context, block);
  31. const auto funType = FunctionType::get(string->getType(), {string->getType(), sub->getType(), pos->getType()}, false);
  32. const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "func", block);
  33. const auto result = CallInst::Create(funType, funcPtr, {string, sub, pos}, "find", block);
  34. return result;
  35. }
  36. #endif
  37. };
  38. template <typename TInput, bool Reverse>
  39. void RegisterFindOpt(IBuiltinFunctionRegistry& registry, const char* name) {
  40. RegisterFunctionImpl<TFind<false, Reverse>, TTernaryArgs<NUdf::TDataType<ui32>, TInput, TInput, NUdf::TDataType<ui32>, false, false, false, true>, TTernaryWrap<false>>(registry, name);
  41. RegisterFunctionImpl<TFind<false, Reverse>, TTernaryArgs<NUdf::TDataType<ui32>, TInput, TInput, NUdf::TDataType<ui32>, true, false, false, true>, TTernaryWrap<true>>(registry, name);
  42. RegisterFunctionImpl<TFind<true, Reverse>, TTernaryArgs<NUdf::TDataType<ui32>, TInput, TInput, NUdf::TDataType<ui32>, false, false, true, true>, TTernaryWrap<false>>(registry, name);
  43. RegisterFunctionImpl<TFind<true, Reverse>, TTernaryArgs<NUdf::TDataType<ui32>, TInput, TInput, NUdf::TDataType<ui32>, true, false, true, true>, TTernaryWrap<true>>(registry, name);
  44. }
  45. }
  46. void RegisterFind(IBuiltinFunctionRegistry& registry) {
  47. RegisterFindOpt<NUdf::TDataType<char*>, false>(registry, "Find");
  48. RegisterFindOpt<NUdf::TDataType<NUdf::TUtf8>, false>(registry, "Find");
  49. RegisterFindOpt<NUdf::TDataType<char*>, true>(registry, "RFind");
  50. RegisterFindOpt<NUdf::TDataType<NUdf::TUtf8>, true>(registry, "RFind");
  51. }
  52. } // namespace NMiniKQL
  53. } // namespace NKikimr