/* * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License v.2.1. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "lib/misc/lib.h" #include "lib/datastruct/str_list.h" struct dm_list *str_list_create(struct dm_pool *mem) { struct dm_list *sl; if (!(sl = dm_pool_alloc(mem, sizeof(struct dm_list)))) { log_errno(ENOMEM, "str_list allocation failed"); return NULL; } dm_list_init(sl); return sl; } static int _str_list_add_no_dup_check(struct dm_pool *mem, struct dm_list *sll, const char *str, int as_first) { struct dm_str_list *sln; if (!str) return_0; if (!(sln = dm_pool_alloc(mem, sizeof(*sln)))) return_0; sln->str = str; if (as_first) dm_list_add_h(sll, &sln->list); else dm_list_add(sll, &sln->list); return 1; } int str_list_add_no_dup_check(struct dm_pool *mem, struct dm_list *sll, const char *str) { return _str_list_add_no_dup_check(mem, sll, str, 0); } int str_list_add_h_no_dup_check(struct dm_pool *mem, struct dm_list *sll, const char *str) { return _str_list_add_no_dup_check(mem, sll, str, 1); } int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str) { if (!str) return_0; /* Already in list? */ if (str_list_match_item(sll, str)) return 1; return str_list_add_no_dup_check(mem, sll, str); } /* Add contents of sll2 to sll */ int str_list_add_list(struct dm_pool *mem, struct dm_list *sll, struct dm_list *sll2) { struct dm_str_list *sl; if (!sll2) return_0; dm_list_iterate_items(sl, sll2) if (!str_list_add(mem, sll, sl->str)) return_0; return 1; } void str_list_del(struct dm_list *sll, const char *str) { struct dm_list *slh, *slht; dm_list_iterate_safe(slh, slht, sll) if (!strcmp(str, dm_list_item(slh, struct dm_str_list)->str)) dm_list_del(slh); } void str_list_wipe(struct dm_list *sll) { struct dm_list *slh, *slht; dm_list_iterate_safe(slh, slht, sll) dm_list_del(slh); } int str_list_dup(struct dm_pool *mem, struct dm_list *sllnew, const struct dm_list *sllold) { struct dm_str_list *sl; dm_list_init(sllnew); dm_list_iterate_items(sl, sllold) { if (!str_list_add(mem, sllnew, dm_pool_strdup(mem, sl->str))) return_0; } return 1; } /* * Is item on list? */ int str_list_match_item(const struct dm_list *sll, const char *str) { struct dm_str_list *sl; dm_list_iterate_items(sl, sll) if (!strcmp(str, sl->str)) return 1; return 0; } /* * Is at least one item on both lists? * If tag_matched is non-NULL, it is set to the tag that matched. */ int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2, const char **tag_matched) { struct dm_str_list *sl; dm_list_iterate_items(sl, sll) if (str_list_match_item(sll2, sl->str)) { if (tag_matched) *tag_matched = sl->str; return 1; } return 0; } /* * Do both lists contain the same set of items? */ int str_list_lists_equal(const struct dm_list *sll, const struct dm_list *sll2) { struct dm_str_list *sl; if (dm_list_size(sll) != dm_list_size(sll2)) return 0; dm_list_iterate_items(sl, sll) if (!str_list_match_item(sll2, sl->str)) return 0; return 1; } char *str_list_to_str(struct dm_pool *mem, const struct dm_list *list, const char *delim) { size_t delim_len = strlen(delim); unsigned list_size = dm_list_size(list); struct dm_str_list *sl; char *str, *p; size_t len = 0; unsigned i = 0; dm_list_iterate_items(sl, list) len += strlen(sl->str); if (list_size > 1) len += ((list_size - 1) * delim_len); str = dm_pool_alloc(mem, len+1); if (!str) { log_error("str_list_to_str: string allocation failed."); return NULL; } str[len] = '\0'; p = str; dm_list_iterate_items(sl, list) { len = strlen(sl->str); memcpy(p, sl->str, len); p += len; if (++i != list_size) { memcpy(p, delim, delim_len); p += delim_len; } } return str; } struct dm_list *str_to_str_list(struct dm_pool *mem, const char *str, const char *delim, int ignore_multiple_delim) { size_t delim_len = strlen(delim); struct dm_list *list; const char *p1, *p2, *next; char *str_item; size_t len; if (!(list = str_list_create(mem))) { log_error("str_to_str_list: string list allocation failed."); return NULL; } p1 = p2 = str; while (*p1) { if (!(p2 = strstr(p1, delim))) next = p2 = str + strlen(str); else next = p2 + delim_len; len = p2 - p1; str_item = dm_pool_alloc(mem, len+1); if (!str_item) { log_error("str_to_str_list: string list item allocation failed."); goto bad; } memcpy(str_item, p1, len); str_item[len] = '\0'; if (!str_list_add_no_dup_check(mem, list, str_item)) goto_bad; if (ignore_multiple_delim) { while (!strncmp(next, delim, delim_len)) next += delim_len; } p1 = next; } return list; bad: dm_pool_free(mem, list); return NULL; }