From: jongfoster Date: Tue, 29 May 2001 08:54:25 +0000 (+0000) Subject: Rewrote the innards of ssplit() to be easier to understand, X-Git-Tag: v_2_9_9~466 X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=commitdiff_plain;h=e52df6067c712756134c5589332cc0a6936fa6f0 Rewrote the innards of ssplit() to be easier to understand, faster, and to use less memory. Didn't change the interface except to give the parameters meaningful names. --- diff --git a/ssplit.c b/ssplit.c index 6dcde3aa..c0315bcf 100644 --- a/ssplit.c +++ b/ssplit.c @@ -1,4 +1,4 @@ -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.2 2001/05/17 23:01:01 oes Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/ssplit.c,v $ @@ -32,6 +32,9 @@ const char ssplit_rcs[] = "$Id: ssplit.c,v 1.1.1.1 2001/05/15 13:59:04 oes Exp $ * * Revisions : * $Log: ssplit.c,v $ + * Revision 1.2 2001/05/17 23:01:01 oes + * - Cleaned CRLF's from the sources and related files + * * Revision 1.1.1.1 2001/05/15 13:59:04 oes * Initial import of version 2.9.3 source tree * @@ -54,180 +57,139 @@ const char ssplit_rcs[] = "$Id: ssplit.c,v 1.1.1.1 2001/05/15 13:59:04 oes Exp $ 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 - * - * Description : Debugging routine to spit info on stdout. Not very - * useful to the non-console based IJB compiles. - * - * Parameters : - * 1 : v = an array of strings - * 2 : n = number of strings in `v' to dump to stdout - * - * Returns : N/A - * - *********************************************************************/ -static void print(char **v, int n) -{ - 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 */ +#undef SSPLIT_VERBOSE +/* #define SSPLIT_VERBOSE 1 */ /********************************************************************* * * Function : ssplit * - * Description : Split a string using deliminters in `c'. Results go - * into `v'. + * Description : Split a string using delimiters in `delim'. Results + * go into `vec'. * * 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'. + * 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) + * 5 : dont_save_empty_fields = zero if consecutive delimiters + * give a null output field(s), nonzero if they are just + * to be considered as single delimeter + * 6 : ignore_leading = nonzero to ignore leading field + * separators. + * + * 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. * *********************************************************************/ -int ssplit(char *s, char *c, char *v[], int n, int m, int l) +int ssplit(char *str, const char *delim, char *vec[], int vec_len, + int dont_save_empty_fields, int ignore_leading) { - 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) + unsigned char is_delim[256]; + unsigned char char_type; + int vec_count = 0; + + if (!str) { return(-1); } - memset(t, '\0', sizeof(t)); - p = (unsigned char *) c; + /* Build is_delim array */ - if (!p) + memset(is_delim, '\0', sizeof(is_delim)); + + if (!delim) { - p = (unsigned char *) " \t"; /* default field separators */ + delim = " \t"; /* default field separators */ } - while (*p) + while (*delim) { - t[*p++] = 1; /* separator */ + is_delim[(unsigned)(unsigned char)*delim++] = 1; /* separator */ } - t['\0'] = 2; /* terminator */ - t['\n'] = 2; /* terminator */ + is_delim[(unsigned)(unsigned char)'\0'] = 2; /* terminator */ + is_delim[(unsigned)(unsigned char)'\n'] = 2; /* terminator */ + - p = (unsigned char *) s; + /* Parse string */ - if (l)/* are we to skip leading separators ? */ + if (ignore_leading) { - while ((b = t[*p]) != 2) + /* skip leading separators */ + while (is_delim[(unsigned)(unsigned char)*str] == 1) { - if (b != 1) - { - break; - } - p++; + str++; } } - xsize = 256; - - x = (char **) zalloc((xsize) * sizeof(char *)); - - x[xi++] = (char *) p; /* first pointer is the beginning of string */ + /* first pointer is the beginning of string */ + /* Check if we want to save this field */ + if ( (!dont_save_empty_fields) + || (is_delim[(unsigned)(unsigned char)*str] == 0) ) + { + /* + * We want empty fields, or 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++] = (char *) str; + } - /* first pass: save pointers to the field separators */ - while ((b = t[*p]) != 2) + while ((char_type = is_delim[(unsigned)(unsigned char)*str]) != 2) { - if (b == 1) /* if the char is a separator ... */ + if (char_type == 1) { - *p++ = '\0'; /* null terminate the substring */ + /* the char is a separator */ - if (xi == xsize) - { - /* get another chunk */ - int new_xsize = xsize + 256; - char **new_x = (char **)zalloc((new_xsize) * sizeof(char *)); + /* null terminate the substring */ + *str++ = '\0'; - for (i=0; i < xsize; i++) + /* Check if we want to save this field */ + if ( (!dont_save_empty_fields) + || (is_delim[(unsigned)(unsigned char)*str] == 0) ) + { + /* + * We want empty fields, or the first character in this + * field is not a delimiter or the end of string. + * So save it. + */ + if (vec_count >= vec_len) { - new_x[i] = x[i]; + return(-1); /* overflow */ } - - free(x); - xsize = new_xsize; - x = new_x; + vec[vec_count++] = (char *) str; } - x[xi++] = (char *) p; /* save pointer to beginning of next string */ } else { - p++; + str++; } } - *p = '\0'; /* null terminate the substring */ - + *str = '\0'; /* null terminate the substring */ #ifdef SSPLIT_VERBOSE - if (DEBUG(HDR)) - { - print(x, xi); /* debugging */ - } -#endif /* def SSPLIT_VERBOSE */ - - - /* second pass: copy the relevant pointers to the output vector */ - last_was_null = 0; - for (i=0 ; i < xi; i++) { - if (m) + int i; + printf("dump %d strings\n", vec_count); + for (i = 0; i < vec_count; i++) { - /* there are NO null fields */ - if (*x[i] == 0) - { - continue; - } - } - if (vi < n) - { - v[vi++] = x[i]; - } - else - { - free(x); - return(-1); /* overflow */ + printf("%d '%s'\n", i, vec[i]); } } - free(x); - -#ifdef SSPLIT_VERBOSE - if (DEBUG(HDR)) - { - print(v, vi); /* debugging */ - } #endif /* def SSPLIT_VERBOSE */ - return(vi); - + return(vec_count); } diff --git a/ssplit.h b/ssplit.h index 39bd9934..757a98e2 100644 --- a/ssplit.h +++ b/ssplit.h @@ -1,9 +1,9 @@ #ifndef _SSPLIT_H #define _SSPLIT_H -#define SSPLIT_H_VERSION "$Id: ssplit.h,v 1.1 2001/05/13 21:57:07 administrator Exp $" +#define SSPLIT_H_VERSION "$Id: ssplit.h,v 1.1.1.1 2001/05/15 13:59:04 oes Exp $" /********************************************************************* * - * File : $Source: /home/administrator/cvs/ijb/ssplit.h,v $ + * File : $Source: /cvsroot/ijbswa/current/ssplit.h,v $ * * Purpose : A function to split a string at specified deliminters. * @@ -34,6 +34,9 @@ * * Revisions : * $Log: ssplit.h,v $ + * Revision 1.1.1.1 2001/05/15 13:59:04 oes + * Initial import of version 2.9.3 source tree + * * *********************************************************************/ @@ -42,7 +45,8 @@ extern "C" { #endif -extern int ssplit(char *s, char *c, char *v[], int n, int m, int l); +extern int ssplit(char *str, const char *delim, char *vec[], int vec_len, + int dont_save_empty_fields, int ignore_leading); /* Revision control strings from this header and associated .c file */ extern const char ssplit_rcs[];