diff options
Diffstat (limited to 'lib/string.c')
| -rw-r--r-- | lib/string.c | 605 | 
1 files changed, 605 insertions, 0 deletions
| diff --git a/lib/string.c b/lib/string.c new file mode 100644 index 000000000..b375b8124 --- /dev/null +++ b/lib/string.c @@ -0,0 +1,605 @@ +/* + *  linux/lib/string.c + * + *  Copyright (C) 1991, 1992  Linus Torvalds + */ + +/* + * stupid library routines.. The optimized versions should generally be found + * as inline code in <asm-xx/string.h> + * + * These are buggy as well.. + * + * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de> + * -  Added strsep() which will replace strtok() soon (because strsep() is + *    reentrant and should be faster). Use only strsep() in new code, please. + */ + +#include <linux/types.h> +#include <linux/string.h> +#include <linux/ctype.h> +#include <malloc.h> + + +#if 0 /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */ +/** + * strnicmp - Case insensitive, length-limited string comparison + * @s1: One string + * @s2: The other string + * @len: the maximum number of characters to compare + */ +int strnicmp(const char *s1, const char *s2, size_t len) +{ +	/* Yes, Virginia, it had better be unsigned */ +	unsigned char c1, c2; + +	c1 = 0;	c2 = 0; +	if (len) { +		do { +			c1 = *s1; c2 = *s2; +			s1++; s2++; +			if (!c1) +				break; +			if (!c2) +				break; +			if (c1 == c2) +				continue; +			c1 = tolower(c1); +			c2 = tolower(c2); +			if (c1 != c2) +				break; +		} while (--len); +	} +	return (int)c1 - (int)c2; +} +#endif + +char * ___strtok; + +#ifndef __HAVE_ARCH_STRCPY +/** + * strcpy - Copy a %NUL terminated string + * @dest: Where to copy the string to + * @src: Where to copy the string from + */ +char * strcpy(char * dest,const char *src) +{ +	char *tmp = dest; + +	while ((*dest++ = *src++) != '\0') +		/* nothing */; +	return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRNCPY +/** + * strncpy - Copy a length-limited, %NUL-terminated string + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @count: The maximum number of bytes to copy + * + * Note that unlike userspace strncpy, this does not %NUL-pad the buffer. + * However, the result is not %NUL-terminated if the source exceeds + * @count bytes. + */ +char * strncpy(char * dest,const char *src,size_t count) +{ +	char *tmp = dest; + +	while (count-- && (*dest++ = *src++) != '\0') +		/* nothing */; + +	return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRCAT +/** + * strcat - Append one %NUL-terminated string to another + * @dest: The string to be appended to + * @src: The string to append to it + */ +char * strcat(char * dest, const char * src) +{ +	char *tmp = dest; + +	while (*dest) +		dest++; +	while ((*dest++ = *src++) != '\0') +		; + +	return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRNCAT +/** + * strncat - Append a length-limited, %NUL-terminated string to another + * @dest: The string to be appended to + * @src: The string to append to it + * @count: The maximum numbers of bytes to copy + * + * Note that in contrast to strncpy, strncat ensures the result is + * terminated. + */ +char * strncat(char *dest, const char *src, size_t count) +{ +	char *tmp = dest; + +	if (count) { +		while (*dest) +			dest++; +		while ((*dest++ = *src++)) { +			if (--count == 0) { +				*dest = '\0'; +				break; +			} +		} +	} + +	return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRCMP +/** + * strcmp - Compare two strings + * @cs: One string + * @ct: Another string + */ +int strcmp(const char * cs,const char * ct) +{ +	register signed char __res; + +	while (1) { +		if ((__res = *cs - *ct++) != 0 || !*cs++) +			break; +	} + +	return __res; +} +#endif + +#ifndef __HAVE_ARCH_STRNCMP +/** + * strncmp - Compare two length-limited strings + * @cs: One string + * @ct: Another string + * @count: The maximum number of bytes to compare + */ +int strncmp(const char * cs,const char * ct,size_t count) +{ +	register signed char __res = 0; + +	while (count) { +		if ((__res = *cs - *ct++) != 0 || !*cs++) +			break; +		count--; +	} + +	return __res; +} +#endif + +#ifndef __HAVE_ARCH_STRCHR +/** + * strchr - Find the first occurrence of a character in a string + * @s: The string to be searched + * @c: The character to search for + */ +char * strchr(const char * s, int c) +{ +	for(; *s != (char) c; ++s) +		if (*s == '\0') +			return NULL; +	return (char *) s; +} +#endif + +#ifndef __HAVE_ARCH_STRRCHR +/** + * strrchr - Find the last occurrence of a character in a string + * @s: The string to be searched + * @c: The character to search for + */ +char * strrchr(const char * s, int c) +{ +       const char *p = s + strlen(s); +       do { +	   if (*p == (char)c) +	       return (char *)p; +       } while (--p >= s); +       return NULL; +} +#endif + +#ifndef __HAVE_ARCH_STRLEN +/** + * strlen - Find the length of a string + * @s: The string to be sized + */ +size_t strlen(const char * s) +{ +	const char *sc; + +	for (sc = s; *sc != '\0'; ++sc) +		/* nothing */; +	return sc - s; +} +#endif + +#ifndef __HAVE_ARCH_STRNLEN +/** + * strnlen - Find the length of a length-limited string + * @s: The string to be sized + * @count: The maximum number of bytes to search + */ +size_t strnlen(const char * s, size_t count) +{ +	const char *sc; + +	for (sc = s; count-- && *sc != '\0'; ++sc) +		/* nothing */; +	return sc - s; +} +#endif + +#ifndef __HAVE_ARCH_STRDUP +char * strdup(const char *s) +{ +	char *new; + +	if ((s == NULL)	|| +	    ((new = malloc (strlen(s) + 1)) == NULL) ) { +		return NULL; +	} + +	strcpy (new, s); +	return new; +} +#endif + +#ifndef __HAVE_ARCH_STRSPN +/** + * strspn - Calculate the length of the initial substring of @s which only + *	contain letters in @accept + * @s: The string to be searched + * @accept: The string to search for + */ +size_t strspn(const char *s, const char *accept) +{ +	const char *p; +	const char *a; +	size_t count = 0; + +	for (p = s; *p != '\0'; ++p) { +		for (a = accept; *a != '\0'; ++a) { +			if (*p == *a) +				break; +		} +		if (*a == '\0') +			return count; +		++count; +	} + +	return count; +} +#endif + +#ifndef __HAVE_ARCH_STRPBRK +/** + * strpbrk - Find the first occurrence of a set of characters + * @cs: The string to be searched + * @ct: The characters to search for + */ +char * strpbrk(const char * cs,const char * ct) +{ +	const char *sc1,*sc2; + +	for( sc1 = cs; *sc1 != '\0'; ++sc1) { +		for( sc2 = ct; *sc2 != '\0'; ++sc2) { +			if (*sc1 == *sc2) +				return (char *) sc1; +		} +	} +	return NULL; +} +#endif + +#ifndef __HAVE_ARCH_STRTOK +/** + * strtok - Split a string into tokens + * @s: The string to be searched + * @ct: The characters to search for + * + * WARNING: strtok is deprecated, use strsep instead. + */ +char * strtok(char * s,const char * ct) +{ +	char *sbegin, *send; + +	sbegin  = s ? s : ___strtok; +	if (!sbegin) { +		return NULL; +	} +	sbegin += strspn(sbegin,ct); +	if (*sbegin == '\0') { +		___strtok = NULL; +		return( NULL ); +	} +	send = strpbrk( sbegin, ct); +	if (send && *send != '\0') +		*send++ = '\0'; +	___strtok = send; +	return (sbegin); +} +#endif + +#ifndef __HAVE_ARCH_STRSEP +/** + * strsep - Split a string into tokens + * @s: The string to be searched + * @ct: The characters to search for + * + * strsep() updates @s to point after the token, ready for the next call. + * + * It returns empty tokens, too, behaving exactly like the libc function + * of that name. In fact, it was stolen from glibc2 and de-fancy-fied. + * Same semantics, slimmer shape. ;) + */ +char * strsep(char **s, const char *ct) +{ +	char *sbegin = *s, *end; + +	if (sbegin == NULL) +		return NULL; + +	end = strpbrk(sbegin, ct); +	if (end) +		*end++ = '\0'; +	*s = end; + +	return sbegin; +} +#endif + +#ifndef __HAVE_ARCH_STRSWAB +/** + * strswab - swap adjacent even and odd bytes in %NUL-terminated string + * s: address of the string + * + * returns the address of the swapped string or NULL on error. If + * string length is odd, last byte is untouched. + */ +char *strswab(const char *s) +{ +	char *p, *q; + +	if ((NULL == s) || ('\0' == *s)) { +		return (NULL); +	} + +	for (p=(char *)s, q=p+1; (*p != '\0') && (*q != '\0'); p+=2, q+=2) { +		char  tmp; + +		tmp = *p; +		*p  = *q; +		*q  = tmp; +	} + +	return (char *) s; +} +#endif + +#ifndef __HAVE_ARCH_MEMSET +/** + * memset - Fill a region of memory with the given value + * @s: Pointer to the start of the area. + * @c: The byte to fill the area with + * @count: The size of the area. + * + * Do not use memset() to access IO space, use memset_io() instead. + */ +void * memset(void * s,int c,size_t count) +{ +	unsigned long *sl = (unsigned long *) s; +	unsigned long cl = 0; +	char *s8; +	int i; + +	/* do it one word at a time (32 bits or 64 bits) while possible */ +	if ( ((ulong)s & (sizeof(*sl) - 1)) == 0) { +		for (i = 0; i < sizeof(*sl); i++) { +			cl <<= 8; +			cl |= c & 0xff; +		} +		while (count >= sizeof(*sl)) { +			*sl++ = cl; +			count -= sizeof(*sl); +		} +	} +	/* fill 8 bits at a time */ +	s8 = (char *)sl; +	while (count--) +		*s8++ = c; + +	return s; +} +#endif + +#ifndef __HAVE_ARCH_BCOPY +/** + * bcopy - Copy one area of memory to another + * @src: Where to copy from + * @dest: Where to copy to + * @count: The size of the area. + * + * Note that this is the same as memcpy(), with the arguments reversed. + * memcpy() is the standard, bcopy() is a legacy BSD function. + * + * You should not use this function to access IO space, use memcpy_toio() + * or memcpy_fromio() instead. + */ +char * bcopy(const char * src, char * dest, int count) +{ +	char *tmp = dest; + +	while (count--) +		*tmp++ = *src++; + +	return dest; +} +#endif + +#ifndef __HAVE_ARCH_MEMCPY +/** + * memcpy - Copy one area of memory to another + * @dest: Where to copy to + * @src: Where to copy from + * @count: The size of the area. + * + * You should not use this function to access IO space, use memcpy_toio() + * or memcpy_fromio() instead. + */ +void * memcpy(void *dest, const void *src, size_t count) +{ +	unsigned long *dl = (unsigned long *)dest, *sl = (unsigned long *)src; +	char *d8, *s8; + +	/* while all data is aligned (common case), copy a word at a time */ +	if ( (((ulong)dest | (ulong)src) & (sizeof(*dl) - 1)) == 0) { +		while (count >= sizeof(*dl)) { +			*dl++ = *sl++; +			count -= sizeof(*dl); +		} +	} +	/* copy the reset one byte at a time */ +	d8 = (char *)dl; +	s8 = (char *)sl; +	while (count--) +		*d8++ = *s8++; + +	return dest; +} +#endif + +#ifndef __HAVE_ARCH_MEMMOVE +/** + * memmove - Copy one area of memory to another + * @dest: Where to copy to + * @src: Where to copy from + * @count: The size of the area. + * + * Unlike memcpy(), memmove() copes with overlapping areas. + */ +void * memmove(void * dest,const void *src,size_t count) +{ +	char *tmp, *s; + +	if (dest <= src) { +		tmp = (char *) dest; +		s = (char *) src; +		while (count--) +			*tmp++ = *s++; +		} +	else { +		tmp = (char *) dest + count; +		s = (char *) src + count; +		while (count--) +			*--tmp = *--s; +		} + +	return dest; +} +#endif + +#ifndef __HAVE_ARCH_MEMCMP +/** + * memcmp - Compare two areas of memory + * @cs: One area of memory + * @ct: Another area of memory + * @count: The size of the area. + */ +int memcmp(const void * cs,const void * ct,size_t count) +{ +	const unsigned char *su1, *su2; +	int res = 0; + +	for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) +		if ((res = *su1 - *su2) != 0) +			break; +	return res; +} +#endif + +#ifndef __HAVE_ARCH_MEMSCAN +/** + * memscan - Find a character in an area of memory. + * @addr: The memory area + * @c: The byte to search for + * @size: The size of the area. + * + * returns the address of the first occurrence of @c, or 1 byte past + * the area if @c is not found + */ +void * memscan(void * addr, int c, size_t size) +{ +	unsigned char * p = (unsigned char *) addr; + +	while (size) { +		if (*p == c) +			return (void *) p; +		p++; +		size--; +	} +	return (void *) p; +} +#endif + +#ifndef __HAVE_ARCH_STRSTR +/** + * strstr - Find the first substring in a %NUL terminated string + * @s1: The string to be searched + * @s2: The string to search for + */ +char * strstr(const char * s1,const char * s2) +{ +	int l1, l2; + +	l2 = strlen(s2); +	if (!l2) +		return (char *) s1; +	l1 = strlen(s1); +	while (l1 >= l2) { +		l1--; +		if (!memcmp(s1,s2,l2)) +			return (char *) s1; +		s1++; +	} +	return NULL; +} +#endif + +#ifndef __HAVE_ARCH_MEMCHR +/** + * memchr - Find a character in an area of memory. + * @s: The memory area + * @c: The byte to search for + * @n: The size of the area. + * + * returns the address of the first occurrence of @c, or %NULL + * if @c is not found + */ +void *memchr(const void *s, int c, size_t n) +{ +	const unsigned char *p = s; +	while (n-- != 0) { +		if ((unsigned char)c == *p++) { +			return (void *)(p-1); +		} +	} +	return NULL; +} + +#endif |