Evaluate a multi-argument scalar function into func_buf (or a direct value). */
| 3571 | |
| 3572 | /* Evaluate a multi-argument scalar function into func_buf (or a direct value). */ |
| 3573 | static const char *eval_multiarg_func(binding_t *b, const cbm_return_item_t *item, char *buf, |
| 3574 | size_t bufsz) { |
| 3575 | const char *f = item->func; |
| 3576 | int n = item->arg_count; |
| 3577 | if (strcmp(f, "coalesce") == 0) { |
| 3578 | for (int i = 0; i < n; i++) { |
| 3579 | const char *v = eval_func_arg(b, &item->args[i]); |
| 3580 | if (v && v[0]) { |
| 3581 | return v; |
| 3582 | } |
| 3583 | } |
| 3584 | return ""; |
| 3585 | } |
| 3586 | if (strcmp(f, "substring") == 0 && n >= 2) { |
| 3587 | const char *s = eval_func_arg(b, &item->args[0]); |
| 3588 | long start = strtol(eval_func_arg(b, &item->args[1]), NULL, CBM_DECIMAL_BASE); |
| 3589 | size_t slen = strlen(s); |
| 3590 | if (start < 0 || (size_t)start >= slen) { |
| 3591 | return ""; |
| 3592 | } |
| 3593 | size_t take = slen - (size_t)start; |
| 3594 | if (n >= 3) { |
| 3595 | long len = strtol(eval_func_arg(b, &item->args[2]), NULL, CBM_DECIMAL_BASE); |
| 3596 | if (len < 0) { |
| 3597 | len = 0; |
| 3598 | } |
| 3599 | if ((size_t)len < take) { |
| 3600 | take = (size_t)len; |
| 3601 | } |
| 3602 | } |
| 3603 | if (take >= bufsz) { |
| 3604 | take = bufsz - SKIP_ONE; |
| 3605 | } |
| 3606 | memcpy(buf, s + start, take); |
| 3607 | buf[take] = '\0'; |
| 3608 | return buf; |
| 3609 | } |
| 3610 | if ((strcmp(f, "left") == 0 || strcmp(f, "right") == 0) && n >= 2) { |
| 3611 | const char *s = eval_func_arg(b, &item->args[0]); |
| 3612 | long k = strtol(eval_func_arg(b, &item->args[1]), NULL, CBM_DECIMAL_BASE); |
| 3613 | if (k < 0) { |
| 3614 | k = 0; |
| 3615 | } |
| 3616 | size_t slen = strlen(s); |
| 3617 | size_t take = (size_t)k < slen ? (size_t)k : slen; |
| 3618 | if (take >= bufsz) { |
| 3619 | take = bufsz - SKIP_ONE; |
| 3620 | } |
| 3621 | memcpy(buf, (strcmp(f, "left") == 0) ? s : s + (slen - take), take); |
| 3622 | buf[take] = '\0'; |
| 3623 | return buf; |
| 3624 | } |
| 3625 | if (strcmp(f, "replace") == 0 && n >= 3) { |
| 3626 | const char *s = eval_func_arg(b, &item->args[0]); |
| 3627 | const char *from = eval_func_arg(b, &item->args[1]); |
| 3628 | const char *to = eval_func_arg(b, &item->args[2]); |
| 3629 | size_t fromlen = strlen(from); |
| 3630 | size_t tolen = strlen(to); |
no test coverage detected