From d8d457f500d6989f5bf26f153afaaeeb366116ba Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Sat, 10 Nov 2018 18:02:34 +0100 Subject: [PATCH 1/5] Remove string_replace() string_replace_at does almost the same and string_replace is only used once, where additionally string_replace_at would be the better choice. --- src/utils.c | 12 +----------- src/utils.h | 3 --- test/utils.c | 23 ----------------------- 3 files changed, 1 insertion(+), 37 deletions(-) diff --git a/src/utils.c b/src/utils.c index adfa14b..34f7265 100644 --- a/src/utils.c +++ b/src/utils.c @@ -44,16 +44,6 @@ char *string_replace_at(char *buf, int pos, int len, const char *repl) return tmp; } -char *string_replace(const char *needle, const char *replacement, char *haystack) -{ - char *start; - start = strstr(haystack, needle); - if (!start) - return haystack; - - return string_replace_at(haystack, (start - haystack), strlen(needle), replacement); -} - char *string_replace_all(const char *needle, const char *replacement, char *haystack) { char *start; @@ -134,7 +124,7 @@ char *string_to_path(char *string) if (string && STRN_EQ(string, "~/", 2)) { char *home = g_strconcat(getenv("HOME"), "/", NULL); - string = string_replace("~/", home, string); + string = string_replace_at(string, 0, 2, home); g_free(home); } diff --git a/src/utils.h b/src/utils.h index 6ea3b4e..1e9cd4d 100644 --- a/src/utils.h +++ b/src/utils.h @@ -25,9 +25,6 @@ char *string_replace_all(const char *needle, const char *replacement, char *hays /* replace characters with at position of the string */ char *string_replace_at(char *buf, int pos, int len, const char *repl); -/* replace needle with replacement in haystack */ -char *string_replace(const char *needle, const char *replacement, char *haystack); - char *string_append(char *a, const char *b, const char *sep); /* strip content between two delimiter characters (inplace) */ diff --git a/test/utils.c b/test/utils.c index b99af9e..f59e00f 100644 --- a/test/utils.c +++ b/test/utils.c @@ -48,28 +48,6 @@ TEST test_string_replace_all(void) PASS(); } -TEST test_string_replace(void) -{ - char *text = malloc(128 * sizeof(char)); - strcpy(text, "aaaaa"); - ASSERT_STR_EQ("baaaa", (text = string_replace("a", "b", text)) ); - - strcpy(text, ""); - ASSERT_STR_EQ((text = string_replace("a", "b", text)), ""); - - strcpy(text, "Nothing to replace"); - ASSERT_STR_EQ((text = string_replace("z", "a", text)), "Nothing to replace"); - - strcpy(text, "Reverse this"); - ASSERT_STR_EQ("Reverse sith", (text = string_replace("this", "sith", text))); - - strcpy(text, "abcdabc"); - ASSERT_STR_EQ("xyzabcdabc", (text = string_replace("a", "xyza", text))); - - free(text); - PASS(); -} - TEST test_string_append(void) { char *exp; @@ -202,7 +180,6 @@ SUITE(suite_utils) { RUN_TEST(test_string_replace_char); RUN_TEST(test_string_replace_all); - RUN_TEST(test_string_replace); RUN_TEST(test_string_append); RUN_TEST(test_string_strip_quotes); RUN_TEST(test_string_strip_delimited); From ae1b20881ecab1508207538fe7dba48d03892f46 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Sun, 11 Nov 2018 14:34:51 +0100 Subject: [PATCH 2/5] Use isspace to test for whitespace --- src/utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils.c b/src/utils.c index 34f7265..ef29cee 100644 --- a/src/utils.c +++ b/src/utils.c @@ -2,6 +2,7 @@ #include "utils.h" #include +#include #include #include #include @@ -134,7 +135,6 @@ char *string_to_path(char *string) gint64 string_to_time(const char *string) { - assert(string); errno = 0; @@ -155,7 +155,7 @@ gint64 string_to_time(const char *string) } // endptr may point to a separating space - while (*endptr == ' ') + while (isspace(*endptr)) endptr++; if (STRN_EQ(endptr, "ms", 2)) From 90b04a22dd1406264c1bdcbfe095bfe03ed5a492 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Sun, 11 Nov 2018 14:39:32 +0100 Subject: [PATCH 3/5] Use g_malloc instead of malloc g_malloc won't return NULL, but abort the program. As we don't check for NULl, this is the better solution. --- test/utils.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/utils.c b/test/utils.c index f59e00f..91e99fb 100644 --- a/test/utils.c +++ b/test/utils.c @@ -5,7 +5,8 @@ TEST test_string_replace_char(void) { - char *text = malloc(128 * sizeof(char)); + char *text = g_malloc(128 * sizeof(char)); + strcpy(text, "a aa aaa"); ASSERT_STR_EQ("b bb bbb", string_replace_char('a', 'b', text)); @@ -14,8 +15,8 @@ TEST test_string_replace_char(void) strcpy(text, ""); ASSERT_STR_EQ("", string_replace_char('a', 'b', text)); - free(text); + g_free(text); PASS(); } @@ -27,8 +28,8 @@ TEST test_string_replace_char(void) TEST test_string_replace_all(void) { + char *text = g_malloc(128 * sizeof(char)); - char *text = malloc(128 * sizeof(char)); strcpy(text, "aaaaa"); ASSERT_STR_EQ("bbbbb", (text = string_replace_all("a", "b", text))); @@ -44,7 +45,7 @@ TEST test_string_replace_all(void) strcpy(text, "abcdabc"); ASSERT_STR_EQ("xyzabcdxyzabc", (text = string_replace_all("a", "xyza", text))); - free(text); + g_free(text); PASS(); } @@ -110,7 +111,7 @@ TEST test_string_strip_quotes(void) TEST test_string_strip_delimited(void) { - char *text = malloc(128 * sizeof(char)); + char *text = g_malloc(128 * sizeof(char)); strcpy(text, "A string_strip_delimited test"); string_strip_delimited(text, '<', '>'); @@ -132,7 +133,7 @@ TEST test_string_strip_delimited(void) string_strip_delimited(text, '<', '>'); ASSERT_STR_EQ("Nothing is done if there are no delimiters in the string", text); - free(text); + g_free(text); PASS(); } From 413c0d68afe144cab8433d72bd06e05edf7a707b Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Sun, 11 Nov 2018 15:15:37 +0100 Subject: [PATCH 4/5] Use assertions and NULL checks in markup and utils --- src/markup.c | 10 +++++++--- src/utils.c | 13 +++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/markup.c b/src/markup.c index dba630f..75372a8 100644 --- a/src/markup.c +++ b/src/markup.c @@ -14,7 +14,8 @@ static char *markup_quote(char *str) { - assert(str); + if (!str) + return NULL; str = string_replace_all("&", "&", str); str = string_replace_all("\"", """, str); @@ -27,7 +28,8 @@ static char *markup_quote(char *str) static char *markup_unquote(char *str) { - assert(str); + if (!str) + return NULL; str = string_replace_all(""", "\"", str); str = string_replace_all("'", "'", str); @@ -40,7 +42,8 @@ static char *markup_unquote(char *str) static char *markup_br2nl(char *str) { - assert(str); + if (!str) + return NULL; str = string_replace_all("
", "\n", str); str = string_replace_all("
", "\n", str); @@ -57,6 +60,7 @@ static char *markup_br2nl(char *str) */ void markup_strip_a(char **str, char **urls) { + assert(*str); char *tag1 = NULL; if (urls) diff --git a/src/utils.c b/src/utils.c index ef29cee..d185662 100644 --- a/src/utils.c +++ b/src/utils.c @@ -13,6 +13,9 @@ char *string_replace_char(char needle, char replacement, char *haystack) { + if (!haystack) + return NULL; + char *current = haystack; while ((current = strchr(current, needle))) *current++ = replacement; @@ -21,6 +24,9 @@ char *string_replace_char(char needle, char replacement, char *haystack) char *string_replace_at(char *buf, int pos, int len, const char *repl) { + assert(buf); + assert(repl); + char *tmp; int size, buf_len, repl_len; @@ -47,6 +53,11 @@ char *string_replace_at(char *buf, int pos, int len, const char *repl) char *string_replace_all(const char *needle, const char *replacement, char *haystack) { + if (!haystack) + return NULL; + assert(needle); + assert(replacement); + char *start; int needle_pos; int needle_len, repl_len; @@ -106,6 +117,8 @@ char *string_strip_quotes(const char *value) void string_strip_delimited(char *str, char a, char b) { + assert(str); + int iread=-1, iwrite=0, copen=0; while (str[++iread] != 0) { if (str[iread] == a) { From 2d2a9c893c6662c1987daa139769cf7c5adc27e2 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Sun, 11 Nov 2018 15:05:44 +0100 Subject: [PATCH 5/5] Add doxygen docs for markup and utils files --- src/markup.c | 46 ++++++++++++---------------------- src/markup.h | 31 +++++++++++++++++++++++ src/utils.c | 8 +++++- src/utils.h | 71 ++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 115 insertions(+), 41 deletions(-) diff --git a/src/markup.c b/src/markup.c index 75372a8..884fb24 100644 --- a/src/markup.c +++ b/src/markup.c @@ -12,6 +12,10 @@ #include "settings.h" #include "utils.h" +/** + * Convert all HTML special symbols to HTML entities. + * @param str (nullable) + */ static char *markup_quote(char *str) { if (!str) @@ -26,6 +30,10 @@ static char *markup_quote(char *str) return str; } +/** + * Convert all HTML special entities to their actual char. + * @param str (nullable) + */ static char *markup_unquote(char *str) { if (!str) @@ -40,6 +48,10 @@ static char *markup_unquote(char *str) return str; } +/** + * Convert all HTML linebreak tags to a newline character + * @param str (nullable) + */ static char *markup_br2nl(char *str) { if (!str) @@ -51,13 +63,7 @@ static char *markup_br2nl(char *str) return str; } -/* - * Remove HTML hyperlinks of a string. - * - * @str: The string to replace a tags - * @urls: (nullable): If any href-attributes found, an '\n' concatenated - * string of the URLs in format '[] ' - */ +/* see markup.h */ void markup_strip_a(char **str, char **urls) { assert(*str); @@ -132,13 +138,7 @@ void markup_strip_a(char **str, char **urls) } } -/* - * Remove img-tags of a string. If alt attribute given, use this as replacement. - * - * @str: The string to replace img tags - * @urls: (nullable): If any src-attributes found, an '\n' concatenated string of - * the URLs in format '[] ' - */ +/* see markup.h */ void markup_strip_img(char **str, char **urls) { const char *start; @@ -221,18 +221,7 @@ void markup_strip_img(char **str, char **urls) } } -/* - * Strip any markup from text; turn it in to plain text. - * - * For well-formed markup, the following two commands should be - * roughly equivalent: - * - * out = markup_strip(in); - * pango_parse_markup(in, -1, 0, NULL, &out, NULL, NULL); - * - * However, `pango_parse_markup()` balks at invalid markup; - * `markup_strip()` shouldn't care if there is invalid markup. - */ +/* see markup.h */ char *markup_strip(char *str) { if (!str) @@ -321,10 +310,7 @@ static char *markup_escape_unsupported(char *str) return str; } -/* - * Transform the string in accordance with `markup_mode` and - * `settings.ignore_newline` - */ +/* see markup.h */ char *markup_transform(char *str, enum markup_mode markup_mode) { if (!str) diff --git a/src/markup.h b/src/markup.h index 9d5cda7..aea4f0f 100644 --- a/src/markup.h +++ b/src/markup.h @@ -4,11 +4,42 @@ #include "settings.h" +/** + * Strip any markup from text; turn it in to plain text. + * + * For well-formed markup, the following two commands should be + * roughly equivalent: + * + * out = markup_strip(in); + * pango_parse_markup(in, -1, 0, NULL, &out, NULL, NULL); + * + * However, `pango_parse_markup()` balks at invalid markup; + * `markup_strip()` shouldn't care if there is invalid markup. + */ char *markup_strip(char *str); +/** + * Remove HTML hyperlinks of a string. + * + * @param str The string to replace a tags + * @param urls (nullable) If any href-attributes found, an `\n` concatenated + * string of the URLs in format `[] ` + */ void markup_strip_a(char **str, char **urls); + +/** + * Remove img-tags of a string. If alt attribute given, use this as replacement. + * + * @param str The string to replace img tags + * @param urls (nullable) If any src-attributes found, an `\n` concatenated string of + * the URLs in format `[] ` + */ void markup_strip_img(char **str, char **urls); +/** + * Transform the string in accordance with `markup_mode` and + * `settings.ignore_newline` + */ char *markup_transform(char *str, enum markup_mode markup_mode); #endif diff --git a/src/utils.c b/src/utils.c index d185662..22a0c50 100644 --- a/src/utils.c +++ b/src/utils.c @@ -11,6 +11,7 @@ #include "log.h" +/* see utils.h */ char *string_replace_char(char needle, char replacement, char *haystack) { if (!haystack) @@ -22,6 +23,7 @@ char *string_replace_char(char needle, char replacement, char *haystack) return haystack; } +/* see utils.h */ char *string_replace_at(char *buf, int pos, int len, const char *repl) { assert(buf); @@ -51,6 +53,7 @@ char *string_replace_at(char *buf, int pos, int len, const char *repl) return tmp; } +/* see utils.h */ char *string_replace_all(const char *needle, const char *replacement, char *haystack) { if (!haystack) @@ -78,6 +81,7 @@ char *string_replace_all(const char *needle, const char *replacement, char *hays return haystack; } +/* see utils.h */ char *string_append(char *a, const char *b, const char *sep) { if (STR_EMPTY(a)) { @@ -95,7 +99,6 @@ char *string_append(char *a, const char *b, const char *sep) g_free(a); return new; - } /* see utils.h */ @@ -115,6 +118,7 @@ char *string_strip_quotes(const char *value) return s; } +/* see utils.h */ void string_strip_delimited(char *str, char a, char b) { assert(str); @@ -132,6 +136,7 @@ void string_strip_delimited(char *str, char a, char b) str[iwrite] = 0; } +/* see utils.h */ char *string_to_path(char *string) { @@ -146,6 +151,7 @@ char *string_to_path(char *string) return string; } +/* see utils.h */ gint64 string_to_time(const char *string) { assert(string); diff --git a/src/utils.h b/src/utils.h index 1e9cd4d..b77fa28 100644 --- a/src/utils.h +++ b/src/utils.h @@ -16,19 +16,48 @@ //! Test if string a and b are the same case-insensitively #define STR_CASEQ(a, b) (strcasecmp(a, b) == 0) -/* replace all occurrences of the character needle with the character replacement in haystack */ +/** + * Replaces all occurrences of the char \p needle with the char \p replacement in \p haystack. + * + * Does not allocate a new string. + * + * @param needle The char to replace with replacement + * @param replacement The char which is the new one + * @param haystack (nullable) The string to replace + * + * @returns The exact value of the haystack paramater (to allow nesting) + */ char *string_replace_char(char needle, char replacement, char *haystack); -/* replace all occurrences of needle with replacement in haystack */ -char *string_replace_all(const char *needle, const char *replacement, char *haystack); - -/* replace characters with at position of the string */ +/** + * Replace a substring inside a string with another string. + * + * May reallocate memory. Free the result with `g_free`. + * + * @param buf The string to replace + * @param pos The position of the substring to replace + * @param len The length of the substring to replace + * @param repl The new contents of the substring. + */ char *string_replace_at(char *buf, int pos, int len, const char *repl); -char *string_append(char *a, const char *b, const char *sep); +/** + * Replace all occurences of a substring. + * + * @param needle The substring to search + * @param replacement The substring to replace + * @param haystack (nullable) The string to search the substring for + */ +char *string_replace_all(const char *needle, const char *replacement, char *haystack); -/* strip content between two delimiter characters (inplace) */ -void string_strip_delimited(char *str, char a, char b); +/** + * Append \p b to string \p a. And concatenate both strings with \p concat, if both are non-empty. + * + * @param a (nullable) The left side of the string + * @param b (nullable) The right side of the string + * @param sep (nullable) The concatenator to concatenate if a and b given + */ +char *string_append(char *a, const char *b, const char *sep); /** * Strip quotes from a string. Won't touch inner quotes. @@ -38,10 +67,32 @@ void string_strip_delimited(char *str, char a, char b); */ char *string_strip_quotes(const char *value); -/* replace tilde and path-specific values with its equivalents */ +/** + * Strip content between two delimiter characters + * + * @param str The string to operate in place + * @param a Starting delimiter + * @param b Ending delimiter + */ +void string_strip_delimited(char *str, char a, char b); + +/** + * Replace tilde and path-specific values with its equivalents + * + * The string gets invalidated. The new valid representation is the return value. + * + * @param string (nullable) The string to convert to a path. + * @returns The tilde-replaced string. + */ char *string_to_path(char *string); -/* convert time units (ms, s, m) to internal gint64 microseconds */ +/** + * Convert time units (ms, s, m) to the internal `gint64` microseconds format + * + * If no unit is given, 's' (seconds) is assumed by default. + * + * @param string The string to parse the time format from. + */ gint64 string_to_time(const char *string); /**