diff options
author | Thomas Haller <thaller@redhat.com> | 2017-10-05 14:27:24 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-10-06 11:08:39 +0200 |
commit | f1009bcde35937a7a22cb0c1b73d40e98c37b85a (patch) | |
tree | c70056168294ead0462e5ba9c549815f5aa93904 | |
parent | dccf9f3a6150a323f2bcb563dc0c068746045135 (diff) | |
download | NetworkManager-f1009bcde35937a7a22cb0c1b73d40e98c37b85a.tar.gz |
shared: add nm_strquote() util
We already have nm_strquote_a(). That is useful, but uses alloca(), hence it
is ill suited to be called from a macro, inside a loop, or from a function
that should be inlined.
Instead, add nm_strquote() that has the same purpose but writes to a provided
string buffer.
-rw-r--r-- | libnm-core/tests/test-general.c | 83 | ||||
-rw-r--r-- | shared/nm-utils/nm-shared-utils.c | 72 | ||||
-rw-r--r-- | shared/nm-utils/nm-shared-utils.h | 2 |
3 files changed, 157 insertions, 0 deletions
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index 08d55555be..257fdad5a1 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -4852,6 +4852,88 @@ test_hexstr2bin (void) /*****************************************************************************/ +static void +_do_strquote (const char *str, gsize buf_len, const char *expected) +{ + char canary = (char) nmtst_get_rand_int (); + gs_free char *buf_full = g_malloc (buf_len + 2); + char *buf = &buf_full[1]; + const char *b; + + buf[-1] = canary; + buf[buf_len] = canary; + + if (buf_len == 0) { + b = nm_strquote (NULL, 0, str); + g_assert (b == NULL); + g_assert (expected == NULL); + b = nm_strquote (buf, 0, str); + g_assert (b == buf); + } else { + b = nm_strquote (buf, buf_len, str); + g_assert (b == buf); + g_assert (strlen (b) < buf_len); + g_assert_cmpstr (expected, ==, b); + } + + g_assert (buf[-1] == canary); + g_assert (buf[buf_len] == canary); +} + +static void +test_nm_strquote (void) +{ + _do_strquote (NULL, 0, NULL); + _do_strquote ("", 0, NULL); + _do_strquote ("a", 0, NULL); + _do_strquote ("ab", 0, NULL); + + _do_strquote (NULL, 1, ""); + _do_strquote (NULL, 2, "("); + _do_strquote (NULL, 3, "(n"); + _do_strquote (NULL, 4, "(nu"); + _do_strquote (NULL, 5, "(nul"); + _do_strquote (NULL, 6, "(null"); + _do_strquote (NULL, 7, "(null)"); + _do_strquote (NULL, 8, "(null)"); + _do_strquote (NULL, 100, "(null)"); + + _do_strquote ("", 1, ""); + _do_strquote ("", 2, "^"); + _do_strquote ("", 3, "\"\""); + _do_strquote ("", 4, "\"\""); + _do_strquote ("", 5, "\"\""); + _do_strquote ("", 100, "\"\""); + + _do_strquote ("a", 1, ""); + _do_strquote ("a", 2, "^"); + _do_strquote ("a", 3, "\"^"); + _do_strquote ("a", 4, "\"a\""); + _do_strquote ("a", 5, "\"a\""); + _do_strquote ("a", 6, "\"a\""); + _do_strquote ("a", 100, "\"a\""); + + _do_strquote ("ab", 1, ""); + _do_strquote ("ab", 2, "^"); + _do_strquote ("ab", 3, "\"^"); + _do_strquote ("ab", 4, "\"a^"); + _do_strquote ("ab", 5, "\"ab\""); + _do_strquote ("ab", 6, "\"ab\""); + _do_strquote ("ab", 7, "\"ab\""); + _do_strquote ("ab", 100, "\"ab\""); + + _do_strquote ("abc", 1, ""); + _do_strquote ("abc", 2, "^"); + _do_strquote ("abc", 3, "\"^"); + _do_strquote ("abc", 4, "\"a^"); + _do_strquote ("abc", 5, "\"ab^"); + _do_strquote ("abc", 6, "\"abc\""); + _do_strquote ("abc", 7, "\"abc\""); + _do_strquote ("abc", 100, "\"abc\""); +} + +/*****************************************************************************/ + #define UUID_NIL "00000000-0000-0000-0000-000000000000" #define UUID_NS_DNS "6ba7b810-9dad-11d1-80b4-00c04fd430c8" @@ -6366,6 +6448,7 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/test_setting_user_data", test_setting_user_data); g_test_add_func ("/core/general/hexstr2bin", test_hexstr2bin); + g_test_add_func ("/core/general/nm_strquote", test_nm_strquote); g_test_add_func ("/core/general/test_nm_utils_uuid_generate_from_string", test_nm_utils_uuid_generate_from_string); g_test_add_func ("/core/general/_nm_utils_uuid_generate_from_strings", test_nm_utils_uuid_generate_from_strings); diff --git a/shared/nm-utils/nm-shared-utils.c b/shared/nm-utils/nm-shared-utils.c index 3be5550b74..16066d7085 100644 --- a/shared/nm-utils/nm-shared-utils.c +++ b/shared/nm-utils/nm-shared-utils.c @@ -115,6 +115,78 @@ nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...) /*****************************************************************************/ +/** + * nm_strquote: + * @buf: the output buffer of where to write the quoted @str argument. + * @buf_len: the size of @buf. + * @str: (allow-none): the string to quote. + * + * Writes @str to @buf with quoting. The resulting buffer + * is always NUL terminated, unless @buf_len is zero. + * If @str is %NULL, it writes "(null)". + * + * If @str needs to be truncated, the closing quote is '^' instead + * of '"'. + * + * This is similar to nm_strquote_a(), which however uses alloca() + * to allocate a new buffer. Also, here @buf_len is the size of @buf, + * while nm_strquote_a() has the number of characters to print. The latter + * doesn't include the quoting. + * + * Returns: the input buffer with the quoted string. */ +const char * +nm_strquote (char *buf, gsize buf_len, const char *str) +{ + const char *const buf0 = buf; + + if (!str) { + nm_utils_strbuf_append_str (&buf, &buf_len, "(null)"); + goto out; + } + + if (G_UNLIKELY (buf_len <= 2)) { + switch (buf_len) { + case 2: + *(buf++) = '^'; + /* fall-through*/ + case 1: + *(buf++) = '\0'; + break; + } + goto out; + } + + *(buf++) = '"'; + buf_len--; + + nm_utils_strbuf_append_str (&buf, &buf_len, str); + + /* if the string was too long we indicate truncation with a + * '^' instead of a closing quote. */ + if (G_UNLIKELY (buf_len <= 1)) { + switch (buf_len) { + case 1: + buf[-1] = '^'; + break; + case 0: + buf[-2] = '^'; + break; + default: + nm_assert_not_reached (); + break; + } + } else { + nm_assert (buf_len >= 2); + *(buf++) = '"'; + *(buf++) = '\0'; + } + +out: + return buf0; +} + +/*****************************************************************************/ + char _nm_utils_to_string_buffer[]; void diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h index 98cac9afcd..af1d22c832 100644 --- a/shared/nm-utils/nm-shared-utils.h +++ b/shared/nm-utils/nm-shared-utils.h @@ -166,6 +166,8 @@ void nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...) _n void nm_utils_strbuf_append_c (char **buf, gsize *len, char c); void nm_utils_strbuf_append_str (char **buf, gsize *len, const char *str); +const char *nm_strquote (char *buf, gsize buf_len, const char *str); + /*****************************************************************************/ const char **nm_utils_strsplit_set (const char *str, const char *delimiters); |