Complicate the license explanation even further
[privoxy.git] / ssplit.c
1 /*********************************************************************
2  *
3  * File        :  $Source: /cvsroot/ijbswa/current/ssplit.c,v $
4  *
5  * Purpose     :  A function to split a string at specified delimiters.
6  *
7  * Copyright   :  Written by and Copyright (C) 2001-2012 the
8  *                Privoxy team. https://www.privoxy.org/
9  *
10  *                Based on the Internet Junkbuster originally written
11  *                by and Copyright (C) 1997 Anonymous Coders and
12  *                Junkbusters Corporation.  http://www.junkbusters.com
13  *
14  *                This program is free software; you can redistribute it
15  *                and/or modify it under the terms of the GNU General
16  *                Public License as published by the Free Software
17  *                Foundation; either version 2 of the License, or (at
18  *                your option) any later version.
19  *
20  *                This program is distributed in the hope that it will
21  *                be useful, but WITHOUT ANY WARRANTY; without even the
22  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
23  *                PARTICULAR PURPOSE.  See the GNU General Public
24  *                License for more details.
25  *
26  *                The GNU General Public License should be included with
27  *                this file.  If not, you can view it at
28  *                http://www.gnu.org/copyleft/gpl.html
29  *                or write to the Free Software Foundation, Inc., 59
30  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
31  *
32  *********************************************************************/
33
34
35 #include "config.h"
36
37 #include <string.h>
38 #include <stdlib.h>
39 #include <assert.h>
40
41 #include "ssplit.h"
42 #include "miscutil.h"
43
44
45 /*********************************************************************
46  *
47  * Function    :  ssplit
48  *
49  * Description :  Split a string using delimiters in `delim'.  Results
50  *                go into `vec'.
51  *
52  * Parameters  :
53  *          1  :  str = string to split.  Will be split in place
54  *                (i.e. do not free until you've finished with vec,
55  *                previous contents will be trashed by the call).
56  *          2  :  delim = array of delimiters (if NULL, uses " \t").
57  *          3  :  vec[] = results vector (aka. array) [out]
58  *          4  :  vec_len = number of usable slots in the vector (aka. array size)
59  *
60  * Returns     :  -1 => Error: vec_len is too small to hold all the
61  *                      data, or str == NULL.
62  *                >=0 => the number of fields put in `vec'.
63  *                On error, vec and str may still have been overwritten.
64  *
65  *********************************************************************/
66 int ssplit(char *str, const char *delim, char *vec[], size_t vec_len)
67 {
68    unsigned char is_delim[256];
69    unsigned char char_type;
70    int vec_count = 0;
71    enum char_type {
72       WANTED     = 0,
73       SEPARATOR  = 1,
74       TERMINATOR = 2,
75    };
76
77
78    if (!str)
79    {
80       return(-1);
81    }
82
83
84    /* Build is_delim array */
85
86    memset(is_delim, '\0', sizeof(is_delim));
87
88    if (!delim)
89    {
90       delim = " \t";  /* default field separators */
91    }
92
93    while (*delim)
94    {
95       is_delim[(unsigned)(unsigned char)*delim++] = SEPARATOR;
96    }
97
98    is_delim[(unsigned)(unsigned char)'\0'] = TERMINATOR;
99    is_delim[(unsigned)(unsigned char)'\n'] = TERMINATOR;
100
101
102    /* Parse string */
103
104    /* Skip leading separators. XXX: Why do they matter? */
105    while (is_delim[(unsigned)(unsigned char)*str] == SEPARATOR)
106    {
107       str++;
108    }
109
110    /* The first pointer is the beginning of string */
111    if (is_delim[(unsigned)(unsigned char)*str] == WANTED)
112    {
113       /*
114        * The first character in this field is not a
115        * delimiter or the end of string, so save it.
116        */
117       if (vec_count >= vec_len)
118       {
119          return(-1); /* overflow */
120       }
121       vec[vec_count++] = str;
122    }
123
124    while ((char_type = is_delim[(unsigned)(unsigned char)*str]) != TERMINATOR)
125    {
126       if (char_type == SEPARATOR)
127       {
128          /* the char is a separator */
129
130          /* null terminate the substring */
131          *str++ = '\0';
132
133          /* Check if we want to save this field */
134          if (is_delim[(unsigned)(unsigned char)*str] == WANTED)
135          {
136             /*
137              * The first character in this field is not a
138              * delimiter or the end of string. So save it.
139              */
140             if (vec_count >= vec_len)
141             {
142                return(-1); /* overflow */
143             }
144             vec[vec_count++] = str;
145          }
146       }
147       else
148       {
149          str++;
150       }
151    }
152    /* null terminate the substring */
153    /* XXX: this shouldn't be necessary, so assert that it isn't. */
154    assert(*str == '\0');
155    *str = '\0';
156
157    return(vec_count);
158 }
159
160
161 /*
162   Local Variables:
163   tab-width: 3
164   end:
165 */