From 798248206b59acc6e1238c778281419c041891a7 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 31 Oct 2011 17:08:07 -0700 Subject: lib/string.c: introduce memchr_inv() memchr_inv() is mainly used to check whether the whole buffer is filled with just a specified byte. The function name and prototype are stolen from logfs and the implementation is from SLUB. Signed-off-by: Akinobu Mita Acked-by: Christoph Lameter Acked-by: Pekka Enberg Cc: Matt Mackall Acked-by: Joern Engel Cc: Marcin Slusarz Cc: Eric Dumazet Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/string.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'lib/string.c') diff --git a/lib/string.c b/lib/string.c index 01fad9b203e..11df54325fb 100644 --- a/lib/string.c +++ b/lib/string.c @@ -756,3 +756,57 @@ void *memchr(const void *s, int c, size_t n) } EXPORT_SYMBOL(memchr); #endif + +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 | value << 8 | value << 16 | value << 24; + value64 = (value64 & 0xffffffff) | value64 << 32; + prefix = 8 - ((unsigned long)start) % 8; + + if (prefix) { + u8 *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); -- cgit v1.2.3-70-g09d2 From 66f6958e69d8055277356d3cc2e7a1d734db1755 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Mon, 31 Oct 2011 17:12:37 -0700 Subject: lib/string.c: fix strim() semantics for strings that have only blanks Commit 84c95c9acf0 ("string: on strstrip(), first remove leading spaces before running over str") improved the performance of the strim() function. Unfortunately this changed the semantics of strim() and broke my code. Before the patch it was possible to use strim() without using the return value for removing trailing spaces from strings that had either only blanks or only trailing blanks. Now this does not work any longer for strings that *only* have blanks. Before patch: " " -> "" (empty string) After patch: " " -> " " (no change) I think we should remove your patch to restore the old behavior. The description (lib/string.c): * Note that the first trailing whitespace is replaced with a %NUL-terminator => The first trailing whitespace of a string that only has whitespace characters is the first whitespace The patch restores the old strim() semantics. Signed-off-by: Michael Holzheu Cc: Andre Goddard Rosa Cc: Martin Schwidefsky Cc: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/string.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/string.c') diff --git a/lib/string.c b/lib/string.c index 11df54325fb..dc4a86341f9 100644 --- a/lib/string.c +++ b/lib/string.c @@ -360,7 +360,6 @@ char *strim(char *s) size_t size; char *end; - s = skip_spaces(s); size = strlen(s); if (!size) return s; @@ -370,7 +369,7 @@ char *strim(char *s) end--; *(end + 1) = '\0'; - return s; + return skip_spaces(s); } EXPORT_SYMBOL(strim); -- cgit v1.2.3-70-g09d2