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