Evaluate a comparison operator between actual and expected strings. */
| 2575 | |
| 2576 | /* Evaluate a comparison operator between actual and expected strings. */ |
| 2577 | static bool eval_comparison_op(const char *op, const char *actual, const char *expected) { |
| 2578 | if (strcmp(op, "=") == 0) { |
| 2579 | return strcmp(actual, expected) == 0; |
| 2580 | } |
| 2581 | if (strcmp(op, "<>") == 0) { |
| 2582 | return strcmp(actual, expected) != 0; |
| 2583 | } |
| 2584 | if (strcmp(op, "=~") == 0) { |
| 2585 | cbm_regex_t re; |
| 2586 | if (cbm_regcomp(&re, expected, CBM_REG_EXTENDED | CBM_REG_NOSUB) != 0) { |
| 2587 | return false; |
| 2588 | } |
| 2589 | int rc = cbm_regexec(&re, actual, 0, NULL, 0); |
| 2590 | cbm_regfree(&re); |
| 2591 | return rc == 0; |
| 2592 | } |
| 2593 | if (strcmp(op, "CONTAINS") == 0) { |
| 2594 | return strstr(actual, expected) != NULL; |
| 2595 | } |
| 2596 | if (strcmp(op, "STARTS WITH") == 0) { |
| 2597 | return strncmp(actual, expected, strlen(expected)) == 0; |
| 2598 | } |
| 2599 | if (strcmp(op, "ENDS WITH") == 0) { |
| 2600 | size_t alen = strlen(actual); |
| 2601 | size_t elen = strlen(expected); |
| 2602 | return alen >= elen && strcmp(actual + alen - elen, expected) == 0; |
| 2603 | } |
| 2604 | if (strcmp(op, ">") == 0 || strcmp(op, "<") == 0 || strcmp(op, ">=") == 0 || |
| 2605 | strcmp(op, "<=") == 0) { |
| 2606 | double a = strtod(actual, NULL); |
| 2607 | double exp_val = strtod(expected, NULL); |
| 2608 | if (op[0] == '>' && op[CYP_CHAR_IDX1] == '=') { |
| 2609 | return a >= exp_val; |
| 2610 | } |
| 2611 | if (op[0] == '<' && op[CYP_CHAR_IDX1] == '=') { |
| 2612 | return a <= exp_val; |
| 2613 | } |
| 2614 | if (op[0] == '>') { |
| 2615 | return a > exp_val; |
| 2616 | } |
| 2617 | return a < exp_val; |
| 2618 | } |
| 2619 | return false; |
| 2620 | } |
| 2621 | |
| 2622 | /* Evaluate a WHERE condition against a binding */ |
| 2623 | static bool eval_condition(const cbm_condition_t *c, binding_t *b) { |
no test coverage detected