Substring_index
| 359 | |
| 360 | // Substring_index |
| 361 | GDV_FORCE_INLINE |
| 362 | const char* gdv_fn_substring_index(int64_t context, const char* txt, int32_t txt_len, |
| 363 | const char* pat, int32_t pat_len, int32_t cnt, |
| 364 | int32_t* out_len) { |
| 365 | if (txt_len == 0 || pat_len == 0 || cnt == 0) { |
| 366 | *out_len = 0; |
| 367 | return ""; |
| 368 | } |
| 369 | |
| 370 | char* out = reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, txt_len)); |
| 371 | if (out == nullptr) { |
| 372 | gdv_fn_context_set_error_msg(context, "Could not allocate memory for output string"); |
| 373 | *out_len = 0; |
| 374 | return ""; |
| 375 | } |
| 376 | |
| 377 | std::vector<int> lps(pat_len); |
| 378 | int len = 0; |
| 379 | |
| 380 | lps[0] = 0; // lps[0] is always 0 |
| 381 | |
| 382 | // the loop calculates lps[i] for i = 1 to M-1 |
| 383 | int i = 1; |
| 384 | while (i < pat_len) { |
| 385 | if (pat[i] == pat[len]) { |
| 386 | len++; |
| 387 | lps[i] = len; |
| 388 | i++; |
| 389 | } else { |
| 390 | // (pat[i] != pat[len]) |
| 391 | // This is tricky. Consider the example. |
| 392 | // AAACAAAA and i = 7. The idea is similar |
| 393 | // to search step. |
| 394 | if (len != 0) { |
| 395 | len = lps[len - 1]; |
| 396 | |
| 397 | // Also, note that we do not increment |
| 398 | // i here |
| 399 | } else { |
| 400 | // if (len == 0) |
| 401 | lps[i] = 0; |
| 402 | i++; |
| 403 | } |
| 404 | } |
| 405 | } |
| 406 | |
| 407 | std::vector<int> occ; |
| 408 | |
| 409 | i = 0; // index for txt[] |
| 410 | int j = 0; // index for pat[] |
| 411 | while (i < txt_len) { |
| 412 | if (pat[j] == txt[i]) { |
| 413 | j++; |
| 414 | i++; |
| 415 | } |
| 416 | |
| 417 | if (j == pat_len) { |
| 418 | occ.push_back(i - j); |