Home | History | Annotate | Line # | Download | only in src
      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 (at) 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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.  */
     35 void
     36 string_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.  */
     45 string_list_ty *
     46 string_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.  */
     60 void
     61 string_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.  */
     80 void
     81 string_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.  */
    105 void
    106 string_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.  */
    118 void
    119 string_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.  */
    133 char *
    134 string_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.  */
    159 char *
    160 string_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. */
    184 char *
    185 string_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.  */
    224 bool
    225 string_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