From cfb1b8ff4632b51bec4e5eab18137081efdfb02d Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Fri, 5 Aug 2011 16:24:08 +0200 Subject: [PATCH] New utility: nmem_strsplit_escape --- include/yaz/nmem.h | 15 +++++++++++++ src/nmemsdup.c | 63 +++++++++++++++++++++++++--------------------------- test/test_nmem.c | 26 ++++++++++++++++++++++ 3 files changed, 71 insertions(+), 33 deletions(-) diff --git a/include/yaz/nmem.h b/include/yaz/nmem.h index c12ddc0..192f362 100644 --- a/include/yaz/nmem.h +++ b/include/yaz/nmem.h @@ -134,6 +134,21 @@ YAZ_EXPORT void nmem_strsplitx(NMEM nmem, const char *delim, YAZ_EXPORT void nmem_strsplit_blank(NMEM nmem, const char *dstr, char ***darray, int *num); + +/** \brief allocates sub strings out of string using certain delimitors + \param nmem NMEM handle + \param delim delimitor chars (splits on each char in there) + \param dstr string to be split + \param darray result string array for each sub string + \param num number of result strings + \param collapse 1=collapse multiple delims to one; 0=no collapse + \param escape_char != 0, an escape char (could be \) +*/ +YAZ_EXPORT void nmem_strsplit_escape(NMEM nmem, const char *delim, + const char *dstr, + char ***darray, int *num, int collapse, + int escape_char); + /** \brief allocates and sets integer for NMEM \param nmem NMEM handle \param v integer value diff --git a/src/nmemsdup.c b/src/nmemsdup.c index f697e73..fcfb074 100644 --- a/src/nmemsdup.c +++ b/src/nmemsdup.c @@ -67,40 +67,19 @@ void nmem_strsplit(NMEM nmem, const char *delim, const char *dstr, void nmem_strsplitx(NMEM nmem, const char *delim, const char *dstr, char ***darray, int *num, int collapse) { - const char *cp = dstr; - *num = 0; + nmem_strsplit_escape(nmem, delim, dstr, darray, num, collapse, 0); +} +void nmem_strsplit_escape(NMEM nmem, const char *delim, const char *dstr, + char ***darray, int *num, int collapse, + int escape_char) +{ + *darray = 0; + /* two passes over the input string.. */ while (1) { - if (collapse) - { - if (!*cp) - break; - while (*cp && strchr(delim, *cp)) - cp++; - if (!*cp) - break; - while (*cp && !strchr(delim, *cp)) - cp++; - (*num)++; - } - else - { - (*num)++; - while (*cp && !strchr(delim, *cp)) - cp++; - if (!*cp) - break; - cp++; - } - } - if (!*num) - *darray = 0; - else - { size_t i = 0; - *darray = (char **) nmem_malloc(nmem, *num * sizeof(**darray)); - cp = dstr; + const char *cp = dstr; while (1) { const char *cp0; @@ -108,26 +87,44 @@ void nmem_strsplitx(NMEM nmem, const char *delim, const char *dstr, { if (!*cp) break; - while (*cp && strchr(delim, *cp)) + while (*cp && strchr(delim, *cp) && *cp != escape_char) cp++; if (!*cp) break; cp0 = cp; while (*cp && !strchr(delim, *cp)) + { + if (*cp == escape_char) + cp++; cp++; - (*darray)[i++] = nmem_strdupn(nmem, cp0, cp - cp0); + } + if (*darray) + (*darray)[i] = nmem_strdupn(nmem, cp0, cp - cp0); + i++; } else { cp0 = cp; while (*cp && !strchr(delim, *cp)) + { + if (*cp == escape_char) + cp++; cp++; - (*darray)[i++] = nmem_strdupn(nmem, cp0, cp - cp0); + } + if (*darray) + (*darray)[i] = nmem_strdupn(nmem, cp0, cp - cp0); + i++; if (!*cp) break; cp++; } } + *num = i; + if (!*num) + break; /* no items, so stop, *darray=0 already */ + else if (*darray) + break; /* second pass, stop */ + *darray = (char **) nmem_malloc(nmem, *num * sizeof(**darray)); } } diff --git a/test/test_nmem.c b/test/test_nmem.c index 027b823..cc34f27 100644 --- a/test/test_nmem.c +++ b/test/test_nmem.c @@ -72,8 +72,16 @@ void tst_nmem_strsplit(void) YAZ_CHECK(num > 0 && !strcmp(array[0], "a")); YAZ_CHECK(num > 1 && !strcmp(array[1], "b")); YAZ_CHECK(num > 2 && !strcmp(array[2], "cd")); + nmem_strsplitx(nmem, ",", ",a,b,,cd", &array, &num, 0); + YAZ_CHECK(num == 5); + YAZ_CHECK(num > 0 && !strcmp(array[0], "")); + YAZ_CHECK(num > 1 && !strcmp(array[1], "a")); + YAZ_CHECK(num > 2 && !strcmp(array[2], "b")); + YAZ_CHECK(num > 3 && !strcmp(array[3], "")); + YAZ_CHECK(num > 4 && !strcmp(array[4], "cd")); + nmem_strsplit_escape(nmem, ",", ",a,b,,cd", &array, &num, 0, '\\'); YAZ_CHECK(num == 5); YAZ_CHECK(num > 0 && !strcmp(array[0], "")); YAZ_CHECK(num > 1 && !strcmp(array[1], "a")); @@ -81,6 +89,24 @@ void tst_nmem_strsplit(void) YAZ_CHECK(num > 3 && !strcmp(array[3], "")); YAZ_CHECK(num > 4 && !strcmp(array[4], "cd")); + nmem_strsplit_escape(nmem, ",", ",a,b\\,,cd", &array, &num, 0, '\\'); + YAZ_CHECK(num == 4); + YAZ_CHECK(num > 0 && !strcmp(array[0], "")); + YAZ_CHECK(num > 1 && !strcmp(array[1], "a")); + YAZ_CHECK(num > 2 && !strcmp(array[2], "b\\,")); + YAZ_CHECK(num > 3 && !strcmp(array[3], "cd")); + + nmem_strsplit_escape(nmem, ",", "\\,a,b\\,,cd", &array, &num, 0, '\\'); + YAZ_CHECK(num == 3); + YAZ_CHECK(num > 0 && !strcmp(array[0], "\\,a")); + YAZ_CHECK(num > 1 && !strcmp(array[1], "b\\,")); + YAZ_CHECK(num > 2 && !strcmp(array[2], "cd")); + + nmem_strsplit_escape(nmem, ",", "\\,a,b\\,\\,cd", &array, &num, 0, '\\'); + YAZ_CHECK(num == 2); + YAZ_CHECK(num > 0 && !strcmp(array[0], "\\,a")); + YAZ_CHECK(num > 1 && !strcmp(array[1], "b\\,\\,cd")); + nmem_destroy(nmem); } -- 1.7.10.4