It may shorten the code a bit as the following pattern:
VIR_STRNDUP(dst, src, cond ? n : strlen(src))
is used on several places among our code. However, we can
move the strlen into virStrndup and thus write just:
VIR_STRNDUP(dst, src, cond ? n : -1)
---
src/util/virstring.c | 7 ++++++-
src/util/virstring.h | 11 ++++++++---
tests/virstringtest.c | 36 ++++++++++++++++++++++++++++++++++++
3 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/src/util/virstring.c b/src/util/virstring.c
index fcbb375..b244e6c 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -568,12 +568,15 @@ virStrdup(char **dest,
* caller's body where virStrndup is called from. Consider
* using VIR_STRNDUP which sets these automatically.
*
+ * In case @n is smaller than zero, the whole @src string is
+ * copied.
+ *
* Returns: 0 for NULL src, 1 on successful copy, -1 otherwise.
*/
int
virStrndup(char **dest,
const char *src,
- size_t n,
+ ssize_t n,
bool report,
int domcode,
const char *filename,
@@ -582,6 +585,8 @@ virStrndup(char **dest,
{
if (!src)
return 0;
+ if (n < 0)
+ n = strlen(src);
if (!(*dest = strndup(src, n))) {
if (report)
virReportOOMErrorFull(domcode, filename, funcname, linenr);
diff --git a/src/util/virstring.h b/src/util/virstring.h
index 534ce91..7063fe4 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -93,7 +93,7 @@ int virStrdup(char **dest, const char *src, bool report, int domcode,
const char *filename, const char *funcname, size_t linenr)
ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1);
-int virStrndup(char **dest, const char *src, size_t n, bool report, int domcode,
+int virStrndup(char **dest, const char *src, ssize_t n, bool report, int domcode,
const char *filename, const char *funcname, size_t linenr)
ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1);
@@ -132,7 +132,9 @@ int virStrndup(char **dest, const char *src, size_t n, bool report,
int domcode,
* @n: the maximum number of bytes to copy
*
* Duplicate @src string and store it into @dst. If @src is longer than @n,
- * only @n bytes are copied and terminating null byte '\0' is added.
+ * only @n bytes are copied and terminating null byte '\0' is added. If @n
+ * is a negative number, then the whole @src string is copied. That is
+ * VIR_STRDUP(dst, src) and VIR_STRNDUP(dst, src, -1) are equal.
*
* This macro is safe to use on arguments with side effects.
*
@@ -150,7 +152,10 @@ int virStrndup(char **dest, const char *src, size_t n, bool report,
int domcode,
* @n: the maximum number of bytes to copy
*
* Duplicate @src string and store it into @dst. If @src is longer than @n,
- * only @n bytes are copied and terminating null byte '\0' is added.
+ * only @n bytes are copied and terminating null byte '\0' is added. If @n
+ * is a negative number, then the whole @src string is copied. That is
+ * VIR_STRDUP_QUIET(dst, src) and VIR_STRNDUP_QUIET(dst, src, -1) are
+ * equal.
*
* This macro is safe to use on arguments with side effects.
*
diff --git a/tests/virstringtest.c b/tests/virstringtest.c
index da06c0f..3d0b55b 100644
--- a/tests/virstringtest.c
+++ b/tests/virstringtest.c
@@ -196,6 +196,39 @@ cleanup:
return ret;
}
+static int
+testStrndupNegative(const void *opaque ATTRIBUTE_UNUSED)
+{
+ int ret = -1;
+ char *dst;
+ const char *src = "Hello world";
+ int value;
+
+ if ((value = VIR_STRNDUP(dst, src, 5)) != 1) {
+ fprintf(stderr, "unexpected virStrndup result %d, expected 1\n",
value);
+ goto cleanup;
+ }
+
+ if (STRNEQ_NULLABLE(dst, "Hello")) {
+ fprintf(stderr, "unexpected content '%s'", dst);
+ goto cleanup;
+ }
+
+ if ((value = VIR_STRNDUP(dst, src, -1)) != 1) {
+ fprintf(stderr, "unexpected virStrndup result %d, expected 1\n",
value);
+ goto cleanup;
+ }
+
+ if (STRNEQ_NULLABLE(dst, src)) {
+ fprintf(stderr, "unexpected content '%s'", dst);
+ goto cleanup;
+ }
+
+ ret = 0;
+cleanup:
+ VIR_FREE(dst);
+ return ret;
+}
static int
mymain(void)
@@ -245,6 +278,9 @@ mymain(void)
if (virtTestRun("strdup", 1, testStrdup, NULL) < 0)
ret = -1;
+ if (virtTestRun("strdup", 1, testStrndupNegative, NULL) < 0)
+ ret = -1;
+
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
--
1.8.2.1