From 6b486f41d1b113bdb4018f5611105b83c7cd5455 Mon Sep 17 00:00:00 2001 From: Nicolas Hillegeer Date: Sat, 26 Apr 2014 19:10:49 +0200 Subject: [PATCH] memory: implement xstp(n)cpy Both are implemented to POSIX 2008 spec, though I'm not sure I'm happy about stpncpy's behaviour. --- src/memory.c | 20 ++++++++++++++++++++ src/memory.h | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/src/memory.c b/src/memory.c index dff7e41bad..9e527bc513 100644 --- a/src/memory.c +++ b/src/memory.c @@ -173,6 +173,26 @@ void *xmemdupz(const void *data, size_t len) return memcpy(xmallocz(len), data, len); } +char *xstpcpy(char *restrict dst, const char *restrict src) +{ + const size_t len = strlen(src); + return (char *)memcpy(dst, src, len + 1) + len; +} + +char *xstpncpy(char *restrict dst, const char *restrict src, size_t maxlen) +{ + const char *p = memchr(src, '\0', maxlen); + if (p) { + size_t srclen = (size_t)(p - src); + memcpy(dst, src, srclen); + memset(dst + srclen, 0, maxlen - srclen); + return dst + srclen; + } else { + memcpy(dst, src, maxlen); + return dst + maxlen; + } +} + char * xstrdup(const char *str) { char *ret = strdup(str); diff --git a/src/memory.h b/src/memory.h index 29ec4cdd0e..b70f6bdf2d 100644 --- a/src/memory.h +++ b/src/memory.h @@ -86,6 +86,47 @@ char * xstrdup(const char *str) char * xstrndup(const char *str, size_t len) FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET; +/// The xstpcpy() function shall copy the string pointed to by src (including +/// the terminating NUL character) into the array pointed to by dst. +/// +/// The xstpcpy() function shall return a pointer to the terminating NUL +/// character copied into the dst buffer. This is the only difference with +/// strcpy(), which returns dst. +/// +/// WARNING: If copying takes place between objects that overlap, the behavior is +/// undefined. +/// +/// This is the Neovim version of stpcpy(3) as defined in POSIX 2008. We +/// don't require that supported platforms implement POSIX 2008, so we +/// implement our own version. +/// +/// @param dst +/// @param src +char *xstpcpy(char *restrict dst, const char *restrict src); + +/// The xstpncpy() function shall copy not more than n bytes (bytes that follow +/// a NUL character are not copied) from the array pointed to by src to the +/// array pointed to by dst. +/// +/// If a NUL character is written to the destination, the xstpncpy() function +/// shall return the address of the first such NUL character. Otherwise, it +/// shall return &dst[maxlen]. +/// +/// WARNING: If copying takes place between objects that overlap, the behavior is +/// undefined. +/// +/// WARNING: xstpncpy will ALWAYS write maxlen bytes. If src is shorter than +/// maxlen, zeroes will be written to the remaining bytes. +/// +/// TODO(aktau): I don't see a good reason to have this last behaviour, and +/// it is potentially wasteful. Could we perhaps deviate from the standard +/// and not zero the rest of the buffer? +/// +/// @param dst +/// @param src +/// @param maxlen +char *xstpncpy(char *restrict dst, const char *restrict src, size_t maxlen); + /// Old low level memory allocation function. /// /// @deprecated use xmalloc() directly instead