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