aboutsummaryrefslogblamecommitdiff
path: root/comparison.c
blob: 65bb7de17d21ea733c00656ed6c213a77fa1165d (plain) (tree)





































































































































































































































                                                                                 
#include <errno.h>
#include <string.h>
#include <stdio.h>
#ifdef __GLIBC__
#include <bsd/string.h>
#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;
}