Use case-insensitive variant of `strcmp`.
parent
6f77c400e9
commit
0fc476ceed
|
@ -5,9 +5,7 @@ CLI utility for defining custom project initialization scripts.
|
|||
TODO:
|
||||
- [ ] Add evaluator tests.
|
||||
- [ ] Color output to console.
|
||||
- [ ] string -> line, case insensitive
|
||||
- [ ] Ensure keys are alphanumeric, underscore
|
||||
- [ ] sophie
|
||||
|
||||
## Overview
|
||||
|
||||
|
|
|
@ -23,4 +23,23 @@ This function assumes a forward slash path separator (i.e. `/`).
|
|||
*/
|
||||
char *join(size_t n, const char *segments[static n], char sep);
|
||||
|
||||
/**
|
||||
@brief Perform case insensitive string comparison.
|
||||
|
||||
This function operates like `strcmp` except comparison ignores case.
|
||||
|
||||
@param s1
|
||||
C string to be compared.
|
||||
@param s2
|
||||
C string to be compared.
|
||||
@return
|
||||
An integral value indicating the relationship between the strings:
|
||||
- `< 0`: the first character (converted uppercase) that does not match has a
|
||||
lower value in @p s1 than in @p s2.
|
||||
- `= 0`: the contents of both strings are equal.
|
||||
- `> 0`: the first character (converted uppercase) that does not match has a
|
||||
greater value in @p s1 than in @p s2.
|
||||
*/
|
||||
int strcmp_ci(const char *s1, const char *s2);
|
||||
|
||||
#endif /* _BOOTSTRAP_STRING_UTILS_H */
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "string_utils.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
char *join(size_t n, const char *segments[static n], char sep) {
|
||||
|
@ -26,3 +28,20 @@ char *join(size_t n, const char *segments[static n], char sep) {
|
|||
|
||||
return joined;
|
||||
}
|
||||
|
||||
int strcmp_ci(const char *s1, const char *s2) {
|
||||
int i = 0;
|
||||
size_t s1_len = strlen(s1);
|
||||
size_t s2_len = strlen(s2);
|
||||
for (; i < (s1_len < s2_len ? s1_len : s2_len); ++i) {
|
||||
if (toupper(s1[i]) < toupper(s2[i])) {
|
||||
return -1;
|
||||
} else if (toupper(s1[i]) > toupper(s2[i])) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (s1_len == s2_len) {
|
||||
return 0;
|
||||
}
|
||||
return s1_len < s2_len ? -1 : 1;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "validator.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "string_utils.h"
|
||||
|
||||
static struct Error *read_field(const cJSON *const field, struct Field **out) {
|
||||
if (!cJSON_IsObject(field)) {
|
||||
|
@ -27,7 +27,7 @@ static struct Error *read_field(const cJSON *const field, struct Field **out) {
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
if (strcmp(type->valuestring, "STRING") == 0) {
|
||||
if (strcmp_ci(type->valuestring, "text") == 0) {
|
||||
(*out)->type = FT_TEXT;
|
||||
} else {
|
||||
error = ERROR_NEW(
|
||||
|
|
|
@ -26,6 +26,7 @@ int main(int argc, char *argv[]) {
|
|||
sput_enter_suite("string_utils");
|
||||
sput_run_test(test_join_single);
|
||||
sput_run_test(test_join_multiple);
|
||||
sput_run_test(test_strcmp_ci);
|
||||
|
||||
sput_enter_suite("parser");
|
||||
sput_run_test(test_parser_missing);
|
||||
|
@ -37,6 +38,7 @@ int main(int argc, char *argv[]) {
|
|||
sput_run_test(test_validator_field_not_object);
|
||||
sput_run_test(test_validator_field_type_invalid);
|
||||
sput_run_test(test_validator_field_type_unknown);
|
||||
sput_run_test(test_validator_valid_type_ci);
|
||||
sput_run_test(test_validator_field_prompt_invalid);
|
||||
sput_run_test(test_validator_valid);
|
||||
|
||||
|
|
|
@ -18,4 +18,14 @@ static void test_join_multiple() {
|
|||
free(joined);
|
||||
}
|
||||
|
||||
static void test_strcmp_ci() {
|
||||
const char *a1 = "aBcD";
|
||||
const char *a2 = "AbCd";
|
||||
sput_fail_unless(strcmp_ci(a1, a2) == 0, "strcmp_ci == 0");
|
||||
const char *b1 = "aBcDe";
|
||||
const char *b2 = "AbCd";
|
||||
sput_fail_unless(strcmp_ci(b1, b2) > 0, "strcmp_ci > 0");
|
||||
sput_fail_unless(strcmp_ci(b2, b1) < 0, "strcmp_ci < 0");
|
||||
}
|
||||
|
||||
#endif /* _BOOTSTRAP_TEST_STRING_UTILS */
|
||||
|
|
|
@ -88,11 +88,27 @@ static void test_validator_field_type_unknown() {
|
|||
test_validator_teardown(fixture);
|
||||
}
|
||||
|
||||
static void test_validator_valid_type_ci() {
|
||||
struct TestValidatorFixture *fixture = test_validator_setup(
|
||||
"{"
|
||||
" \"key\": {"
|
||||
" \"type\": \"tExT\","
|
||||
" \"prompt\": \"What value for key?\""
|
||||
" }"
|
||||
"}"
|
||||
);
|
||||
|
||||
struct Error *error = validate_spec_json(fixture->parsed, &fixture->prompts);
|
||||
sput_fail_unless(error == 0, "valid");
|
||||
|
||||
test_validator_teardown(fixture);
|
||||
}
|
||||
|
||||
static void test_validator_field_prompt_invalid() {
|
||||
struct TestValidatorFixture *fixture = test_validator_setup(
|
||||
"{"
|
||||
" \"key\": {"
|
||||
" \"type\": \"STRING\","
|
||||
" \"type\": \"text\","
|
||||
" \"prompt\": 2"
|
||||
" }"
|
||||
"}"
|
||||
|
@ -111,7 +127,7 @@ static void test_validator_valid() {
|
|||
struct TestValidatorFixture *fixture = test_validator_setup(
|
||||
"{"
|
||||
" \"key\": {"
|
||||
" \"type\": \"STRING\","
|
||||
" \"type\": \"text\","
|
||||
" \"prompt\": \"What value for key?\""
|
||||
" }"
|
||||
"}"
|
||||
|
|
Loading…
Reference in New Issue