285 lines · 4.8 KB · C
RawDownload
/* SPDX-License-Identifier: LGPL-2.1 OR MIT *//* * string function definitions for NOLIBC * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu> */ #ifndef _NOLIBC_STRING_H#define _NOLIBC_STRING_H #include "std.h" static void *malloc(size_t len); /* * As much as possible, please keep functions alphabetically sorted. */ static __attribute__((unused))int memcmp(const void *s1, const void *s2, size_t n){	size_t ofs = 0;	char c1 = 0; 	while (ofs < n && !(c1 = ((char *)s1)[ofs] - ((char *)s2)[ofs])) {		ofs++;	}	return c1;} static __attribute__((unused))void *_nolibc_memcpy_up(void *dst, const void *src, size_t len){	size_t pos = 0; 	while (pos < len) {		((char *)dst)[pos] = ((const char *)src)[pos];		pos++;	}	return dst;} static __attribute__((unused))void *_nolibc_memcpy_down(void *dst, const void *src, size_t len){	while (len) {		len--;		((char *)dst)[len] = ((const char *)src)[len];	}	return dst;} /* might be ignored by the compiler without -ffreestanding, then found as * missing. */__attribute__((weak,unused,section(".text.nolibc_memmove")))void *memmove(void *dst, const void *src, size_t len){	size_t dir, pos; 	pos = len;	dir = -1; 	if (dst < src) {		pos = -1;		dir = 1;	} 	while (len) {		pos += dir;		((char *)dst)[pos] = ((const char *)src)[pos];		len--;	}	return dst;} /* must be exported, as it's used by libgcc on ARM */__attribute__((weak,unused,section(".text.nolibc_memcpy")))void *memcpy(void *dst, const void *src, size_t len){	return _nolibc_memcpy_up(dst, src, len);} /* might be ignored by the compiler without -ffreestanding, then found as * missing. */__attribute__((weak,unused,section(".text.nolibc_memset")))void *memset(void *dst, int b, size_t len){	char *p = dst; 	while (len--)		*(p++) = b;	return dst;} static __attribute__((unused))char *strchr(const char *s, int c){	while (*s) {		if (*s == (char)c)			return (char *)s;		s++;	}	return NULL;} static __attribute__((unused))int strcmp(const char *a, const char *b){	unsigned int c;	int diff; 	while (!(diff = (unsigned char)*a++ - (c = (unsigned char)*b++)) && c)		;	return diff;} static __attribute__((unused))char *strcpy(char *dst, const char *src){	char *ret = dst; 	while ((*dst++ = *src++));	return ret;} /* this function is only used with arguments that are not constants or when * it's not known because optimizations are disabled. */static __attribute__((unused))size_t nolibc_strlen(const char *str){	size_t len; 	for (len = 0; str[len]; len++);	return len;} /* do not trust __builtin_constant_p() at -O0, as clang will emit a test and * the two branches, then will rely on an external definition of strlen(). */#if defined(__OPTIMIZE__)#define strlen(str) ({                          \	__builtin_constant_p((str)) ?           \		__builtin_strlen((str)) :       \		nolibc_strlen((str));           \})#else#define strlen(str) nolibc_strlen((str))#endif static __attribute__((unused))size_t strnlen(const char *str, size_t maxlen){	size_t len; 	for (len = 0; (len < maxlen) && str[len]; len++);	return len;} static __attribute__((unused))char *strdup(const char *str){	size_t len;	char *ret; 	len = strlen(str);	ret = malloc(len + 1);	if (__builtin_expect(ret != NULL, 1))		memcpy(ret, str, len + 1); 	return ret;} static __attribute__((unused))char *strndup(const char *str, size_t maxlen){	size_t len;	char *ret; 	len = strnlen(str, maxlen);	ret = malloc(len + 1);	if (__builtin_expect(ret != NULL, 1)) {		memcpy(ret, str, len);		ret[len] = '\0';	} 	return ret;} static __attribute__((unused))size_t strlcat(char *dst, const char *src, size_t size){	size_t len;	char c; 	for (len = 0; dst[len];	len++)		; 	for (;;) {		c = *src;		if (len < size)			dst[len] = c;		if (!c)			break;		len++;		src++;	} 	return len;} static __attribute__((unused))size_t strlcpy(char *dst, const char *src, size_t size){	size_t len;	char c; 	for (len = 0;;) {		c = src[len];		if (len < size)			dst[len] = c;		if (!c)			break;		len++;	}	return len;} static __attribute__((unused))char *strncat(char *dst, const char *src, size_t size){	char *orig = dst; 	while (*dst)		dst++; 	while (size && (*dst = *src)) {		src++;		dst++;		size--;	} 	*dst = 0;	return orig;} static __attribute__((unused))int strncmp(const char *a, const char *b, size_t size){	unsigned int c;	int diff = 0; 	while (size-- &&	       !(diff = (unsigned char)*a++ - (c = (unsigned char)*b++)) && c)		; 	return diff;} static __attribute__((unused))char *strncpy(char *dst, const char *src, size_t size){	size_t len; 	for (len = 0; len < size; len++)		if ((dst[len] = *src))			src++;	return dst;} static __attribute__((unused))char *strrchr(const char *s, int c){	const char *ret = NULL; 	while (*s) {		if (*s == (char)c)			ret = s;		s++;	}	return (char *)ret;} #endif /* _NOLIBC_STRING_H */