| 2904 | /* ── String function application ──────────────────────────────── */ |
| 2905 | |
| 2906 | static const char *apply_string_func(const char *func, const char *val, char *buf, size_t buf_sz) { |
| 2907 | if (!func || !val) { |
| 2908 | return val ? val : ""; |
| 2909 | } |
| 2910 | if (strcmp(func, "toLower") == 0) { |
| 2911 | size_t i = 0; |
| 2912 | for (; i < buf_sz - SKIP_ONE && val[i]; i++) { |
| 2913 | buf[i] = (char)tolower((unsigned char)val[i]); |
| 2914 | } |
| 2915 | buf[i] = '\0'; |
| 2916 | return buf; |
| 2917 | } |
| 2918 | if (strcmp(func, "toUpper") == 0) { |
| 2919 | size_t i = 0; |
| 2920 | for (; i < buf_sz - SKIP_ONE && val[i]; i++) { |
| 2921 | buf[i] = (char)toupper((unsigned char)val[i]); |
| 2922 | } |
| 2923 | buf[i] = '\0'; |
| 2924 | return buf; |
| 2925 | } |
| 2926 | if (strcmp(func, "toString") == 0) { |
| 2927 | return val; /* already strings */ |
| 2928 | } |
| 2929 | if (strcmp(func, "toInteger") == 0) { |
| 2930 | char *end = NULL; |
| 2931 | long long v = strtoll(val, &end, CBM_DECIMAL_BASE); |
| 2932 | if (end == val) { |
| 2933 | /* Not an integer literal — accept a float string and truncate. */ |
| 2934 | char *fend = NULL; |
| 2935 | double d = strtod(val, &fend); |
| 2936 | if (fend == val) { |
| 2937 | return ""; /* non-numeric → null */ |
| 2938 | } |
| 2939 | v = (long long)d; |
| 2940 | } |
| 2941 | snprintf(buf, buf_sz, "%lld", v); |
| 2942 | return buf; |
| 2943 | } |
| 2944 | if (strcmp(func, "toFloat") == 0) { |
| 2945 | char *end = NULL; |
| 2946 | double d = strtod(val, &end); |
| 2947 | if (end == val) { |
| 2948 | return ""; /* non-numeric → null */ |
| 2949 | } |
| 2950 | snprintf(buf, buf_sz, "%g", d); |
| 2951 | return buf; |
| 2952 | } |
| 2953 | if (strcmp(func, "toBoolean") == 0) { |
| 2954 | if (cyp_ci_eq(val, "true")) { |
| 2955 | return "true"; |
| 2956 | } |
| 2957 | if (cyp_ci_eq(val, "false")) { |
| 2958 | return "false"; |
| 2959 | } |
| 2960 | return ""; /* not a boolean → null */ |
| 2961 | } |
| 2962 | if (strcmp(func, "size") == 0 || strcmp(func, "length") == 0) { |
| 2963 | snprintf(buf, buf_sz, "%zu", strlen(val)); |
no test coverage detected