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