From 4e134b6e77f558730ec1eceb6b816b0bcfd845e9 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 18 Feb 2016 15:37:32 +0100 Subject: Add helper function _gcry_strtokenize. * src/misc.c (_gcry_strtokenize): New. -- The code has been taken from GnuPG and re-licensed to LPGLv2+ by me as its original author. Minor changes for use in Libgcrypt. Signed-off-by: Werner Koch --- src/g10lib.h | 3 +++ src/misc.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/src/g10lib.h b/src/g10lib.h index a579e945..9d2ece9c 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -189,6 +189,9 @@ int _gcry_log_verbosity( int level ); /* Compatibility macro. */ #define log_mpidump _gcry_log_printmpi +/* Tokeninze STRING and return a malloced array. */ +char **_gcry_strtokenize (const char *string, const char *delim); + /*-- src/hwfeatures.c --*/ /* (Do not change these values unless synced with the asm code.) */ diff --git a/src/misc.c b/src/misc.c index b3c56e29..ac64d703 100644 --- a/src/misc.c +++ b/src/misc.c @@ -436,6 +436,79 @@ _gcry_log_printsxp (const char *text, gcry_sexp_t sexp) } +/* + * Tokenize STRING using the set of delimiters in DELIM. Leading + * white spaces 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 ** +_gcry_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; + char const ws[] = " \t\v\f\r\n"; + + if (!delim) + delim = ws; + + /* 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 (strchr (ws, *(byte*)p)) + p++; + for (px = pend - 1; px >= p && strchr (ws, *(byte*)px); px--) + *px = 0; + result[n++] = p; + } + while (*p && strchr (ws, *(byte*)p)) + p++; + for (px = p + strlen (p) - 1; px >= p && strchr (ws, *(byte*)px); px--) + *px = 0; + /* Traling spaces may result in an empty field. We do not want to + store that. */ + result[n++] = *p? p : NULL; + result[n] = NULL; + + gcry_assert ((char*)(result + n + 1) == buffer); + + return result; +} + + void __gcry_burn_stack (unsigned int bytes) { -- cgit v1.2.1