mkql_builtins_substring.cpp 4.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. #include "mkql_builtins_impl.h" // Y_IGNORE
  2. #include <yql/essentials/minikql/mkql_string_util.h>
  3. namespace NKikimr {
  4. namespace NMiniKQL {
  5. namespace {
  6. template <bool StartOptional, bool CountOptional>
  7. struct TSubString {
  8. static NUdf::TUnboxedValuePod Execute(NUdf::TUnboxedValuePod string, NUdf::TUnboxedValuePod start, NUdf::TUnboxedValuePod count)
  9. {
  10. return SubString(string,
  11. StartOptional && !start ? std::numeric_limits<ui32>::min() : start.Get<ui32>(),
  12. CountOptional && !count ? std::numeric_limits<ui32>::max() : count.Get<ui32>()
  13. );
  14. }
  15. #ifndef MKQL_DISABLE_CODEGEN
  16. static Value* Generate(Value* string, Value* st, Value* cn, const TCodegenContext& ctx, BasicBlock*& block)
  17. {
  18. auto& context = ctx.Codegen.GetContext();
  19. const auto doFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(SubString));
  20. const auto start = StartOptional ?
  21. SelectInst::Create(
  22. IsEmpty(st, block),
  23. ConstantInt::get(GetTypeFor<ui32>(context), std::numeric_limits<ui32>::min()),
  24. GetterFor<ui32>(st, context, block), "start", block
  25. ):
  26. GetterFor<ui32>(st, context, block);
  27. const auto count = CountOptional ?
  28. SelectInst::Create(
  29. IsEmpty(cn, block),
  30. ConstantInt::get(GetTypeFor<ui32>(context), std::numeric_limits<ui32>::max()),
  31. GetterFor<ui32>(cn, context, block), "count", block
  32. ):
  33. GetterFor<ui32>(cn, context, block);
  34. if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) {
  35. const auto funType = FunctionType::get(string->getType(), {string->getType(), start->getType(), count->getType()}, false);
  36. const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "func", block);
  37. const auto result = CallInst::Create(funType, funcPtr, {string, start, count}, "substring", block);
  38. return result;
  39. } else {
  40. const auto ptrArg = new AllocaInst(string->getType(), 0U, "arg", block);
  41. const auto ptrResult = new AllocaInst(string->getType(), 0U, "result", block);
  42. new StoreInst(string, ptrArg, block);
  43. const auto funType = FunctionType::get(Type::getVoidTy(context), {ptrResult->getType(), ptrArg->getType(), start->getType(), count->getType()}, false);
  44. const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "func", block);
  45. CallInst::Create(funType, funcPtr, {ptrResult, ptrArg, start, count}, "", block);
  46. const auto result = new LoadInst(string->getType(), ptrResult, "substring", block);
  47. return result;
  48. }
  49. }
  50. #endif
  51. };
  52. template <typename TInput>
  53. void RegisterSubstringnOpt(IBuiltinFunctionRegistry& registry, const char* name) {
  54. RegisterFunctionImpl<TSubString<false, false>, TTernaryArgs<TInput, TInput, NUdf::TDataType<ui32>, NUdf::TDataType<ui32>, false, false, false>, TTernaryWrap<false>>(registry, name);
  55. RegisterFunctionImpl<TSubString<false, false>, TTernaryArgs<TInput, TInput, NUdf::TDataType<ui32>, NUdf::TDataType<ui32>, true, false, false>, TTernaryWrap<true>>(registry, name);
  56. RegisterFunctionImpl<TSubString<true, false>, TTernaryArgs<TInput, TInput, NUdf::TDataType<ui32>, NUdf::TDataType<ui32>, false, true, false>, TTernaryWrap<false>>(registry, name);
  57. RegisterFunctionImpl<TSubString<true, false>, TTernaryArgs<TInput, TInput, NUdf::TDataType<ui32>, NUdf::TDataType<ui32>, true, true, false>, TTernaryWrap<true>>(registry, name);
  58. RegisterFunctionImpl<TSubString<false, true>, TTernaryArgs<TInput, TInput, NUdf::TDataType<ui32>, NUdf::TDataType<ui32>, false, false, true>, TTernaryWrap<false>>(registry, name);
  59. RegisterFunctionImpl<TSubString<false, true>, TTernaryArgs<TInput, TInput, NUdf::TDataType<ui32>, NUdf::TDataType<ui32>, true, false, true>, TTernaryWrap<true>>(registry, name);
  60. RegisterFunctionImpl<TSubString<true, true>, TTernaryArgs<TInput, TInput, NUdf::TDataType<ui32>, NUdf::TDataType<ui32>, false, true, true>, TTernaryWrap<false>>(registry, name);
  61. RegisterFunctionImpl<TSubString<true, true>, TTernaryArgs<TInput, TInput, NUdf::TDataType<ui32>, NUdf::TDataType<ui32>, true, true, true>, TTernaryWrap<true>>(registry, name);
  62. }
  63. }
  64. void RegisterSubstring(IBuiltinFunctionRegistry& registry) {
  65. RegisterSubstringnOpt<NUdf::TDataType<char*>>(registry, "Substring");
  66. RegisterSubstringnOpt<NUdf::TDataType<NUdf::TUtf8>>(registry, "Substring");
  67. }
  68. } // namespace NMiniKQL
  69. } // namespace NKikimr