1/* GNU gettext - internationalization aids 2 Copyright (C) 1995, 1998, 2000-2004 Free Software Foundation, Inc. 3 4 This file was written by Peter Miller <millerp@canb.auug.org.au> 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software Foundation, 18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 19 20#ifdef HAVE_CONFIG_H 21# include "config.h" 22#endif 23 24/* Specification. */ 25#include "str-list.h" 26 27#include <stdio.h> 28#include <stdlib.h> 29#include <string.h> 30 31#include "xalloc.h" 32 33 34/* Initialize an empty list of strings. */ 35void 36string_list_init (string_list_ty *slp) 37{ 38 slp->item = NULL; 39 slp->nitems = 0; 40 slp->nitems_max = 0; 41} 42 43 44/* Return a fresh, empty list of strings. */ 45string_list_ty * 46string_list_alloc () 47{ 48 string_list_ty *slp; 49 50 slp = (string_list_ty *) xmalloc (sizeof (*slp)); 51 slp->item = NULL; 52 slp->nitems = 0; 53 slp->nitems_max = 0; 54 55 return slp; 56} 57 58 59/* Append a single string to the end of a list of strings. */ 60void 61string_list_append (string_list_ty *slp, const char *s) 62{ 63 /* Grow the list. */ 64 if (slp->nitems >= slp->nitems_max) 65 { 66 size_t nbytes; 67 68 slp->nitems_max = slp->nitems_max * 2 + 4; 69 nbytes = slp->nitems_max * sizeof (slp->item[0]); 70 slp->item = (const char **) xrealloc (slp->item, nbytes); 71 } 72 73 /* Add a copy of the string to the end of the list. */ 74 slp->item[slp->nitems++] = xstrdup (s); 75} 76 77 78/* Append a single string to the end of a list of strings, unless it is 79 already contained in the list. */ 80void 81string_list_append_unique (string_list_ty *slp, const char *s) 82{ 83 size_t j; 84 85 /* Do not if the string is already in the list. */ 86 for (j = 0; j < slp->nitems; ++j) 87 if (strcmp (slp->item[j], s) == 0) 88 return; 89 90 /* Grow the list. */ 91 if (slp->nitems >= slp->nitems_max) 92 { 93 slp->nitems_max = slp->nitems_max * 2 + 4; 94 slp->item = (const char **) xrealloc (slp->item, 95 slp->nitems_max 96 * sizeof (slp->item[0])); 97 } 98 99 /* Add a copy of the string to the end of the list. */ 100 slp->item[slp->nitems++] = xstrdup (s); 101} 102 103 104/* Destroy a list of strings. */ 105void 106string_list_destroy (string_list_ty *slp) 107{ 108 size_t j; 109 110 for (j = 0; j < slp->nitems; ++j) 111 free ((char *) slp->item[j]); 112 if (slp->item != NULL) 113 free (slp->item); 114} 115 116 117/* Free a list of strings. */ 118void 119string_list_free (string_list_ty *slp) 120{ 121 size_t j; 122 123 for (j = 0; j < slp->nitems; ++j) 124 free ((char *) slp->item[j]); 125 if (slp->item != NULL) 126 free (slp->item); 127 free (slp); 128} 129 130 131/* Return a freshly allocated string obtained by concatenating all the 132 strings in the list. */ 133char * 134string_list_concat (const string_list_ty *slp) 135{ 136 size_t len; 137 size_t j; 138 char *result; 139 size_t pos; 140 141 len = 1; 142 for (j = 0; j < slp->nitems; ++j) 143 len += strlen (slp->item[j]); 144 result = (char *) xmalloc (len); 145 pos = 0; 146 for (j = 0; j < slp->nitems; ++j) 147 { 148 len = strlen (slp->item[j]); 149 memcpy (result + pos, slp->item[j], len); 150 pos += len; 151 } 152 result[pos] = '\0'; 153 return result; 154} 155 156 157/* Return a freshly allocated string obtained by concatenating all the 158 strings in the list, and destroy the list. */ 159char * 160string_list_concat_destroy (string_list_ty *slp) 161{ 162 char *result; 163 164 /* Optimize the most frequent case. */ 165 if (slp->nitems == 1) 166 { 167 result = (char *) slp->item[0]; 168 free (slp->item); 169 } 170 else 171 { 172 result = string_list_concat (slp); 173 string_list_destroy (slp); 174 } 175 return result; 176} 177 178 179/* Return a freshly allocated string obtained by concatenating all the 180 strings in the list, separated by the separator character, terminated 181 by the terminator character. The terminator character is not added if 182 drop_redundant_terminator is true and the last string already ends with 183 the terminator. */ 184char * 185string_list_join (const string_list_ty *slp, char separator, 186 char terminator, bool drop_redundant_terminator) 187{ 188 size_t len; 189 size_t j; 190 char *result; 191 size_t pos; 192 193 len = 1; 194 for (j = 0; j < slp->nitems; ++j) 195 { 196 if (separator && j > 0) 197 ++len; 198 len += strlen (slp->item[j]); 199 } 200 if (terminator) 201 ++len; 202 result = (char *) xmalloc (len); 203 pos = 0; 204 for (j = 0; j < slp->nitems; ++j) 205 { 206 if (separator && j > 0) 207 result[pos++] = separator; 208 len = strlen (slp->item[j]); 209 memcpy (result + pos, slp->item[j], len); 210 pos += len; 211 } 212 if (terminator 213 && !(drop_redundant_terminator 214 && slp->nitems > 0 215 && (len = strlen (slp->item[slp->nitems - 1])) > 0 216 && slp->item[slp->nitems - 1][len - 1] == terminator)) 217 result[pos++] = terminator; 218 result[pos] = '\0'; 219 return result; 220} 221 222 223/* Return 1 if s is contained in the list of strings, 0 otherwise. */ 224bool 225string_list_member (const string_list_ty *slp, const char *s) 226{ 227 size_t j; 228 229 for (j = 0; j < slp->nitems; ++j) 230 if (strcmp (slp->item[j], s) == 0) 231 return true; 232 return false; 233} 234