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