Evaluate a multi-argument scalar function into func_buf (or a direct value). */
| 3239 | |
| 3240 | /* Evaluate a multi-argument scalar function into func_buf (or a direct value). */ |
| 3241 | static const char *eval_multiarg_func(binding_t *b, const cbm_return_item_t *item, char *buf, |
| 3242 | size_t bufsz) { |
| 3243 | const char *f = item->func; |
| 3244 | int n = item->arg_count; |
| 3245 | if (strcmp(f, "coalesce") == 0) { |
| 3246 | for (int i = 0; i < n; i++) { |
| 3247 | const char *v = eval_func_arg(b, &item->args[i]); |
| 3248 | if (v && v[0]) { |
| 3249 | return v; |
| 3250 | } |
| 3251 | } |
| 3252 | return ""; |
| 3253 | } |
| 3254 | if (strcmp(f, "substring") == 0 && n >= 2) { |
| 3255 | const char *s = eval_func_arg(b, &item->args[0]); |
| 3256 | long start = strtol(eval_func_arg(b, &item->args[1]), NULL, CBM_DECIMAL_BASE); |
| 3257 | size_t slen = strlen(s); |
| 3258 | if (start < 0 || (size_t)start >= slen) { |
| 3259 | return ""; |
| 3260 | } |
| 3261 | size_t take = slen - (size_t)start; |
| 3262 | if (n >= 3) { |
| 3263 | long len = strtol(eval_func_arg(b, &item->args[2]), NULL, CBM_DECIMAL_BASE); |
| 3264 | if (len < 0) { |
| 3265 | len = 0; |
| 3266 | } |
| 3267 | if ((size_t)len < take) { |
| 3268 | take = (size_t)len; |
| 3269 | } |
| 3270 | } |
| 3271 | if (take >= bufsz) { |
| 3272 | take = bufsz - SKIP_ONE; |
| 3273 | } |
| 3274 | memcpy(buf, s + start, take); |
| 3275 | buf[take] = '\0'; |
| 3276 | return buf; |
| 3277 | } |
| 3278 | if ((strcmp(f, "left") == 0 || strcmp(f, "right") == 0) && n >= 2) { |
| 3279 | const char *s = eval_func_arg(b, &item->args[0]); |
| 3280 | long k = strtol(eval_func_arg(b, &item->args[1]), NULL, CBM_DECIMAL_BASE); |
| 3281 | if (k < 0) { |
| 3282 | k = 0; |
| 3283 | } |
| 3284 | size_t slen = strlen(s); |
| 3285 | size_t take = (size_t)k < slen ? (size_t)k : slen; |
| 3286 | if (take >= bufsz) { |
| 3287 | take = bufsz - SKIP_ONE; |
| 3288 | } |
| 3289 | memcpy(buf, (strcmp(f, "left") == 0) ? s : s + (slen - take), take); |
| 3290 | buf[take] = '\0'; |
| 3291 | return buf; |
| 3292 | } |
| 3293 | if (strcmp(f, "replace") == 0 && n >= 3) { |
| 3294 | const char *s = eval_func_arg(b, &item->args[0]); |
| 3295 | const char *from = eval_func_arg(b, &item->args[1]); |
| 3296 | const char *to = eval_func_arg(b, &item->args[2]); |
| 3297 | size_t fromlen = strlen(from); |
| 3298 | size_t tolen = strlen(to); |
no test coverage detected