uagen: Bump version
[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
40 #include "ssplit.h"
41 #include "miscutil.h"
42
43
44 /*********************************************************************
45  *
46  * Function    :  ssplit
47  *
48  * Description :  Split a string using delimiters in `delim'.  Results
49  *                go into `vec'.
50  *
51  * Parameters  :
52  *          1  :  str = string to split.  Will be split in place
53  *                (i.e. do not free until you've finished with vec,
54  *                previous contents will be trashed by the call).
55  *          2  :  delim = array of delimiters (if NULL, uses " \t").
56  *          3  :  vec[] = results vector (aka. array) [out]
57  *          4  :  vec_len = number of usable slots in the vector (aka. array size)
58  *
59  * Returns     :  -1 => Error: vec_len is too small to hold all the
60  *                      data, or str == NULL.
61  *                >=0 => the number of fields put in `vec'.
62  *                On error, vec and str may still have been overwritten.
63  *
64  *********************************************************************/
65 int ssplit(char *str, const char *delim, char *vec[], size_t vec_len)
66 {
67    unsigned char is_delim[256];
68    unsigned char char_type;
69    int vec_count = 0;
70    enum char_type {
71       WANTED     = 0,
72       SEPARATOR  = 1,
73       TERMINATOR = 2,
74    };
75
76
77    if (!str)
78    {
79       return(-1);
80    }
81
82
83    /* Build is_delim array */
84
85    memset(is_delim, '\0', sizeof(is_delim));
86
87    if (!delim)
88    {
89       delim = " \t";  /* default field separators */
90    }
91
92    while (*delim)
93    {
94       is_delim[(unsigned)(unsigned char)*delim++] = SEPARATOR;
95    }
96
97    is_delim[(unsigned)(unsigned char)'\0'] = TERMINATOR;
98    is_delim[(unsigned)(unsigned char)'\n'] = TERMINATOR;
99
100
101    /* Parse string */
102
103    /* Skip leading separators. XXX: Why do they matter? */
104    while (is_delim[(unsigned)(unsigned char)*str] == SEPARATOR)
105    {
106       str++;
107    }
108
109    /* The first pointer is the beginning of string */
110    if (is_delim[(unsigned)(unsigned char)*str] == WANTED)
111    {
112       /*
113        * The first character in this field is not a
114        * delimiter or the end of string, so save it.
115        */
116       if (vec_count >= vec_len)
117       {
118          return(-1); /* overflow */
119       }
120       vec[vec_count++] = str;
121    }
122
123    while ((char_type = is_delim[(unsigned)(unsigned char)*str]) != TERMINATOR)
124    {
125       if (char_type == SEPARATOR)
126       {
127          /* the char is a separator */
128
129          /* null terminate the substring */
130          *str++ = '\0';
131
132          /* Check if we want to save this field */
133          if (is_delim[(unsigned)(unsigned char)*str] == WANTED)
134          {
135             /*
136              * The first character in this field is not a
137              * delimiter or the end of string. So save it.
138              */
139             if (vec_count >= vec_len)
140             {
141                return(-1); /* overflow */
142             }
143             vec[vec_count++] = str;
144          }
145       }
146       else
147       {
148          str++;
149       }
150    }
151    /* null terminate the substring */
152    *str = '\0';
153
154    return(vec_count);
155 }
156
157
158 /*
159   Local Variables:
160   tab-width: 3
161   end:
162 */