Rebuild with utf-8 encoding
[privoxy.git] / ssplit.c
index 6dcde3a..0161898 100644 (file)
--- a/ssplit.c
+++ b/ssplit.c
@@ -1,18 +1,18 @@
-const char ssplit_rcs[] = "$Id: ssplit.c,v 1.1.1.1 2001/05/15 13:59:04 oes Exp $";
+const char ssplit_rcs[] = "$Id: ssplit.c,v 1.19 2012/07/23 12:46:40 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/ssplit.c,v $
  *
- * Purpose     :  A function to split a string at specified deliminters.
+ * Purpose     :  A function to split a string at specified delimiters.
  *
- * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
- *                IJBSWA team.  http://ijbswa.sourceforge.net
+ * Copyright   :  Written by and Copyright (C) 2001-2012 the
+ *                Privoxy team. http://www.privoxy.org/
  *
  *                Based on the Internet Junkbuster originally written
- *                by and Copyright (C) 1997 Anonymous Coders and 
+ *                by and Copyright (C) 1997 Anonymous Coders and
  *                Junkbusters Corporation.  http://www.junkbusters.com
  *
- *                This program is free software; you can redistribute it 
+ *                This program is free software; you can redistribute it
  *                and/or modify it under the terms of the GNU General
  *                Public License as published by the Free Software
  *                Foundation; either version 2 of the License, or (at
@@ -30,204 +30,134 @@ const char ssplit_rcs[] = "$Id: ssplit.c,v 1.1.1.1 2001/05/15 13:59:04 oes Exp $
  *                or write to the Free Software Foundation, Inc., 59
  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
- * Revisions   :
- *    $Log: ssplit.c,v $
- *    Revision 1.1.1.1  2001/05/15 13:59:04  oes
- *    Initial import of version 2.9.3 source tree
- *
- *
  *********************************************************************/
-\f
+
 
 #include "config.h"
 
 #include <string.h>
 #include <stdlib.h>
-
-#ifdef _WIN32
-#include <malloc.h>
-#endif
+#include <assert.h>
 
 #include "ssplit.h"
 #include "miscutil.h"
 
 const char ssplit_h_rcs[] = SSPLIT_H_VERSION;
 
-/* Define this for lots of debugging information to stdout */
-/* #define SSPLIT_VERBOSE */
 
-#ifdef SSPLIT_VERBOSE
 /*********************************************************************
  *
- * Function    :  print
+ * Function    :  ssplit
  *
- * Description :  Debugging routine to spit info on stdout.  Not very
- *                useful to the non-console based IJB compiles.
+ * Description :  Split a string using delimiters in `delim'.  Results
+ *                go into `vec'.
  *
  * Parameters  :
- *          1  :  v = an array of strings
- *          2  :  n = number of strings in `v' to dump to stdout
- *
- * Returns     :  N/A
+ *          1  :  str = string to split.  Will be split in place
+ *                (i.e. do not free until you've finished with vec,
+ *                previous contents will be trashed by the call).
+ *          2  :  delim = array of delimiters (if NULL, uses " \t").
+ *          3  :  vec[] = results vector (aka. array) [out]
+ *          4  :  vec_len = number of usable slots in the vector (aka. array size)
+ *
+ * Returns     :  -1 => Error: vec_len is too small to hold all the
+ *                      data, or str == NULL.
+ *                >=0 => the number of fields put in `vec'.
+ *                On error, vec and str may still have been overwritten.
  *
  *********************************************************************/
-static void print(char **v, int n)
+int ssplit(char *str, const char *delim, char *vec[], size_t vec_len)
 {
-   int i;
-   printf("dump %d strings\n", n);
-   for (i=0; i < n; i++)
-   {
-      printf("%d '%s'\n", i, v[i]);
-   }
-
-}
-#endif /* def SSPLIT_VERBOSE */
+   unsigned char is_delim[256];
+   unsigned char char_type;
+   int vec_count = 0;
+   enum char_type {
+      WANTED     = 0,
+      SEPARATOR  = 1,
+      TERMINATOR = 2,
+   };
 
 
-/*********************************************************************
- *
- * Function    :  ssplit
- *
- * Description :  Split a string using deliminters in `c'.  Results go
- *                into `v'.
- *
- * Parameters  :
- *          1  :  s = string to split
- *          2  :  c = array of delimiters
- *          3  :  v[] = results vector (aka. array)
- *          4  :  n = number of usable slots in the vector (aka. array size)
- *          5  :  m = consecutive delimiters means multiple fields?
- *          6  :  l = ignore leading field separators?
- *
- * Returns     :  -1 => failure, else the number of fields put in `v'.
- *
- *********************************************************************/
-int ssplit(char *s, char *c, char *v[], int n, int m, int l)
-{
-   char t[256];
-   char **x = NULL;
-   int xsize = 0;
-   unsigned char *p, b;
-   int xi = 0;
-   int vi = 0;
-   int i;
-   int last_was_null;
-
-   if (!s)
+   if (!str)
    {
       return(-1);
    }
 
-   memset(t, '\0', sizeof(t));
 
-   p = (unsigned char *) c;
+   /* Build is_delim array */
 
-   if (!p)
-   {
-      p = (unsigned char *) " \t";  /* default field separators */
-   }
+   memset(is_delim, '\0', sizeof(is_delim));
 
-   while (*p)
+   if (!delim)
    {
-      t[*p++] = 1;   /* separator  */
+      delim = " \t";  /* default field separators */
    }
 
-   t['\0'] = 2;   /* terminator */
-   t['\n'] = 2;   /* terminator */
-
-   p = (unsigned char *) s;
-
-   if (l)/* are we to skip leading separators ? */
+   while (*delim)
    {
-      while ((b = t[*p]) != 2)
-      {
-         if (b != 1)
-         {
-            break;
-         }
-         p++;
-      }
+      is_delim[(unsigned)(unsigned char)*delim++] = SEPARATOR;
    }
 
-   xsize = 256;
+   is_delim[(unsigned)(unsigned char)'\0'] = TERMINATOR;
+   is_delim[(unsigned)(unsigned char)'\n'] = TERMINATOR;
 
-   x = (char **) zalloc((xsize) * sizeof(char *));
 
-   x[xi++] = (char *) p;   /* first pointer is the beginning of string */
+   /* Parse string */
 
-   /* first pass:  save pointers to the field separators */
-   while ((b = t[*p]) != 2)
+   /* Skip leading separators. XXX: Why do they matter? */
+   while (is_delim[(unsigned)(unsigned char)*str] == SEPARATOR)
    {
-      if (b == 1)    /* if the char is a separator ... */
-      {
-         *p++ = '\0';      /* null terminate the substring */
-
-         if (xi == xsize)
-         {
-            /* get another chunk */
-            int new_xsize = xsize + 256;
-            char **new_x = (char **)zalloc((new_xsize) * sizeof(char *));
-
-            for (i=0; i < xsize; i++)
-            {
-               new_x[i] = x[i];
-            }
+      str++;
+   }
 
-            free(x);
-            xsize = new_xsize;
-            x     = new_x;
-         }
-         x[xi++] = (char *) p;   /* save pointer to beginning of next string */
-      }
-      else
+   /* The first pointer is the beginning of string */
+   if (is_delim[(unsigned)(unsigned char)*str] == WANTED)
+   {
+      /*
+       * The first character in this field is not a
+       * delimiter or the end of string, so save it.
+       */
+      if (vec_count >= vec_len)
       {
-         p++;
+         return(-1); /* overflow */
       }
+      vec[vec_count++] = str;
    }
-   *p = '\0';     /* null terminate the substring */
-
 
-#ifdef SSPLIT_VERBOSE
-   if (DEBUG(HDR))
+   while ((char_type = is_delim[(unsigned)(unsigned char)*str]) != TERMINATOR)
    {
-      print(x, xi); /* debugging */
-   }
-#endif /* def SSPLIT_VERBOSE */
+      if (char_type == SEPARATOR)
+      {
+         /* the char is a separator */
 
+         /* null terminate the substring */
+         *str++ = '\0';
 
-   /* second pass: copy the relevant pointers to the output vector */
-   last_was_null = 0;
-   for (i=0 ; i < xi; i++)
-   {
-      if (m)
-      {
-         /* there are NO null fields */
-         if (*x[i] == 0)
+         /* Check if we want to save this field */
+         if (is_delim[(unsigned)(unsigned char)*str] == WANTED)
          {
-            continue;
+            /*
+             * The first character in this field is not a
+             * delimiter or the end of string. So save it.
+             */
+            if (vec_count >= vec_len)
+            {
+               return(-1); /* overflow */
+            }
+            vec[vec_count++] = str;
          }
       }
-      if (vi < n)
-      {
-         v[vi++] = x[i];
-      }
       else
       {
-         free(x);
-         return(-1); /* overflow */
+         str++;
       }
    }
-   free(x);
-
-#ifdef SSPLIT_VERBOSE
-   if (DEBUG(HDR))
-   {
-      print(v, vi); /* debugging  */
-   }
-#endif /* def SSPLIT_VERBOSE */
-
-   return(vi);
+   /* null terminate the substring */
+   /* XXX: this shouldn't be necessary, so assert that it isn't. */
+   assert(*str == '\0');
+   *str = '\0';
 
+   return(vec_count);
 }