s@declarded@declared@
[privoxy.git] / ssplit.c
1 const char ssplit_rcs[] = "$Id: ssplit.c,v 1.8 2006/07/18 14:48:47 david__schmidt 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  * Revisions   :
34  *    $Log: ssplit.c,v $
35  *    Revision 1.8  2006/07/18 14:48:47  david__schmidt
36  *    Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
37  *    with what was really the latest development (the v_3_0_branch branch)
38  *
39  *    Revision 1.6  2002/03/26 22:29:55  swa
40  *    we have a new homepage!
41  *
42  *    Revision 1.5  2002/03/24 13:25:43  swa
43  *    name change related issues
44  *
45  *    Revision 1.4  2001/11/13 00:16:38  jongfoster
46  *    Replacing references to malloc.h with the standard stdlib.h
47  *    (See ANSI or K&R 2nd Ed)
48  *
49  *    Revision 1.3  2001/05/29 08:54:25  jongfoster
50  *    Rewrote the innards of ssplit() to be easier to understand,
51  *    faster, and to use less memory.  Didn't change the interface
52  *    except to give the parameters meaningful names.
53  *
54  *    Revision 1.2  2001/05/17 23:01:01  oes
55  *     - Cleaned CRLF's from the sources and related files
56  *
57  *    Revision 1.1.1.1  2001/05/15 13:59:04  oes
58  *    Initial import of version 2.9.3 source tree
59  *
60  *
61  *********************************************************************/
62 \f
63
64 #include "config.h"
65
66 #include <string.h>
67 #include <stdlib.h>
68
69 #include "ssplit.h"
70 #include "miscutil.h"
71
72 const char ssplit_h_rcs[] = SSPLIT_H_VERSION;
73
74 /* Define this for lots of debugging information to stdout */
75 #undef SSPLIT_VERBOSE
76 /* #define SSPLIT_VERBOSE 1 */
77
78
79 /*********************************************************************
80  *
81  * Function    :  ssplit
82  *
83  * Description :  Split a string using delimiters in `delim'.  Results
84  *                go into `vec'.
85  *
86  * Parameters  :
87  *          1  :  str = string to split.  Will be split in place
88  *                (i.e. do not free until you've finished with vec,
89  *                previous contents will be trashed by the call).
90  *          2  :  delim = array of delimiters (if NULL, uses " \t").
91  *          3  :  vec[] = results vector (aka. array) [out]
92  *          4  :  vec_len = number of usable slots in the vector (aka. array size)
93  *          5  :  dont_save_empty_fields = zero if consecutive delimiters
94  *                give a null output field(s), nonzero if they are just 
95  *                to be considered as single delimeter
96  *          6  :  ignore_leading = nonzero to ignore leading field
97  *                separators.
98  *
99  * Returns     :  -1 => Error: vec_len is too small to hold all the 
100  *                      data, or str == NULL.
101  *                >=0 => the number of fields put in `vec'.
102  *                On error, vec and str may still have been overwritten.
103  *
104  *********************************************************************/
105 int ssplit(char *str, const char *delim, char *vec[], int vec_len, 
106            int dont_save_empty_fields, int ignore_leading)
107 {
108    unsigned char is_delim[256];
109    unsigned char char_type;
110    int vec_count = 0;
111
112    if (!str)
113    {
114       return(-1);
115    }
116
117
118    /* Build is_delim array */
119
120    memset(is_delim, '\0', sizeof(is_delim));
121
122    if (!delim)
123    {
124       delim = " \t";  /* default field separators */
125    }
126
127    while (*delim)
128    {
129       is_delim[(unsigned)(unsigned char)*delim++] = 1;   /* separator  */
130    }
131
132    is_delim[(unsigned)(unsigned char)'\0'] = 2;   /* terminator */
133    is_delim[(unsigned)(unsigned char)'\n'] = 2;   /* terminator */
134
135
136    /* Parse string */
137
138    if (ignore_leading)
139    {
140       /* skip leading separators */
141       while (is_delim[(unsigned)(unsigned char)*str] == 1)
142       {
143          str++;
144       }
145    }
146
147    /* first pointer is the beginning of string */
148    /* Check if we want to save this field */
149    if ( (!dont_save_empty_fields)
150      || (is_delim[(unsigned)(unsigned char)*str] == 0) )
151       {
152       /*
153        * We want empty fields, or the first character in this 
154        * field is not a delimiter or the end of string.
155        * So save it.
156        */
157       if (vec_count >= vec_len)
158       {
159          return(-1); /* overflow */
160       }
161       vec[vec_count++] = (char *) str;   
162    }
163
164    while ((char_type = is_delim[(unsigned)(unsigned char)*str]) != 2)
165    {
166       if (char_type == 1)    
167       {
168          /* the char is a separator */
169
170          /* null terminate the substring */
171          *str++ = '\0';      
172
173          /* Check if we want to save this field */
174          if ( (!dont_save_empty_fields)
175            || (is_delim[(unsigned)(unsigned char)*str] == 0) )
176             {
177             /*
178              * We want empty fields, or the first character in this 
179              * field is not a delimiter or the end of string.
180              * So save it.
181              */
182             if (vec_count >= vec_len)
183             {
184                return(-1); /* overflow */
185             }
186             vec[vec_count++] = (char *) str;   
187          }
188       }
189       else
190       {
191          str++;
192       }
193    }
194    *str = '\0';     /* null terminate the substring */
195
196 #ifdef SSPLIT_VERBOSE
197    {
198       int i;
199       printf("dump %d strings\n", vec_count);
200       for (i = 0; i < vec_count; i++)
201       {
202          printf("%d '%s'\n", i, vec[i]);
203       }
204    }
205 #endif /* def SSPLIT_VERBOSE */
206
207    return(vec_count);
208 }
209
210
211 /*
212   Local Variables:
213   tab-width: 3
214   end:
215 */