📄 su_strlst.c
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@defgroup su_strlst String Lists * * Lists of strings. * * String lists using #su_home_t. * *//**@ingroup su_strlst * @CFILE su_strlst.c * @brief String lists. * * The string lists can be used to concatenate a large number of strings, or * split a string to smaller pieces (e.g., lines). * * Example of concatenating a number of strings to @a s: * @code * su_strlst_t *l = su_strlist_create(home); * su_strlst_append(l, "============="); * su_slprintf(l, "a is: %d", a) * su_slprintf(l, "b is: %d", b) * su_slprintf(l, "c is: %d", c) * su_strlst_append(l, "------------"); * su_slprintf(l, "total: %d", a + b + c)); * su_strlst_append(l, "============="); * s = su_strlst_join(l, "\n"); * @endcode * * Another example, splitting a string into lines and counting the number of * non-empty ones: * @code * unsigned i, n; * su_strlst_t *l; * * l = su_strlst_split(NULL, buf, "\n"); * * for (i = 0, nonempty = 0; i < su_strlst_len(l); i++) { * n = strcspn(su_strlst_item(l, i), " \t"); * if (su_strlst_item(l, i)[n]) * nonempty++; * } * * su_strlst_destroy(l); * @endcode * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * * @date Created: Fri May 3 09:22:59 2002 ppessi */#include "config.h"#include "sofia-sip/su_config.h"#include "sofia-sip/su_strlst.h"#include <stdlib.h>#include <stddef.h>#include <memory.h>#include <limits.h>#include <string.h>#include <assert.h>#if defined(va_copy)/* Xyzzy */#elif defined(__va_copy)#define va_copy(dst, src) __va_copy((dst), (src))#else#define va_copy(dst, src) (memcpy(&(dst), &(src), sizeof (va_list)))#endifenum { N = 8 };struct su_strlst_s{ su_home_t sl_home[1]; unsigned sl_size; unsigned sl_len; unsigned sl_total; char const **sl_list;};/** Create a list with initial values */staticsu_strlst_t *su_strlst_vcreate_with_by(su_home_t *home, char const *value, va_list va, int deeply){ su_strlst_t *self; int i, n, m; size_t total, size; m = 0, total = 0; /* Count arguments and their length */ if (value) { char const *s; va_list va0; va_copy(va0, va); for (s = value; s; m++, s = va_arg(va0, char *)) total += strlen(s); va_end(va0); } for (n = N; m > n; n *= 2) ; size = sizeof(*self) + n * sizeof(*self->sl_list); if (deeply) size += total + m; self = su_home_clone(home, size); if (self) { self->sl_size = n; self->sl_list = (char const **)(self + 1); self->sl_len = m; self->sl_total = total; if (deeply) { char *s = (char *)(self->sl_list + self->sl_size); char *end = s + total + m; for (i = 0; i < m; i++) { assert(s); self->sl_list[i] = s; s = memccpy(s, value, '\0', end - s); value = va_arg(va, char const *); } } else { for (i = 0; i < m; i++) { self->sl_list[i] = value; value = va_arg(va, char const *); } } } return self;}/** Create an empty string list. * * The list is initially empty. The memory home for the list is cloned from * @a home. * */su_strlst_t *su_strlst_create(su_home_t *home){ su_strlst_t *self; self = su_home_clone(home, sizeof(*self) + N * sizeof(*self->sl_list)); if (self) { self->sl_size = N; self->sl_list = (char const **)(self + 1); } return self;}/** Create a string list with initial values. * * The list is initialized with strings in argument. The argument list is * terminated with NULL. The memory home for the list is cloned from @a * home. */su_strlst_t *su_strlst_create_with(su_home_t *home, char const *value, ...){ va_list va; su_strlst_t *l; va_start(va, value); l = su_strlst_vcreate_with_by(home, value, va, 0); va_end(va); return l;}/** Create a string list with initial values. * * The string list is initialized with strings from @a va_list @a va. The * argument list is terminated with NULL. The memory home for the list is * cloned from @a home. */su_strlst_t *su_strlst_vcreate_with(su_home_t *home, char const *value, va_list va){ return su_strlst_vcreate_with_by(home, value, va, 0);}/** Create a string list with duplicatedd initial values. * * The list is initialized with copies of strings in argument list. The * argument list is terminated with NULL. The memory home for the list is * cloned from @a home. */su_strlst_t *su_strlst_create_with_dup(su_home_t *home, char const *value, ...){ va_list va; su_strlst_t *l; va_start(va, value); l = su_strlst_vcreate_with_by(home, value, va, 1); va_end(va); return l;}/** Create a string list with duplicates of initial values. * * The string list is initialized with copies of strings from @a va_list @a * va. The argument list is terminated with NULL. The memory home for the * list is cloned from @a home. */su_strlst_t *su_strlst_vcreate_with_dup(su_home_t *home, char const *value, va_list va){ return su_strlst_vcreate_with_by(home, value, va, 1);}/** Copy a string list */staticsu_strlst_t *su_strlst_copy_by(su_home_t *home, su_strlst_t const *orig, int deeply){ su_strlst_t *self; int N, i; size_t size, deepsize = 0; if (orig == NULL) return NULL; N = orig->sl_size; if (deeply) deepsize = orig->sl_len + orig->sl_total; size = sizeof(*self) + N * sizeof(self->sl_list[0]) + deepsize; self = su_home_clone(home, size); if (self) { self->sl_size = N; self->sl_list = (char const **)(self + 1); self->sl_len = N = orig->sl_len; self->sl_total = orig->sl_total; if (deeply) { char *s = (char *)(self->sl_list + self->sl_size); char *end = s + deepsize; for (i = 0; i < N; i++) { self->sl_list[i] = s; s = memccpy(s, orig->sl_list[i], '\0', end - s); assert(s); } } else { for (i = 0; i < N; i++) { self->sl_list[i] = orig->sl_list[i]; } } } return self;}/** Shallow copy a string list. */su_strlst_t *su_strlst_copy(su_home_t *home, su_strlst_t const *orig){ return su_strlst_copy_by(home, orig, 0);}/** Deep copy a string list. */su_strlst_t *su_strlst_dup(su_home_t *home, su_strlst_t const *orig){ return su_strlst_copy_by(home, orig, 1);}/** Destroy a string list. * * The function su_strlst_destroy() destroys a list of strings and frees all * duplicated strings belonging to it. */void su_strlst_destroy(su_strlst_t *self){ su_home_zap(self->sl_home);}/** Increase the list size for next item, if necessary. */static int su_strlst_increase(su_strlst_t *self){ if (self->sl_size <= self->sl_len + 1) { unsigned n = 2 * self->sl_size; char const **list; if (self->sl_list != (char const **)(self + 1)) { list = su_realloc(self->sl_home, (void *)self->sl_list, n * sizeof(*self->sl_list)); } else { list = su_alloc(self->sl_home, n * sizeof(*self->sl_list)); if (list) memcpy(list, self->sl_list, self->sl_len * sizeof(*self->sl_list)); } if (!list) return 0; self->sl_list = list; self->sl_size = n; } return 1;}/**Duplicate and append a string to list. * * @param self pointer to a string list object * @param str string to be duplicated and appended * * @return * Pointer to duplicated string, if successful, or NULL upon an error. */char *su_strlst_dup_append(su_strlst_t *self, char const *str){ if (str == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -