From 8ba5282b9982e1d49199f816a1ec4148a232d8df Mon Sep 17 00:00:00 2001 From: Leah Neukirchen Date: Sat, 6 Nov 2021 19:05:14 +0100 Subject: add comparison of several string copying variants --- comparison.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 comparison.c (limited to 'comparison.c') diff --git a/comparison.c b/comparison.c new file mode 100644 index 0000000..65bb7de --- /dev/null +++ b/comparison.c @@ -0,0 +1,230 @@ +#include +#include +#include +#ifdef __GLIBC__ +#include +#endif + +#include "ste.h" + +/* Task: write a function that appends three char* arguments into + a 1024 byte fixed buffer and return a pointer to it. + Return NULL if the strings don't fit. */ + +/* Annotations of suboptimal behavior: + (T) traverses the string to find the end + (I) doesn't support incremental string construction + (L) overhead strlen + (Z) buffer is not NUL-terminated at time of truncation detection + */ + +char * +path3_stecpy(char *a, char *b, char *c) +{ + static char buf[1024]; + char *end = buf + sizeof buf; + + char *pos = buf; + pos = stecpy(pos, end, a); + pos = stecpy(pos, end, b); + pos = stecpy(pos, end, c); + + if (pos == end) + return 0; + return buf; +} + +char *str_ecpy(char *to, char *e, char *from); + +char * +path3_strecpy(char *a, char *b, char *c) +{ + static char buf[1024]; + char *end = buf + sizeof buf; + + char *pos = buf; + pos = str_ecpy(pos, end, a); + pos = str_ecpy(pos, end, b); + pos = str_ecpy(pos, end, c); + + if (pos == end - 1) // almost the same as stecpy but easier to get wrong + return 0; + return buf; +} + +char * +path3_strncat(char *a, char *b, char *c) +{ + static char buf[1024]; + size_t n = sizeof buf - 1; + + buf[0] = 0; + if (strlen(a) > n) // (L) + return 0; + strncat(buf, a, n); + n -= strlen(a); // (L) + if (strlen(b) > n) // (L) + return 0; + strncat(buf, b, n); // (T) + n -= strlen(b); // (L) + if (strlen(c) > n) // (L) + return 0; + strncat(buf, c, n); // (T) + + return buf; +} + +char * +path3_strlcat(char *a, char *b, char *c) +{ + static char buf[1024]; + + strlcpy(buf, a, sizeof buf); + strlcat(buf, b, sizeof buf); // (T) + if (strlcat(buf, c, sizeof buf) >= sizeof buf) // (T) + return 0; + + return buf; +} + +char * +path3_snprintf(char *a, char *b, char *c) +{ + static char buf[1024]; + + if (snprintf(buf, sizeof buf, "%s%s%s", a, b, c) >= sizeof buf) // (I) + return 0; + + return buf; +} + +ssize_t str_scpy(char *dst, const char *src, size_t count); + +char * +path3_strscpy(char *a, char *b, char *c) +{ + static char buf[1024]; + + ssize_t r; + size_t l = 0; + r = str_scpy(buf + l, a, sizeof buf - l); + if (r < 0) + return 0; + l += r; + r = str_scpy(buf + l, b, sizeof buf - l); + if (r < 0) + return 0; + l += r; + r = str_scpy(buf + l, c, sizeof buf - l); + if (r < 0) + return 0; + + return buf; +} + +char * +path3_memcpy(char *a, char *b, char *c) +{ + static char buf[1024]; + size_t s = 0; + + if (strlen(a) >= sizeof buf - s) // (L) + return 0; + memcpy(buf + s, a, strlen(a)); + s += strlen(a); + + if (strlen(b) >= sizeof buf - s) // (L) + return 0; + memcpy(buf + s, b, strlen(b)); + s += strlen(b); + + if (strlen(c) >= sizeof buf - s) // (L) + return 0; + memcpy(buf + s, c, strlen(c)); + + return buf; +} + +size_t str_copyb(char *s, const char *t, size_t max); + +char * +path3_str_copyb(char *a, char *b, char *c) +{ + static char buf[1024]; + + size_t n = 0; + + n += str_copyb(buf + n, a, sizeof buf - n); + if (n == sizeof buf) + return 0; // (Z) + n += str_copyb(buf + n, b, sizeof buf - n); + if (n == sizeof buf) + return 0; // (Z) + n += str_copyb(buf + n, c, sizeof buf - n); + if (n == sizeof buf) + return 0; // (Z) + + return buf; +} + +int +main() +{ + printf("%s\n", path3_stecpy("abc", "def", "ghi")); + printf("%s\n", path3_strecpy("abc", "def", "ghi")); + printf("%s\n", path3_strncat("abc", "def", "ghi")); + printf("%s\n", path3_strlcat("abc", "def", "ghi")); + printf("%s\n", path3_snprintf("abc", "def", "ghi")); + printf("%s\n", path3_strscpy("abc", "def", "ghi")); + printf("%s\n", path3_memcpy("abc", "def", "ghi")); + printf("%s\n", path3_str_copyb("abc", "def", "ghi")); +} + + + +/* Plan 9 strecpy(3) */ +char* +str_ecpy(char *to, char *e, char *from) +{ + if (to >= e) + return to; + + to = memccpy(to, from, '\0', e - to); + if (!to) { + to = e - 1; + *to = '\0'; + } else { + to--; + } + + return to; +} + +/* Linux kernel strscpy */ +ssize_t +str_scpy(char *dst, const char *src, size_t count) +{ + if (count == 0) + return -E2BIG; // no space for trailing null + + char *end = memccpy(dst, src, 0, count); + if (!end) { + dst[count] = 0; + return -E2BIG; + } + + return end - dst - 1; +} + +/* djb-style, but with proper integer widths */ +size_t +str_copyb(char *s, const char *t, size_t max) +{ + size_t len = 0; + + while (max-- > 0) { + if (!(*s = *t)) { return len; } ++s; ++t; ++len; + } + + return len; +} -- cgit 1.4.1