forked from Minki/linux
tools lib: Adopt memchr_inv() from kernel
We'll use it to check for undefined/zero data. Signed-off-by: Jiri Olsa <jolsa@kernel.org> Suggested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Alexey Budankov <alexey.budankov@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Song Liu <songliubraving@fb.com> Cc: Stephane Eranian <eranian@google.com> Link: http://lore.kernel.org/lkml/20201126170026.2619053-6-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
05e91e7fe2
commit
b3e453272d
@ -46,4 +46,5 @@ extern char * __must_check skip_spaces(const char *);
|
||||
|
||||
extern char *strim(char *);
|
||||
|
||||
extern void *memchr_inv(const void *start, int c, size_t bytes);
|
||||
#endif /* _TOOLS_LINUX_STRING_H_ */
|
||||
|
@ -168,3 +168,61 @@ char *strreplace(char *s, char old, char new)
|
||||
*s = new;
|
||||
return s;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user