X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Fstring.c;h=78bd65c41369cd5b0050b75013bc97bbc7b5bda5;hb=c55094f14d3362c9bceba867d0faecc733125f83;hp=2c4f0ec9a11f8e7219b9c5d40659616bf4bc6aaf;hpb=1902692aa0b2dcbb9351172be03c57d1e82447e4;p=platform%2Fkernel%2Fu-boot.git diff --git a/lib/string.c b/lib/string.c index 2c4f0ec..78bd65c 100644 --- a/lib/string.c +++ b/lib/string.c @@ -15,20 +15,21 @@ * reentrant and should be faster). Use only strsep() in new code, please. */ +#include +#include #include #include #include #include -#if 0 /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */ /** - * strnicmp - Case insensitive, length-limited string comparison + * strncasecmp - 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) +int strncasecmp(const char *s1, const char *s2, size_t len) { /* Yes, Virginia, it had better be unsigned */ unsigned char c1, c2; @@ -52,7 +53,16 @@ int strnicmp(const char *s1, const char *s2, size_t len) } return (int)c1 - (int)c2; } -#endif + +/** + * strcasecmp - Case insensitive string comparison + * @s1: One string + * @s2: The other string + */ +int strcasecmp(const char *s1, const char *s2) +{ + return strncasecmp(s1, s2, -1U); +} char * ___strtok; @@ -94,6 +104,35 @@ char * strncpy(char * dest,const char *src,size_t count) } #endif +#ifndef __HAVE_ARCH_STRLCPY +/** + * strlcpy - Copy a C-string into a sized buffer + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @size: size of destination buffer + * + * Compatible with *BSD: the result is always a valid + * NUL-terminated string that fits in the buffer (unless, + * of course, the buffer size is zero). It does not pad + * out the result like strncpy() does. + * + * Return: the number of bytes copied + */ +size_t strlcpy(char *dest, const char *src, size_t size) +{ + if (size) { + size_t srclen = strlen(src); + size_t len = (srclen >= size) ? size - 1 : srclen; + + memcpy(dest, src, len); + dest[len] = '\0'; + return len + 1; + } + + return 0; +} +#endif + #ifndef __HAVE_ARCH_STRCAT /** * strcat - Append one %NUL-terminated string to another @@ -142,6 +181,25 @@ char * strncat(char *dest, const char *src, size_t count) } #endif +#ifndef __HAVE_ARCH_STRLCAT +/** + * strlcat - Append a length-limited, %NUL-terminated string to another + * @dest: The string to be appended to + * @src: The string to append to it + * @size: The size of @dest + * + * Compatible with *BSD: the result is always a valid NUL-terminated string that + * fits in the buffer (unless, of course, the buffer size is zero). It does not + * write past @size like strncat() does. + */ +size_t strlcat(char *dest, const char *src, size_t size) +{ + size_t len = strnlen(dest, size); + + return len + strlcpy(dest + len, src, size - len); +} +#endif + #ifndef __HAVE_ARCH_STRCMP /** * strcmp - Compare two strings @@ -197,6 +255,14 @@ char * strchr(const char * s, int c) } #endif +const char *strchrnul(const char *s, int c) +{ + for (; *s != (char)c; ++s) + if (*s == '\0') + break; + return s; +} + #ifndef __HAVE_ARCH_STRRCHR /** * strrchr - Find the last occurrence of a character in a string @@ -245,6 +311,30 @@ size_t strnlen(const char * s, size_t count) } #endif +#ifndef __HAVE_ARCH_STRCSPN +/** + * strcspn - Calculate the length of the initial substring of @s which does + * not contain letters in @reject + * @s: The string to be searched + * @reject: The string to avoid + */ +size_t strcspn(const char *s, const char *reject) +{ + const char *p; + const char *r; + size_t count = 0; + + for (p = s; *p != '\0'; ++p) { + for (r = reject; *r != '\0'; ++r) { + if (*p == *r) + return count; + } + ++count; + } + return count; +} +#endif + #ifndef __HAVE_ARCH_STRDUP char * strdup(const char *s) { @@ -258,6 +348,29 @@ char * strdup(const char *s) strcpy (new, s); return new; } + +char * strndup(const char *s, size_t n) +{ + size_t len; + char *new; + + if (s == NULL) + return NULL; + + len = strlen(s); + + if (n < len) + len = n; + + new = malloc(len + 1); + if (new == NULL) + return NULL; + + strncpy(new, s, len); + new[len] = '\0'; + + return new; +} #endif #ifndef __HAVE_ARCH_STRSPN @@ -401,11 +514,13 @@ char *strswab(const char *s) * * Do not use memset() to access IO space, use memset_io() instead. */ -void * memset(void * s,int c,size_t count) +__used void * memset(void * s,int c,size_t count) { unsigned long *sl = (unsigned long *) s; - unsigned long cl = 0; char *s8; + +#if !CONFIG_IS_ENABLED(TINY_MEMSET) + unsigned long cl = 0; int i; /* do it one word at a time (32 bits or 64 bits) while possible */ @@ -419,7 +534,7 @@ void * memset(void * s,int c,size_t count) count -= sizeof(*sl); } } - /* fill 8 bits at a time */ +#endif /* fill 8 bits at a time */ s8 = (char *)sl; while (count--) *s8++ = c; @@ -428,30 +543,6 @@ void * memset(void * s,int c,size_t count) } #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 @@ -462,7 +553,7 @@ char * bcopy(const char * src, char * dest, int count) * 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) +__used void * memcpy(void *dest, const void *src, size_t count) { unsigned long *dl = (unsigned long *)dest, *sl = (unsigned long *)src; char *d8, *s8; @@ -496,20 +587,25 @@ void * memcpy(void *dest, const void *src, size_t count) * * Unlike memcpy(), memmove() copes with overlapping areas. */ -void * memmove(void * dest,const void *src,size_t count) +__used void * memmove(void * dest,const void *src,size_t count) { char *tmp, *s; - if (src == dest) - return dest; - - if (dest <= src) { - tmp = (char *) dest; - s = (char *) src; - while (count--) - *tmp++ = *s++; - } - else { + if (dest <= src || (src + count) <= dest) { + /* + * Use the fast memcpy implementation (ARCH optimized or lib/string.c) when it is possible: + * - when dest is before src (assuming that memcpy is doing forward-copying) + * - when destination don't overlap the source buffer (src + count <= dest) + * + * WARNING: the first optimisation cause an issue, when __HAVE_ARCH_MEMCPY is defined, + * __HAVE_ARCH_MEMMOVE is not defined and if the memcpy ARCH-specific + * implementation is not doing a forward-copying. + * + * No issue today because memcpy is doing a forward-copying in lib/string.c and for ARM32 + * architecture; no other arches use __HAVE_ARCH_MEMCPY without __HAVE_ARCH_MEMMOVE. + */ + memcpy(dest, src, count); + } else { tmp = (char *) dest + count; s = (char *) src + count; while (count--) @@ -527,7 +623,7 @@ void * memmove(void * dest,const void *src,size_t count) * @ct: Another area of memory * @count: The size of the area. */ -int memcmp(const void * cs,const void * ct,size_t count) +__used int memcmp(const void * cs,const void * ct,size_t count) { const unsigned char *su1, *su2; int res = 0; @@ -563,6 +659,19 @@ void * memscan(void * addr, int c, size_t size) } #endif +char *memdup(const void *src, size_t len) +{ + char *p; + + p = malloc(len); + if (!p) + return NULL; + + memcpy(p, src, len); + + return p; +} + #ifndef __HAVE_ARCH_STRSTR /** * strstr - Find the first substring in a %NUL terminated string @@ -609,3 +718,61 @@ void *memchr(const void *s, int c, size_t n) } #endif +#ifndef __HAVE_ARCH_MEMCHR_INV +static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes) +{ + while (bytes) { + if (*start != value) + return (void *)start; + start++; + bytes--; + } + return NULL; +} +/** + * memchr_inv - Find an unmatching character in an area of memory. + * @start: The memory area + * @c: Find a character other than c + * @bytes: The size of the area. + * + * returns the address of the first character other than @c, or %NULL + * if the whole buffer contains just @c. + */ +void *memchr_inv(const void *start, int c, size_t bytes) +{ + u8 value = c; + u64 value64; + unsigned int words, prefix; + + if (bytes <= 16) + return check_bytes8(start, value, bytes); + + value64 = value; + value64 |= value64 << 8; + value64 |= value64 << 16; + value64 |= value64 << 32; + + prefix = (unsigned long)start % 8; + if (prefix) { + u8 *r; + + prefix = 8 - prefix; + r = check_bytes8(start, value, prefix); + if (r) + return r; + start += prefix; + bytes -= prefix; + } + + words = bytes / 8; + + while (words) { + if (*(u64 *)start != value64) + return check_bytes8(start, value, 8); + start += 8; + words--; + } + + return check_bytes8(start, value, bytes % 8); +} +#endif