From d6034263894fbc9e0d10571bc0b3abab262005f6 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Thu, 9 Apr 2020 09:59:39 +0200 Subject: [PATCH] util: add function to split string into words --- test/unit/util.c | 35 ++++++++++++++++++++++++++++++++++- util.c | 30 ++++++++++++++++++++++++++++++ util.h | 5 +++++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/test/unit/util.c b/test/unit/util.c index 824f3a8..e597d97 100644 --- a/test/unit/util.c +++ b/test/unit/util.c @@ -30,7 +30,7 @@ void test_unit(void) { Timespec tspec; Float f; int i, j, c; - char buf[16], *s; + char buf[16], *s, *words[3]; uid_t uid; gid_t gid; struct stat st; @@ -333,4 +333,37 @@ void test_unit(void) { TEST_CHECK(UTI_BytesToHex("\xAB\x12\x34\x56\x78\x00\x01", 7, buf, 14) == 0); TEST_CHECK(UTI_BytesToHex("\xAB\x12\x34\x56\x78\x00\x01", 7, buf, 15) == 1); TEST_CHECK(strcmp(buf, "AB123456780001") == 0); + + TEST_CHECK(snprintf(buf, sizeof (buf), "%s", "") < sizeof (buf)); + TEST_CHECK(UTI_SplitString(buf, words, 3) == 0); + TEST_CHECK(!words[0]); + TEST_CHECK(snprintf(buf, sizeof (buf), "%s", " ") < sizeof (buf)); + TEST_CHECK(UTI_SplitString(buf, words, 3) == 0); + TEST_CHECK(!words[0]); + TEST_CHECK(snprintf(buf, sizeof (buf), "%s", "a \n ") < sizeof (buf)); + TEST_CHECK(UTI_SplitString(buf, words, 3) == 1); + TEST_CHECK(words[0] == buf + 0); + TEST_CHECK(strcmp(words[0], "a") == 0); + TEST_CHECK(snprintf(buf, sizeof (buf), "%s", " a ") < sizeof (buf)); + TEST_CHECK(UTI_SplitString(buf, words, 3) == 1); + TEST_CHECK(words[0] == buf + 2); + TEST_CHECK(strcmp(words[0], "a") == 0); + TEST_CHECK(snprintf(buf, sizeof (buf), "%s", " \n a") < sizeof (buf)); + TEST_CHECK(UTI_SplitString(buf, words, 3) == 1); + TEST_CHECK(words[0] == buf + 4); + TEST_CHECK(strcmp(words[0], "a") == 0); + TEST_CHECK(snprintf(buf, sizeof (buf), "%s", "a b") < sizeof (buf)); + TEST_CHECK(UTI_SplitString(buf, words, 1) == 2); + TEST_CHECK(snprintf(buf, sizeof (buf), "%s", "a b") < sizeof (buf)); + TEST_CHECK(UTI_SplitString(buf, words, 2) == 2); + TEST_CHECK(words[0] == buf + 0); + TEST_CHECK(words[1] == buf + 4); + TEST_CHECK(strcmp(words[0], "a") == 0); + TEST_CHECK(strcmp(words[1], "b") == 0); + TEST_CHECK(snprintf(buf, sizeof (buf), "%s", " a b ") < sizeof (buf)); + TEST_CHECK(UTI_SplitString(buf, words, 3) == 2); + TEST_CHECK(words[0] == buf + 1); + TEST_CHECK(words[1] == buf + 3); + TEST_CHECK(strcmp(words[0], "a") == 0); + TEST_CHECK(strcmp(words[1], "b") == 0); } diff --git a/util.c b/util.c index 7cd043f..8f18a21 100644 --- a/util.c +++ b/util.c @@ -1402,3 +1402,33 @@ UTI_HexToBytes(const char *hex, void *buf, unsigned int len) return *hex == '\0' ? i : 0; } + +/* ================================================== */ + +int +UTI_SplitString(char *string, char **words, int max_saved_words) +{ + char *s = string; + int i; + + for (i = 0; i < max_saved_words; i++) + words[i] = NULL; + + for (i = 0; ; i++) { + /* Zero white-space characters before the word */ + while (*s != '\0' && isspace((unsigned char)*s)) + *s++ = '\0'; + + if (*s == '\0') + break; + + if (i < max_saved_words) + words[i] = s; + + /* Find the next word */ + while (*s != '\0' && !isspace((unsigned char)*s)) + s++; + } + + return i; +} diff --git a/util.h b/util.h index 3552f78..1e28b26 100644 --- a/util.h +++ b/util.h @@ -220,6 +220,11 @@ extern int UTI_BytesToHex(const void *buf, unsigned int buf_len, char *hex, unsi is supported. */ extern unsigned int UTI_HexToBytes(const char *hex, void *buf, unsigned int len); +/* Split a string into words separated by whitespace characters. It returns + the number of words found in the string, but saves only up to the specified + number of pointers to the words. */ +extern int UTI_SplitString(char *string, char **words, int max_saved_words); + /* Macros to get maximum and minimum of two values */ #ifdef MAX #undef MAX