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