feat(string): add BSD strlcpy/strlcat at level 2
Exact OpenBSD semantics: strlcpy returns strlen(src) and writes at most size-1 bytes plus NUL; strlcat returns dlen + strlen(src) with dlen = min(size, strlen(dst)) and never reads past size bytes in dst. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <[email protected]>
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Append src to dst, NUL-terminating the result within size bytes.
|
||||
* Return dlen + strlen(src), where dlen = min(size, strlen(dst)): the length
|
||||
* the result would have had without truncation. dst is never read past
|
||||
* size bytes. When size is 0 or dlen == size, nothing is written.
|
||||
*/
|
||||
size_t
|
||||
strlcat(char *dst, const char *src, size_t size)
|
||||
{
|
||||
char *d;
|
||||
const char *s;
|
||||
size_t n;
|
||||
size_t dlen;
|
||||
|
||||
d = dst;
|
||||
s = src;
|
||||
n = size;
|
||||
|
||||
/* Find the end of dst, stopping after at most size bytes. */
|
||||
while (n != 0 && *d != '\0')
|
||||
{
|
||||
d++;
|
||||
n--;
|
||||
}
|
||||
dlen = (size_t)(d - dst);
|
||||
n = size - dlen;
|
||||
|
||||
if (n != 0)
|
||||
{
|
||||
/* Append as much of src as fits, leaving room for the NUL. */
|
||||
while (*s != '\0')
|
||||
{
|
||||
if (n != 1)
|
||||
{
|
||||
*d++ = *s;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
}
|
||||
|
||||
/* Count the unwritten remainder of src. */
|
||||
while (*s != '\0')
|
||||
{
|
||||
s++;
|
||||
}
|
||||
|
||||
return dlen + (size_t)(s - src);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Copy src to dst, NUL-terminating the result, truncated to fit size bytes.
|
||||
* Return strlen(src): the length of the string the call tried to create,
|
||||
* independent of any truncation. When size is 0, nothing is written.
|
||||
*/
|
||||
size_t
|
||||
strlcpy(char *dst, const char *src, size_t size)
|
||||
{
|
||||
const char *orig_src;
|
||||
size_t nleft;
|
||||
|
||||
orig_src = src;
|
||||
nleft = size;
|
||||
|
||||
/* Copy as many bytes as will fit, leaving room for the NUL. */
|
||||
if (nleft != 0)
|
||||
{
|
||||
while (--nleft != 0)
|
||||
{
|
||||
*dst = *src;
|
||||
if (*src == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
dst++;
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
/* No room for a NUL (or size was 0): NUL-terminate and measure src. */
|
||||
if (nleft == 0)
|
||||
{
|
||||
if (size != 0)
|
||||
{
|
||||
*dst = '\0';
|
||||
}
|
||||
while (*src != '\0')
|
||||
{
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
/* src ends at its NUL either way, so this is strlen(original src). */
|
||||
return (size_t)(src - orig_src);
|
||||
}
|
||||
Reference in New Issue
Block a user