StringVector.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 Reinhard Prix
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with with program; see the file COPYING. If not, write to the
00016  *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017  *  MA  02111-1307  USA
00018  */
00019 
00020 /**
00021  * \file
00022  *
00023  * \author Reinhard Prix
00024  * \ingroup factories
00025  * \brief  Creation/destruction/manipulation functions for 'LALStringVector' type objects.
00026  *
00027  * Revision: $Id: StringVector.c,v 1.1 2008/02/22 16:11:07 reinhard Exp $
00028  *
00029  */
00030 
00031 /*---------- INCLUDES ----------*/
00032 #include <string.h>
00033 #include <stdlib.h>
00034 #include <stdarg.h>
00035 
00036 #include <lal/XLALError.h>
00037 #include <lal/StringVector.h>
00038 #include <lal/LALMalloc.h>
00039 
00040 /*---------- DEFINES ----------*/
00041 /*---------- internal types ----------*/
00042 static CHAR *deblank_string ( const CHAR *start, UINT4 len );
00043 
00044 /*---------- empty initializers ---------- */
00045 const LALStringVector empty_LALStringVector;
00046 
00047 /*---------- Global variables ----------*/
00048 NRCSID( STRINGVECTORC, "$Id: StringVector.c,v 1.1 2008/02/22 16:11:07 reinhard Exp $");
00049 
00050 /*---------- internal prototypes ----------*/
00051 
00052 
00053 /*==================== FUNCTION DEFINITIONS ====================*/
00054 
00055 /** Append the given string to the string-vector (XLAL interface), return
00056  * pointer to the resulting string-vector, or NULL on error.
00057  *
00058  * \note It is allowed to pass NULL as the input string-vector 'vect', which corresponds
00059  * to creating a new string-vector with a single element 'string'
00060  */
00061 LALStringVector *
00062 XLALAppendString2Vector (LALStringVector *vect,         /**< input string-vector to append to */
00063                          const CHAR *string             /**< string to append */
00064                          )
00065 {
00066   const CHAR *fn = "XLALAppendString2Vector()";
00067   UINT4 oldlen;
00068   LALStringVector *ret;
00069 
00070   if ( !string ) {
00071     XLALPrintError ("\n%s: NULL string passed to append\n\n", fn );
00072     XLAL_ERROR_NULL ( fn, XLAL_EINVAL );
00073   }
00074 
00075   if ( ! vect )
00076     ret = XLALCreateStringVector ( string, NULL );      /* special case: NULL string-vector to append to */
00077   else
00078     {
00079       ret = vect;
00080       oldlen = ret->length;
00081 
00082       if ( (ret->data = LALRealloc ( ret->data, (oldlen + 1)*sizeof( *ret->data ) )) == NULL ) {
00083         XLAL_ERROR_NULL ( fn, XLAL_ENOMEM );
00084       }
00085 
00086       ret->length ++;
00087 
00088       if ( (ret->data[oldlen] = LALCalloc(1, strlen(string) + 1 )) == NULL ) {
00089         XLAL_ERROR_NULL ( fn, XLAL_ENOMEM );
00090       }
00091 
00092       strcpy ( ret->data[oldlen], string );
00093     }
00094 
00095   return ret;
00096 
00097 } /* XLALAppendString2Vector() */
00098 
00099 
00100 
00101 
00102 /** Create a StringVector from the list of strings passed as arguments
00103  * \note All arguments MUST be CHAR* strings.
00104  * The last argument MUST be NULL, as C cannot deduce the number of arguments
00105  * otherwise.
00106  */
00107 LALStringVector *
00108 XLALCreateStringVector ( const CHAR *str1, ... )
00109 {
00110   const CHAR *fn = "XLALCreateStringVector()";
00111   LALStringVector *ret;
00112   const CHAR *next;
00113   va_list ap;
00114 
00115   if ( !str1 ) {
00116     XLAL_ERROR_NULL (fn, XLAL_EINVAL );
00117   }
00118 
00119   /* set up return vector of strings, and handle first argument */
00120   if ( (ret = LALCalloc ( 1, sizeof(*ret) )) == NULL ) {
00121     XLAL_ERROR_NULL ( fn, XLAL_ENOMEM );
00122   }
00123   if ( (ret->data = LALCalloc ( 1, sizeof(ret->data[0]) )) == NULL) {
00124     LALFree ( ret );
00125     XLAL_ERROR_NULL ( fn, XLAL_ENOMEM );
00126   }
00127   if ( (ret->data[0] = LALCalloc ( strlen(str1)+1, sizeof(CHAR) )) == NULL ) {
00128     LALFree ( ret->data );
00129     LALFree ( ret );
00130     XLAL_ERROR_NULL ( fn, XLAL_ENOMEM );
00131   }
00132   strcpy ( ret->data[0], str1 );
00133   ret->length ++;
00134 
00135   /* handle remaining variable-length list of (assumed)string arguments */
00136   va_start(ap, str1);
00137 
00138   while ( (next = va_arg(ap, const CHAR *)) != NULL )
00139     {
00140       ret->length ++;
00141       if ( (ret->data = LALRealloc ( ret->data, ret->length * sizeof(ret->data[0]))) == NULL )
00142         goto failed;
00143       if ( (ret->data[ret->length-1] = LALCalloc( strlen(next)+1, sizeof(CHAR) )) == NULL )
00144         goto failed;
00145 
00146       strcpy ( ret->data[ret->length-1], next );
00147 
00148     } /* while more arguments */
00149 
00150   va_end(ap);
00151 
00152   return ret;
00153 
00154  failed:
00155   va_end(ap);
00156   XLALDestroyStringVector ( ret );
00157   XLAL_ERROR_NULL ( fn, XLAL_ENOMEM );
00158 
00159 } /* XLALCreateStringVector() */
00160 
00161 
00162 /** XLAL-interface: Free a string-vector ;) */
00163 void
00164 XLALDestroyStringVector ( LALStringVector *vect )
00165 {
00166   UINT4 i;
00167 
00168   if ( !vect )
00169     return;
00170 
00171   if ( vect->data )
00172     {
00173       for ( i=0; i < vect->length; i++ )
00174         {
00175           if ( vect->data[i] )
00176             LALFree ( vect->data[i] );
00177         }
00178 
00179       LALFree ( vect->data );
00180     }
00181 
00182   LALFree ( vect );
00183 
00184   return;
00185 
00186 } /* XLALDestroyStringVector() */
00187 
00188 
00189 
00190 /* comparison function for strings */
00191 static int StringCompare (const void *p1, const void *p2)
00192 {
00193   const char *s1 = p1;
00194   const char *s2 = p2;
00195   return (strcmp ( s1, s2 ) );
00196 }
00197 
00198 /** Sort string-vector alphabetically
00199  */
00200 int
00201 XLALSortStringVector (LALStringVector *strings)
00202 {
00203   const CHAR *fn = "XLALSortStringVector()";
00204   if ( !strings || strings->length == 0 ) {
00205     XLAL_ERROR ( fn, XLAL_EINVAL );
00206   }
00207 
00208   qsort ( (void*)(strings->data), (size_t)(strings->length), sizeof(CHAR*), StringCompare );
00209 
00210   return XLAL_SUCCESS;
00211 
00212 } /* XLALSortStringVector() */
00213 
00214 
00215 
00216 /** Parse a list of comma-separated values (CSV) into a StringVector
00217  * \note surrounding whitespace is removed from the 'values'.
00218  */
00219 LALStringVector *
00220 XLALParseCSV2StringVector ( const CHAR *CSVlist )
00221 {
00222   const CHAR *fn = "XLALParseCSV2StringVector";
00223   UINT4 counter;
00224   const CHAR *start, *tmp;
00225   CHAR **data = NULL;
00226   LALStringVector *ret = NULL;
00227 
00228   if ( !CSVlist )
00229     return NULL;
00230 
00231   /* prepare return string-vector */
00232   if ( ( ret = LALCalloc ( 1, sizeof( *ret )) ) == NULL )
00233     XLAL_ERROR_NULL ( fn, XLAL_ENOMEM );
00234 
00235   start = CSVlist;
00236   counter = 0;
00237   do
00238     {
00239       UINT4 len;
00240 
00241       /* extend string-array */
00242       if ( ( data = LALRealloc ( data, (counter+1) * sizeof(CHAR*) )) == NULL )
00243         goto failed;
00244 
00245       /* determine string-length of next value */
00246       if ( ( tmp = strchr ( start, ',' ) ) )
00247         len = tmp - start;
00248       else
00249         len = strlen ( start );
00250 
00251       /* allocate space for that value in string-array */
00252       if ( (data[counter] = deblank_string ( start, len ) ) == NULL )
00253         goto failed;
00254 
00255       counter ++;
00256 
00257     } while ( tmp && (start = tmp + 1) );
00258 
00259   ret -> length = counter;
00260   ret -> data = data;
00261 
00262   /* success: */
00263   return ( ret );
00264 
00265  failed:
00266   XLALDestroyStringVector ( ret );
00267   XLAL_ERROR_NULL ( fn, XLAL_ENOMEM );
00268 
00269 } /* XLALParseCSV2StringVector() */
00270 
00271 
00272 /** Copy (and allocate) string from 'start' with length 'len', removing
00273  * all starting- and trailing blanks!
00274  */
00275 CHAR *
00276 deblank_string ( const CHAR *start, UINT4 len )
00277 {
00278   const CHAR *blank_chars = " \t\n";
00279   const CHAR *pos0, *pos1;
00280   UINT4 newlen;
00281   CHAR *ret;
00282 
00283   if ( !start || !len )
00284     return NULL;
00285 
00286   /* clip from beginning */
00287   pos0 = start;
00288   pos1 = start + len - 1;
00289   while ( (pos0 < pos1) && strchr ( blank_chars, *pos0 ) )
00290     pos0 ++;
00291 
00292   /* clip backwards from end */
00293   while ( (pos1 >= pos0) && strchr ( blank_chars, *pos1 ) )
00294     pos1 --;
00295 
00296   newlen = pos1 - pos0 + 1;
00297   if ( !newlen )
00298     return NULL;
00299 
00300   if ( (ret = LALCalloc(1, newlen + 1)) == NULL )
00301     return NULL;
00302 
00303   strncpy ( ret, pos0, newlen );
00304   ret[ newlen ] = 0;
00305 
00306   return ret;
00307 
00308 } /* deblank_string() */
00309 

Generated on Mon Oct 13 02:32:18 2008 for LAL by  doxygen 1.5.2