summaryrefslogtreecommitdiffstats
path: root/lib/string/stpecpy.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/string/stpecpy.h')
-rw-r--r--lib/string/stpecpy.h90
1 files changed, 90 insertions, 0 deletions
diff --git a/lib/string/stpecpy.h b/lib/string/stpecpy.h
new file mode 100644
index 0000000..2324baa
--- /dev/null
+++ b/lib/string/stpecpy.h
@@ -0,0 +1,90 @@
+/*
+ * SPDX-FileCopyrightText: 2022 - 2023, Alejandro Colomar <alx@kernel.org>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#ifndef SHADOW_INCLUDE_LIB_STPECPY_H_
+#define SHADOW_INCLUDE_LIB_STPECPY_H_
+
+
+#include <config.h>
+
+#if !defined(HAVE_STPECPY)
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "attr.h"
+
+
+ATTR_STRING(3)
+inline char *stpecpy(char *dst, char *end, const char *restrict src);
+
+
+/*
+ * SYNOPSIS
+ * [[gnu::null_terminated_string_arg(3)]]
+ * char *_Nullable stpecpy(char *_Nullable dst, char end[0],
+ * const char *restrict src);
+ *
+ * ARGUMENTS
+ * dst Destination buffer where to copy a string.
+ *
+ * end Pointer to one after the last element of the buffer
+ * pointed to by `dst`. Usually, it should be calculated
+ * as `dst + NITEMS(dst)`.
+ *
+ * src Source string to be copied into dst.
+ *
+ * DESCRIPTION
+ * This function copies the string pointed to by src, into a string
+ * at the buffer pointed to by dst. If the destination buffer,
+ * limited by a pointer to its end --one after its last element--,
+ * isn't large enough to hold the copy, the resulting string is
+ * truncated.
+ *
+ * This function can be chained with calls to [v]stpeprintf().
+ *
+ * RETURN VALUE
+ * dst + strlen(dst)
+ * • On success, this function returns a pointer to the
+ * terminating NUL byte.
+ *
+ * end
+ * • If this call truncated the resulting string.
+ * • If `dst == end` (a previous chained call to these
+ * functions truncated).
+ * NULL
+ * • If `dst == NULL` (a previous chained call to
+ * [v]stpeprintf() failed).
+ *
+ * ERRORS
+ * This function doesn't set errno.
+ */
+
+
+inline char *
+stpecpy(char *dst, char *end, const char *restrict src)
+{
+ bool trunc;
+ size_t dsize, dlen, slen;
+
+ if (dst == end)
+ return end;
+ if (dst == NULL)
+ return NULL;
+
+ dsize = end - dst;
+ slen = strnlen(src, dsize);
+ trunc = (slen == dsize);
+ dlen = slen - trunc;
+
+ return stpcpy(mempcpy(dst, src, dlen), "") + trunc;
+}
+
+
+#endif // !HAVE_STPECPY
+#endif // include guard