9
0
Fork 0

string: introduce memchr_inv

Directly taken from Linux Kernel.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Sascha Hauer 2013-07-18 14:26:44 +02:00
parent bdfd6a629c
commit b445152396
2 changed files with 61 additions and 0 deletions

View File

@ -106,6 +106,8 @@ extern char * skip_spaces(const char *);
extern char *strim(char *);
void *memchr_inv(const void *start, int c, size_t bytes);
#ifdef __cplusplus
}
#endif

View File

@ -666,3 +666,62 @@ char *strim(char *s)
return s;
}
EXPORT_SYMBOL(strim);
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);
}
EXPORT_SYMBOL(memchr_inv);