X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Fecoli_strvec.c;h=c574b1b63764ea5e79a40198905e3cd17ba484b0;hb=15718f19cbf3868bf6fba79f4e26b5254c57873e;hp=b35c56926c545c0337d87f1729c916812908de14;hpb=7cbb8a1000b85db2a487afd4d17e688b8c0aa756;p=protos%2Flibecoli.git diff --git a/lib/ecoli_strvec.c b/lib/ecoli_strvec.c index b35c569..c574b1b 100644 --- a/lib/ecoli_strvec.c +++ b/lib/ecoli_strvec.c @@ -1,7 +1,8 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright (c) 2016, Olivier MATZ + * Copyright 2016, Olivier MATZ */ +#define _GNU_SOURCE /* qsort_r */ #include #include #include @@ -42,18 +43,18 @@ int ec_strvec_add(struct ec_strvec *strvec, const char *s) new_vec = ec_realloc(strvec->vec, sizeof(*strvec->vec) * (strvec->len + 1)); if (new_vec == NULL) - return -ENOMEM; + return -1; strvec->vec = new_vec; elt = ec_malloc(sizeof(*elt)); if (elt == NULL) - return -ENOMEM; + return -1; elt->str = ec_strdup(s); if (elt->str == NULL) { ec_free(elt); - return -ENOMEM; + return -1; } elt->refcnt = 1; @@ -69,6 +70,9 @@ struct ec_strvec *ec_strvec_from_array(const char * const *strarr, size_t i; strvec = ec_strvec(); + if (strvec == NULL) + goto fail; + for (i = 0; i < n; i++) { if (ec_strvec_add(strvec, strarr[i]) < 0) goto fail; @@ -190,6 +194,24 @@ int ec_strvec_cmp(const struct ec_strvec *strvec1, return 0; } +static int +cmp_vec_elt(const void *p1, const void *p2, void *arg) +{ + int (*str_cmp)(const char *s1, const char *s2) = arg; + const struct ec_strvec_elt * const *e1 = p1, * const *e2 = p2; + + return str_cmp((*e1)->str, (*e2)->str); +} + +void ec_strvec_sort(struct ec_strvec *strvec, + int (*str_cmp)(const char *s1, const char *s2)) +{ + if (str_cmp == NULL) + str_cmp = strcmp; + qsort_r(strvec->vec, ec_strvec_len(strvec), + sizeof(*strvec->vec), cmp_vec_elt, str_cmp); +} + void ec_strvec_dump(FILE *out, const struct ec_strvec *strvec) { size_t i; @@ -215,6 +237,10 @@ static int ec_strvec_testcase(void) { struct ec_strvec *strvec = NULL; struct ec_strvec *strvec2 = NULL; + FILE *f = NULL; + char *buf = NULL; + size_t buflen = 0; + int testres = 0; strvec = ec_strvec(); if (strvec == NULL) { @@ -318,16 +344,77 @@ static int ec_strvec_testcase(void) } ec_strvec_free(strvec2); - ec_strvec_dump(stdout, strvec); - ec_strvec_dump(stdout, NULL); + strvec2 = EC_STRVEC("0", "1"); + if (strvec2 == NULL) { + EC_TEST_ERR("cannot create strvec from array\n"); + goto fail; + } + testres |= EC_TEST_CHECK(ec_strvec_cmp(strvec, strvec2) == 0, + "strvec and strvec2 should be equal\n"); + ec_strvec_free(strvec2); + + f = open_memstream(&buf, &buflen); + if (f == NULL) + goto fail; + ec_strvec_dump(f, strvec); + fclose(f); + f = NULL; + testres |= EC_TEST_CHECK( + strstr(buf, "strvec (len=2) [0, 1]"), "bad dump\n"); + free(buf); + buf = NULL; + + ec_strvec_del_last(strvec); + strvec2 = EC_STRVEC("0"); + if (strvec2 == NULL) { + EC_TEST_ERR("cannot create strvec from array\n"); + goto fail; + } + testres |= EC_TEST_CHECK(ec_strvec_cmp(strvec, strvec2) == 0, + "strvec and strvec2 should be equal\n"); + ec_strvec_free(strvec2); + strvec2 = NULL; + + f = open_memstream(&buf, &buflen); + if (f == NULL) + goto fail; + ec_strvec_dump(f, NULL); + fclose(f); + f = NULL; + testres |= EC_TEST_CHECK( + strstr(buf, "none"), "bad dump\n"); + free(buf); + buf = NULL; ec_strvec_free(strvec); - return 0; + strvec = EC_STRVEC("e", "a", "f", "d", "b", "c"); + if (strvec == NULL) { + EC_TEST_ERR("cannot create strvec from array\n"); + goto fail; + } + ec_strvec_sort(strvec, NULL); + strvec2 = EC_STRVEC("a", "b", "c", "d", "e", "f"); + if (strvec2 == NULL) { + EC_TEST_ERR("cannot create strvec from array\n"); + goto fail; + } + testres |= EC_TEST_CHECK(ec_strvec_cmp(strvec, strvec2) == 0, + "strvec and strvec2 should be equal\n"); + ec_strvec_free(strvec); + strvec = NULL; + ec_strvec_free(strvec2); + strvec2 = NULL; + + return testres; fail: + if (f != NULL) + fclose(f); ec_strvec_free(strvec); ec_strvec_free(strvec2); + free(buf); + return -1; } /* LCOV_EXCL_STOP */