⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 su_strlst.c

📁 Internet Phone, Chat, Conferencing
💻 C
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 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_sprintf(su_strlst_home(l), "a is: %d", a)); * su_strlst_append(l, su_sprintf(su_strlst_home(l), "b is: %d", b)); * su_strlst_append(l, su_sprintf(su_strlst_home(l), "c is: %d", c)); * su_strlst_append(l, "------------"); * su_strlst_append(l, su_sprintf(su_strlst_home(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 <stdlib.h>#include <stddef.h>#include <memory.h>#include <limits.h>#include <string.h>#include <assert.h>#include "sofia-sip/su_config.h"#include "sofia-sip/su_strlst.h"enum { 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 string list.  * * The function su_strlst_create() creates a list of strings. The list is * initially empty. It clones a memory home for the list 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;}/** 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.  * * The function su_strlst_append() duplicates and appends a string to a * 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)    str = "";  if (self && str && su_strlst_increase(self)) {    int len = strlen(str);    char *retval = su_alloc(self->sl_home, len + 1);    if (retval) {      memcpy(retval, str, len);      retval[len] = 0;      self->sl_list[self->sl_len++] = retval;      self->sl_total += len;    }    return retval;  }  return NULL;}/**Append a string to list.  * * The function su_strlst_append() appends a string to a list. The string is * not copied, and it @b must not be modified while string list exists. * * @param self  pointer to a string list object * @param str   string to be appended * * @return * Pointer to string, if successful, or NULL upon an error. */char const *su_strlst_append(su_strlst_t *self, char const *str){  if (str == NULL)    str = "";  if (self && su_strlst_increase(self)) {    self->sl_list[self->sl_len++] = str;    self->sl_total += strlen(str);    return str;  }  return NULL;}/**Returns a numbered item from the list of strings. The numbering starts from * 0. *  * @param self  pointer to a string list object * @param i     string index * * @return * Pointer to string, if item exists, or NULL if index is out of bounds or * list does not exist. */char const *su_strlst_item(su_strlst_t const *self, unsigned i){  if (self && i < self->sl_len)    return self->sl_list[i];  else    return NULL;}/**Sets a item to the list of strings.  * * Note that the item numbering starts from 0. *  * @param self  pointer to a string list object * @param i     string index * @param s     string to be set as item @a i * * @return * Pointer to string, if item exists, or NULL if index is out of bounds or * list does not exist. */char const *su_strlst_set_item(su_strlst_t *self, unsigned i, char const *s){  char const *old = NULL;  if (self == NULL)    return NULL;  else if (i == self->sl_len)    return (void)su_strlst_append(self, s), NULL;  else if (i > self->sl_len)    return NULL;  if (s == NULL)    s = "";  old = self->sl_list[i];  self->sl_list[i] = s;  return old;}/**Removes a numbered item from the list of strings. The numbering starts from * 0. The caller is responsible of reclaiming memory used by the removed string. *  * @param self  pointer to a string list object * @param i     string index * * @return * Pointer to string, if item exists, or NULL if index is out of bounds or * list does not exist. */SU_DLL char const *su_strlst_remove(su_strlst_t *self, unsigned i){  if (self && i < self->sl_len) {    char const *s = self->sl_list[i];    memmove(&self->sl_list[i], &self->sl_list[i + 1], 	    &self->sl_list[self->sl_len] - &self->sl_list[i]);    self->sl_len--;    return s;  }  else    return NULL;}/** Concatenate list of strings to one string. * * The function su_strlst_join() concatenates the list of strings. Between * each string in list it uses @a sep. The separator is not inserted after * the last string in list, but one can always append an empty string to the * list. * * The string is allocated from the memory @a home. If @a home is NULL, the * string is allocated using malloc(). * * @param self  pointer to a string list object * @param home  home pointer * @param sep   separator (may be NULL) * * @return  * * The function su_strlst_join() returns a concatenation of the strings in * list, or NULL upon an error. */char *su_strlst_join(su_strlst_t *self, su_home_t *home, char const *sep){  if (!sep)    sep = "";  if (self && self->sl_len > 0) {    unsigned seplen = strlen(sep);    unsigned total = self->sl_total + seplen * (self->sl_len - 1);    char *retval = su_alloc(home, total + 1);    if (retval) {      char *s = retval;      unsigned i = 0, len;      for (;;) {	len = strlen(self->sl_list[i]);	memcpy(s, self->sl_list[i], len), s += len;	if (++i >= self->sl_len)	  break;	memcpy(s, sep, seplen),	s += seplen;      }      *s = '\0';      assert(s == retval + total);    }    return retval;  }  return su_strdup(home, "");}static inlinesu_strlst_t *su_strlst_split0(su_strlst_t *l, char *str, char const *sep){  int n = sep ? strlen(sep) : 0;  char *s;  if (n > 0) {    while ((s = strstr(str, sep))) {      *s = '\0';      if (!su_strlst_append(l, str))	return NULL;      str = s + n;    }  }  if (!su_strlst_append(l, str))    return NULL;  return l;}/**Split a string.  * * Splits a string to substrings. It returns a string list object. The * string to be split is not copied but instead modified in place. Use * su_strlst_dup_split() if you do not want to modify @a str. * * @param home  home pointer * @param str     string to be split * @param sep   separator between substrings * * @return * Pointer to list of strings, if successful, or NULL upon an error. */su_strlst_t *su_strlst_split(su_home_t *home, char *str, char const *sep){  if (str) {    su_strlst_t *l = su_strlst_create(home);    if (!su_strlst_split0(l, str, sep))      su_strlst_destroy(l), l = NULL;    return l;  }  return NULL;}/**Duplicate and split a string.  * * Duplicates a string and splits the result to substrings. It returns a * string list object. The string to be splitted is not modified. * * @param home  home pointer * @param cstr  string to be split * @param sep   separator between substrings * * @return * Pointer to list of strings, if successful, or NULL upon an error. */su_strlst_t *su_strlst_dup_split(su_home_t *home, 				 char const *cstr, 				 char const *sep){  if (cstr) {    su_strlst_t *l = su_strlst_create(home);    if (l) {      char *s = su_strdup(su_strlst_home(l), cstr);      if (s && !su_strlst_split0(l, s, sep))	su_strlst_destroy(l), l = NULL;    }    return l;  }  return NULL;}/** Get number of items in list.  * * The function su_strlst_len() returns the number of items in the  * string list. *  */unsigned su_strlst_len(su_strlst_t const *l){  return l ? l->sl_len : 0;}/**Get a string array from list.  * * The function su_strlst_get_array() returns an array of strings. The * length of the array is always one longer than the length of the string * list, and the last string in the returned array is always NULL. *  * @param self pointer to a string list object * * @return * Pointer to array of strings, or NULL if error occurred. */char const **su_strlst_get_array(su_strlst_t *self){  if (self) {    char const **retval =       su_alloc(self->sl_home, sizeof(retval[0]) * (self->sl_len + 1));        if (retval) {      retval[self->sl_len] = NULL;      return memcpy(retval, self->sl_list, sizeof(retval[0]) * self->sl_len);    }  }  return NULL;}/**Free a string array.  * * The function su_strlst_free_array() discards a string array allocated * with su_strlst_get_array(). *  * @param self  pointer to a string list object * @param array  string array to be freed * */void su_strlst_free_array(su_strlst_t *self, char const **array){  if (array)    su_free(self->sl_home, (void *)array);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -