mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-20 14:37:08 +01:00
common: Add function strtokenize.
* common/stringhelp.c: Include assert.h. (strtokenize): New. * common/t-stringhelp.c (test_strtokenize): New. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
e0873a3372
commit
d37f47081d
@ -48,6 +48,7 @@
|
|||||||
# endif
|
# endif
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "common-defs.h"
|
#include "common-defs.h"
|
||||||
@ -1234,3 +1235,69 @@ strsplit (char *string, char delim, char replacement, int *count)
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Tokenize STRING using the set of delimiters in DELIM. Leading
|
||||||
|
* spaces and tabs are removed from all tokens. The caller must xfree
|
||||||
|
* the result.
|
||||||
|
*
|
||||||
|
* Returns: A malloced and NULL delimited array with the tokens. On
|
||||||
|
* memory error NULL is returned and ERRNO is set.
|
||||||
|
*/
|
||||||
|
char **
|
||||||
|
strtokenize (const char *string, const char *delim)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
size_t fields;
|
||||||
|
size_t bytes, n;
|
||||||
|
char *buffer;
|
||||||
|
char *p, *px, *pend;
|
||||||
|
char **result;
|
||||||
|
|
||||||
|
/* Count the number of fields. */
|
||||||
|
for (fields = 1, s = strpbrk (string, delim); s; s = strpbrk (s + 1, delim))
|
||||||
|
fields++;
|
||||||
|
fields++; /* Add one for the terminating NULL. */
|
||||||
|
|
||||||
|
/* Allocate an array for all fields, a terminating NULL, and space
|
||||||
|
for a copy of the string. */
|
||||||
|
bytes = fields * sizeof *result;
|
||||||
|
if (bytes / sizeof *result != fields)
|
||||||
|
{
|
||||||
|
gpg_err_set_errno (ENOMEM);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
n = strlen (string) + 1;
|
||||||
|
bytes += n;
|
||||||
|
if (bytes < n)
|
||||||
|
{
|
||||||
|
gpg_err_set_errno (ENOMEM);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
result = xtrymalloc (bytes);
|
||||||
|
if (!result)
|
||||||
|
return NULL;
|
||||||
|
buffer = (char*)(result + fields);
|
||||||
|
|
||||||
|
/* Copy and parse the string. */
|
||||||
|
strcpy (buffer, string);
|
||||||
|
for (n = 0, p = buffer; (pend = strpbrk (p, delim)); p = pend + 1)
|
||||||
|
{
|
||||||
|
*pend = 0;
|
||||||
|
while (spacep (p))
|
||||||
|
p++;
|
||||||
|
for (px = pend - 1; px >= p && spacep (px); px--)
|
||||||
|
*px = 0;
|
||||||
|
result[n++] = p;
|
||||||
|
}
|
||||||
|
while (spacep (p))
|
||||||
|
p++;
|
||||||
|
for (px = p + strlen (p) - 1; px >= p && spacep (px); px--)
|
||||||
|
*px = 0;
|
||||||
|
result[n++] = p;
|
||||||
|
result[n] = NULL;
|
||||||
|
|
||||||
|
assert ((char*)(result + n + 1) == buffer);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -145,6 +145,10 @@ char *xstrconcat (const char *s1, ...) GNUPG_GCC_A_SENTINEL(0);
|
|||||||
|
|
||||||
char **strsplit (char *string, char delim, char replacement, int *count);
|
char **strsplit (char *string, char delim, char replacement, int *count);
|
||||||
|
|
||||||
|
/* Tokenize STRING using the set of delimiters in DELIM. */
|
||||||
|
char **strtokenize (const char *string, const char *delim);
|
||||||
|
|
||||||
|
|
||||||
/*-- mapstrings.c --*/
|
/*-- mapstrings.c --*/
|
||||||
const char *map_static_macro_string (const char *string);
|
const char *map_static_macro_string (const char *string);
|
||||||
|
|
||||||
|
@ -538,6 +538,146 @@ test_strsplit (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_strtokenize (void)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
const char *s;
|
||||||
|
const char *delim;
|
||||||
|
const char *fields_expected[10];
|
||||||
|
} tv[] = {
|
||||||
|
{
|
||||||
|
"", ":",
|
||||||
|
{ "", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a", ":",
|
||||||
|
{ "a", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
":", ":",
|
||||||
|
{ "", "", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"::", ":",
|
||||||
|
{ "", "", "", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:b:c", ":",
|
||||||
|
{ "a", "b", "c", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:b:", ":",
|
||||||
|
{ "a", "b", "", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:b", ":",
|
||||||
|
{ "a", "b", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"aa:b:cd", ":",
|
||||||
|
{ "aa", "b", "cd", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"aa::b:cd", ":",
|
||||||
|
{ "aa", "", "b", "cd", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"::b:cd", ":",
|
||||||
|
{ "", "", "b", "cd", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"aa: : b:cd ", ":",
|
||||||
|
{ "aa", "", "b", "cd", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
" aa: : b: cd ", ":",
|
||||||
|
{ "aa", "", "b", "cd", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
" ", ":",
|
||||||
|
{ "", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
" :", ":",
|
||||||
|
{ "", "", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
" : ", ":",
|
||||||
|
{ "", "", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
": ", ":",
|
||||||
|
{ "", "", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
": x ", ":",
|
||||||
|
{ "", "x", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:bc:cde:fghi:jklmn::foo:", ":",
|
||||||
|
{ "a", "bc", "cde", "fghi", "jklmn", "", "foo", "", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
",a,bc,,def,", ",",
|
||||||
|
{ "", "a", "bc", "", "def", "", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
" a ", " ",
|
||||||
|
{ "", "a", "", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
" ", " ",
|
||||||
|
{ "", "", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"", " ",
|
||||||
|
{ "", NULL }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int tidx;
|
||||||
|
|
||||||
|
for (tidx = 0; tidx < DIM(tv); tidx++)
|
||||||
|
{
|
||||||
|
char **fields;
|
||||||
|
int field_count;
|
||||||
|
int field_count_expected;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (field_count_expected = 0;
|
||||||
|
tv[tidx].fields_expected[field_count_expected];
|
||||||
|
field_count_expected ++)
|
||||||
|
;
|
||||||
|
|
||||||
|
fields = strtokenize (tv[tidx].s, tv[tidx].delim);
|
||||||
|
if (!fields)
|
||||||
|
fail (tidx * 1000);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (field_count = 0; fields[field_count]; field_count++)
|
||||||
|
;
|
||||||
|
if (field_count != field_count_expected)
|
||||||
|
fail (tidx * 1000);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < field_count_expected; i++)
|
||||||
|
if (strcmp (tv[tidx].fields_expected[i], fields[i]))
|
||||||
|
{
|
||||||
|
printf ("For field %d, expected '%s', but got '%s'\n",
|
||||||
|
i, tv[tidx].fields_expected[i], fields[i]);
|
||||||
|
fail (tidx * 1000 + i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree (fields);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -551,6 +691,7 @@ main (int argc, char **argv)
|
|||||||
test_make_filename_try ();
|
test_make_filename_try ();
|
||||||
test_make_absfilename_try ();
|
test_make_absfilename_try ();
|
||||||
test_strsplit ();
|
test_strsplit ();
|
||||||
|
test_strtokenize ();
|
||||||
|
|
||||||
xfree (home_buffer);
|
xfree (home_buffer);
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user