/** * Copyright (C) Mellanox Technologies Ltd. 2019. ALL RIGHTS RESERVED. * * See file LICENSE for terms. */ #include "string_set.h" #include #include #include #define UCS_STRING_SET_ALLOC_NAME "string_set" void ucs_string_set_init(ucs_string_set_t *sset) { kh_init_inplace(ucs_string_set, sset); } void ucs_string_set_cleanup(ucs_string_set_t *sset) { char *str; kh_foreach_key(sset, str, { ucs_free(str); }); kh_destroy_inplace(ucs_string_set, sset); } /* Adds string by pointer, and releases the string if add fails or the string * already exists in the set */ static ucs_status_t ucs_string_set_add_ptr(ucs_string_set_t *sset, char *str) { int ret; kh_put(ucs_string_set, sset, str, &ret); switch (ret) { case -1: ucs_free(str); return UCS_ERR_NO_MEMORY; case 0: /* key already present */ ucs_free(str); return UCS_OK; case 1: case 2: /* key inserted */ return UCS_OK; default: ucs_error("unexpected return value from kh_put(ucs_string_set): %d", ret); return UCS_ERR_INVALID_PARAM; } } ucs_status_t ucs_string_set_add(ucs_string_set_t *sset, const char *str) { char *str_copy; str_copy = ucs_strdup(str, UCS_STRING_SET_ALLOC_NAME); if (str_copy == NULL) { return UCS_ERR_NO_MEMORY; } return ucs_string_set_add_ptr(sset, str_copy); } ucs_status_t ucs_string_set_addf(ucs_string_set_t *sset, const char *fmt, ...) { int length; va_list ap; char *str; va_start(ap, fmt); length = vsnprintf(NULL, 0, fmt, ap); va_end(ap); str = ucs_malloc(length + 1, UCS_STRING_SET_ALLOC_NAME); if (str == NULL) { return UCS_ERR_NO_MEMORY; } va_start(ap, fmt); vsnprintf(str, length + 1, fmt, ap); va_end(ap); return ucs_string_set_add_ptr(sset, str); } int ucs_string_set_contains(const ucs_string_set_t *sset, const char *str) { return kh_get(ucs_string_set, sset, (char*)str) != kh_end(sset); } static int ucs_string_set_compare_func(const void *a, const void *b) { return strcmp(*(const char**)a, *(const char**)b); } ucs_status_t ucs_string_set_print_sorted(const ucs_string_set_t *sset, ucs_string_buffer_t *strb, const char *sep) { const char **sorted_strings; ucs_status_t status; size_t index, count; char *str; /* allocate a temporary array to hold the sorted strings */ count = kh_size(sset); sorted_strings = ucs_calloc(count, sizeof(*sorted_strings), "string_set"); if (sorted_strings == NULL) { status = UCS_ERR_NO_MEMORY; goto out; } /* collect and sort the strings */ index = 0; kh_foreach_key(sset, str, { sorted_strings[index++] = str; }) ucs_assert(index == count); qsort(sorted_strings, count, sizeof(*sorted_strings), ucs_string_set_compare_func); /* append the sorted strings to the string buffer */ for (index = 0; index < count; ++index) { status = ucs_string_buffer_appendf(strb, "%s%s", (index > 0) ? sep : "", sorted_strings[index]); if (status != UCS_OK) { goto out_free_array; } } status = UCS_OK; out_free_array: ucs_free(sorted_strings); out: return status; }