Do not check for the existence of strerror() and memmove() twice
[privoxy.git] / ssplit.c
1 const char ssplit_rcs[] = "$Id: ssplit.c,v 1.10 2009/05/16 13:27:20 fabiankeil Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/ssplit.c,v $
5  *
6  * Purpose     :  A function to split a string at specified delimiters.
7  *
8  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
9  *                Privoxy team. http://www.privoxy.org/
10  *
11  *                Based on the Internet Junkbuster originally written
12  *                by and Copyright (C) 1997 Anonymous Coders and 
13  *                Junkbusters Corporation.  http://www.junkbusters.com
14  *
15  *                This program is free software; you can redistribute it 
16  *                and/or modify it under the terms of the GNU General
17  *                Public License as published by the Free Software
18  *                Foundation; either version 2 of the License, or (at
19  *                your option) any later version.
20  *
21  *                This program is distributed in the hope that it will
22  *                be useful, but WITHOUT ANY WARRANTY; without even the
23  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
24  *                PARTICULAR PURPOSE.  See the GNU General Public
25  *                License for more details.
26  *
27  *                The GNU General Public License should be included with
28  *                this file.  If not, you can view it at
29  *                http://www.gnu.org/copyleft/gpl.html
30  *                or write to the Free Software Foundation, Inc., 59
31  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
32  *
33  *********************************************************************/
34
35
36 #include "config.h"
37
38 #include <string.h>
39 #include <stdlib.h>
40
41 #include "ssplit.h"
42 #include "miscutil.h"
43
44 const char ssplit_h_rcs[] = SSPLIT_H_VERSION;
45
46 /* Define this for lots of debugging information to stdout */
47 #undef SSPLIT_VERBOSE
48 /* #define SSPLIT_VERBOSE 1 */
49
50
51 /*********************************************************************
52  *
53  * Function    :  ssplit
54  *
55  * Description :  Split a string using delimiters in `delim'.  Results
56  *                go into `vec'.
57  *
58  * Parameters  :
59  *          1  :  str = string to split.  Will be split in place
60  *                (i.e. do not free until you've finished with vec,
61  *                previous contents will be trashed by the call).
62  *          2  :  delim = array of delimiters (if NULL, uses " \t").
63  *          3  :  vec[] = results vector (aka. array) [out]
64  *          4  :  vec_len = number of usable slots in the vector (aka. array size)
65  *          5  :  dont_save_empty_fields = zero if consecutive delimiters
66  *                give a null output field(s), nonzero if they are just 
67  *                to be considered as single delimeter
68  *          6  :  ignore_leading = nonzero to ignore leading field
69  *                separators.
70  *
71  * Returns     :  -1 => Error: vec_len is too small to hold all the 
72  *                      data, or str == NULL.
73  *                >=0 => the number of fields put in `vec'.
74  *                On error, vec and str may still have been overwritten.
75  *
76  *********************************************************************/
77 int ssplit(char *str, const char *delim, char *vec[], size_t vec_len,
78            int dont_save_empty_fields, int ignore_leading)
79 {
80    unsigned char is_delim[256];
81    unsigned char char_type;
82    int vec_count = 0;
83
84    if (!str)
85    {
86       return(-1);
87    }
88
89
90    /* Build is_delim array */
91
92    memset(is_delim, '\0', sizeof(is_delim));
93
94    if (!delim)
95    {
96       delim = " \t";  /* default field separators */
97    }
98
99    while (*delim)
100    {
101       is_delim[(unsigned)(unsigned char)*delim++] = 1;   /* separator  */
102    }
103
104    is_delim[(unsigned)(unsigned char)'\0'] = 2;   /* terminator */
105    is_delim[(unsigned)(unsigned char)'\n'] = 2;   /* terminator */
106
107
108    /* Parse string */
109
110    if (ignore_leading)
111    {
112       /* skip leading separators */
113       while (is_delim[(unsigned)(unsigned char)*str] == 1)
114       {
115          str++;
116       }
117    }
118
119    /* first pointer is the beginning of string */
120    /* Check if we want to save this field */
121    if ( (!dont_save_empty_fields)
122      || (is_delim[(unsigned)(unsigned char)*str] == 0) )
123       {
124       /*
125        * We want empty fields, or the first character in this 
126        * field is not a delimiter or the end of string.
127        * So save it.
128        */
129       if (vec_count >= vec_len)
130       {
131          return(-1); /* overflow */
132       }
133       vec[vec_count++] = (char *) str;   
134    }
135
136    while ((char_type = is_delim[(unsigned)(unsigned char)*str]) != 2)
137    {
138       if (char_type == 1)    
139       {
140          /* the char is a separator */
141
142          /* null terminate the substring */
143          *str++ = '\0';      
144
145          /* Check if we want to save this field */
146          if ( (!dont_save_empty_fields)
147            || (is_delim[(unsigned)(unsigned char)*str] == 0) )
148             {
149             /*
150              * We want empty fields, or the first character in this 
151              * field is not a delimiter or the end of string.
152              * So save it.
153              */
154             if (vec_count >= vec_len)
155             {
156                return(-1); /* overflow */
157             }
158             vec[vec_count++] = (char *) str;   
159          }
160       }
161       else
162       {
163          str++;
164       }
165    }
166    *str = '\0';     /* null terminate the substring */
167
168 #ifdef SSPLIT_VERBOSE
169    {
170       int i;
171       printf("dump %d strings\n", vec_count);
172       for (i = 0; i < vec_count; i++)
173       {
174          printf("%d '%s'\n", i, vec[i]);
175       }
176    }
177 #endif /* def SSPLIT_VERBOSE */
178
179    return(vec_count);
180 }
181
182
183 /*
184   Local Variables:
185   tab-width: 3
186   end:
187 */