From: Olivier Matz Date: Thu, 13 Dec 2018 18:49:55 +0000 (+0100) Subject: add attrs to strvec X-Git-Url: http://git.droids-corp.org/?p=protos%2Flibecoli.git;a=commitdiff_plain;h=cb86533e80f5b2556ab66a78e4d980221f9f94bf add attrs to strvec --- diff --git a/libecoli/ecoli_strvec.c b/libecoli/ecoli_strvec.c index c574b1b..98a952f 100644 --- a/libecoli/ecoli_strvec.c +++ b/libecoli/ecoli_strvec.c @@ -11,6 +11,7 @@ #include #include #include +#include #include EC_LOG_TYPE_REGISTER(strvec); @@ -18,6 +19,7 @@ EC_LOG_TYPE_REGISTER(strvec); struct ec_strvec_elt { unsigned int refcnt; char *str; + struct ec_keyval *attrs; }; struct ec_strvec { @@ -36,10 +38,64 @@ struct ec_strvec *ec_strvec(void) return strvec; } +static struct ec_strvec_elt * +__ec_strvec_elt(const char *s) +{ + struct ec_strvec_elt *elt; + + elt = ec_calloc(1, sizeof(*elt)); + if (elt == NULL) + return NULL; + + elt->str = ec_strdup(s); + if (elt->str == NULL) { + ec_free(elt); + return NULL; + } + elt->refcnt = 1; + + return elt; +} + +static void +__ec_strvec_elt_free(struct ec_strvec_elt *elt) +{ + elt->refcnt--; + if (elt->refcnt == 0) { + ec_free(elt->str); + ec_keyval_free(elt->attrs); + ec_free(elt); + } +} + +int ec_strvec_set(struct ec_strvec *strvec, size_t idx, const char *s) +{ + struct ec_strvec_elt *elt; + + if (strvec == NULL || s == NULL || idx >= strvec->len) { + errno = EINVAL; + return -1; + } + + elt = __ec_strvec_elt(s); + if (elt == NULL) + return -1; + + __ec_strvec_elt_free(strvec->vec[idx]); + strvec->vec[idx] = elt; + + return 0; +} + int ec_strvec_add(struct ec_strvec *strvec, const char *s) { struct ec_strvec_elt *elt, **new_vec; + if (strvec == NULL || s == NULL) { + errno = EINVAL; + return -1; + } + new_vec = ec_realloc(strvec->vec, sizeof(*strvec->vec) * (strvec->len + 1)); if (new_vec == NULL) @@ -47,19 +103,13 @@ int ec_strvec_add(struct ec_strvec *strvec, const char *s) strvec->vec = new_vec; - elt = ec_malloc(sizeof(*elt)); + elt = __ec_strvec_elt(s); if (elt == NULL) return -1; - elt->str = ec_strdup(s); - if (elt->str == NULL) { - ec_free(elt); - return -1; - } - elt->refcnt = 1; - new_vec[strvec->len] = elt; strvec->len++; + return 0; } @@ -87,20 +137,14 @@ fail: int ec_strvec_del_last(struct ec_strvec *strvec) { - struct ec_strvec_elt *elt; - if (strvec->len == 0) { errno = EINVAL; return -1; } - elt = strvec->vec[strvec->len - 1]; - elt->refcnt--; - if (elt->refcnt == 0) { - ec_free(elt->str); - ec_free(elt); - } + __ec_strvec_elt_free(strvec->vec[strvec->len - 1]); strvec->len--; + return 0; } @@ -153,11 +197,7 @@ void ec_strvec_free(struct ec_strvec *strvec) for (i = 0; i < ec_strvec_len(strvec); i++) { elt = strvec->vec[i]; - elt->refcnt--; - if (elt->refcnt == 0) { - ec_free(elt->str); - ec_free(elt); - } + __ec_strvec_elt_free(elt); } ec_free(strvec->vec); @@ -177,6 +217,46 @@ const char *ec_strvec_val(const struct ec_strvec *strvec, size_t idx) return strvec->vec[idx]->str; } +const struct ec_keyval *ec_strvec_get_attrs(const struct ec_strvec *strvec, + size_t idx) +{ + if (strvec == NULL || idx >= strvec->len) { + errno = EINVAL; + return NULL; + } + + return strvec->vec[idx]->attrs; +} + +int ec_strvec_set_attrs(struct ec_strvec *strvec, size_t idx, + struct ec_keyval *attrs) +{ + struct ec_strvec_elt *elt; + + if (strvec == NULL || idx >= strvec->len) { + errno = EINVAL; + goto fail; + } + + elt = strvec->vec[idx]; + if (elt->refcnt > 1) { + if (ec_strvec_set(strvec, idx, elt->str) < 0) + goto fail; + elt = strvec->vec[idx]; + } + + if (elt->attrs != NULL) + ec_keyval_free(elt->attrs); + + elt->attrs = attrs; + + return 0; + +fail: + ec_keyval_free(attrs); + return -1; +} + int ec_strvec_cmp(const struct ec_strvec *strvec1, const struct ec_strvec *strvec2) { @@ -237,6 +317,8 @@ static int ec_strvec_testcase(void) { struct ec_strvec *strvec = NULL; struct ec_strvec *strvec2 = NULL; + const struct ec_keyval *const_attrs = NULL; + struct ec_keyval *attrs = NULL; FILE *f = NULL; char *buf = NULL; size_t buflen = 0; @@ -393,7 +475,33 @@ static int ec_strvec_testcase(void) EC_TEST_ERR("cannot create strvec from array\n"); goto fail; } + attrs = ec_keyval(); + if (attrs == NULL) { + EC_TEST_ERR("cannot create attrs\n"); + goto fail; + } + if (ec_keyval_set(attrs, "key", "value", NULL) < 0) { + EC_TEST_ERR("cannot set attr\n"); + goto fail; + } + if (ec_strvec_set_attrs(strvec, 1, attrs) < 0) { + attrs = NULL; + EC_TEST_ERR("cannot set attrs in strvec\n"); + goto fail; + } + attrs = NULL; + ec_strvec_sort(strvec, NULL); + + /* attrs are now at index 0 after sorting */ + const_attrs = ec_strvec_get_attrs(strvec, 0); + if (const_attrs == NULL) { + EC_TEST_ERR("cannot get attrs\n"); + goto fail; + } + testres |= EC_TEST_CHECK( + ec_keyval_has_key(const_attrs, "key"), "cannot get attrs key\n"); + strvec2 = EC_STRVEC("a", "b", "c", "d", "e", "f"); if (strvec2 == NULL) { EC_TEST_ERR("cannot create strvec from array\n"); @@ -411,6 +519,7 @@ static int ec_strvec_testcase(void) fail: if (f != NULL) fclose(f); + ec_keyval_free(attrs); ec_strvec_free(strvec); ec_strvec_free(strvec2); free(buf); diff --git a/libecoli/ecoli_strvec.h b/libecoli/ecoli_strvec.h index 8e14973..cabe6b2 100644 --- a/libecoli/ecoli_strvec.h +++ b/libecoli/ecoli_strvec.h @@ -57,6 +57,20 @@ struct ec_strvec *ec_strvec(void); struct ec_strvec *ec_strvec_from_array(const char * const *strarr, size_t n); +/** + * Set a string in the vector at specified index. + * + * @param strvec + * The pointer to the string vector. + * @param idx + * The index of the string to set. + * @param s + * The string to be set. + * @return + * 0 on success or -1 on error (errno is set). + */ +int ec_strvec_set(struct ec_strvec *strvec, size_t idx, const char *s); + /** * Add a string in a vector. * @@ -84,6 +98,8 @@ int ec_strvec_del_last(struct ec_strvec *strvec); /** * Duplicate a string vector. * + * Attributes are duplicated if any. + * * @param strvec * The pointer to the string vector. * @return @@ -94,6 +110,8 @@ struct ec_strvec *ec_strvec_dup(const struct ec_strvec *strvec); /** * Duplicate a part of a string vector. * + * Attributes are duplicated if any. + * * @param strvec * The pointer to the string vector. * @param off @@ -137,6 +155,36 @@ size_t ec_strvec_len(const struct ec_strvec *strvec); */ const char *ec_strvec_val(const struct ec_strvec *strvec, size_t idx); +/** + * Get the attributes of a vector element. + * + * @param strvec + * The pointer to the string vector. + * @param idx + * The index of the string to get. + * @return + * The read-only attributes (dictionnary) of the string at specified + * index, or NULL if there is no attribute. + */ +const struct ec_keyval *ec_strvec_get_attrs(const struct ec_strvec *strvec, + size_t idx); + +/** + * Set the attributes of a vector element. + * + * @param strvec + * The pointer to the string vector. + * @param idx + * The index of the string to get. + * @param attrs + * The attributes to be set. + * @return + * 0 on success, -1 on error (errno is set). On error, attrs + * are freed and must not be used by the caller. + */ +int ec_strvec_set_attrs(struct ec_strvec *strvec, size_t idx, + struct ec_keyval *attrs); + /** * Compare two string vectors * @@ -153,6 +201,8 @@ int ec_strvec_cmp(const struct ec_strvec *strvec1, /** * Sort the string vector. * + * Attributes are not compared. + * * @param strvec * The pointer to the first string vector. * @param str_cmp