// SPDX-License-Identifier: GPL-2.01/*2* linux/tools/lib/string.c3*4* Copied from linux/lib/string.c, where it is:5*6* Copyright (C) 1991, 1992 Linus Torvalds7*8* More specifically, the first copied function was strtobool, which9* was introduced by:10*11* d0f1fed29e6e ("Add a strtobool function matching semantics of existing in kernel equivalents")12* Author: Jonathan Cameron <[email protected]>13*/1415#include <stdlib.h>16#include <string.h>17#include <errno.h>18#include <linux/string.h>19#include <linux/ctype.h>20#include <linux/compiler.h>2122/**23* memdup - duplicate region of memory24*25* @src: memory region to duplicate26* @len: memory region length27*/28void *memdup(const void *src, size_t len)29{30void *p = malloc(len);3132if (p)33memcpy(p, src, len);3435return p;36}3738/**39* strtobool - convert common user inputs into boolean values40* @s: input string41* @res: result42*43* This routine returns 0 iff the first character is one of 'Yy1Nn0', or44* [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL. Value45* pointed to by res is updated upon finding a match.46*/47int strtobool(const char *s, bool *res)48{49if (!s)50return -EINVAL;5152switch (s[0]) {53case 'y':54case 'Y':55case '1':56*res = true;57return 0;58case 'n':59case 'N':60case '0':61*res = false;62return 0;63case 'o':64case 'O':65switch (s[1]) {66case 'n':67case 'N':68*res = true;69return 0;70case 'f':71case 'F':72*res = false;73return 0;74default:75break;76}77default:78break;79}8081return -EINVAL;82}8384/**85* strlcpy - Copy a C-string into a sized buffer86* @dest: Where to copy the string to87* @src: Where to copy the string from88* @size: size of destination buffer89*90* Compatible with *BSD: the result is always a valid91* NUL-terminated string that fits in the buffer (unless,92* of course, the buffer size is zero). It does not pad93* out the result like strncpy() does.94*95* If libc has strlcpy() then that version will override this96* implementation:97*/98#ifdef __clang__99#pragma clang diagnostic push100#pragma clang diagnostic ignored "-Wignored-attributes"101#endif102size_t __weak strlcpy(char *dest, const char *src, size_t size)103{104size_t ret = strlen(src);105106if (size) {107size_t len = (ret >= size) ? size - 1 : ret;108memcpy(dest, src, len);109dest[len] = '\0';110}111return ret;112}113#ifdef __clang__114#pragma clang diagnostic pop115#endif116117/**118* skip_spaces - Removes leading whitespace from @str.119* @str: The string to be stripped.120*121* Returns a pointer to the first non-whitespace character in @str.122*/123char *skip_spaces(const char *str)124{125while (isspace(*str))126++str;127return (char *)str;128}129130/**131* strim - Removes leading and trailing whitespace from @s.132* @s: The string to be stripped.133*134* Note that the first trailing whitespace is replaced with a %NUL-terminator135* in the given string @s. Returns a pointer to the first non-whitespace136* character in @s.137*/138char *strim(char *s)139{140size_t size;141char *end;142143size = strlen(s);144if (!size)145return s;146147end = s + size - 1;148while (end >= s && isspace(*end))149end--;150*(end + 1) = '\0';151152return skip_spaces(s);153}154155/*156* remove_spaces - Removes whitespaces from @s157*/158void remove_spaces(char *s)159{160char *d = s;161162do {163while (*d == ' ')164++d;165} while ((*s++ = *d++));166}167168/**169* strreplace - Replace all occurrences of character in string.170* @s: The string to operate on.171* @old: The character being replaced.172* @new: The character @old is replaced with.173*174* Returns pointer to the nul byte at the end of @s.175*/176char *strreplace(char *s, char old, char new)177{178for (; *s; ++s)179if (*s == old)180*s = new;181return s;182}183184static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes)185{186while (bytes) {187if (*start != value)188return (void *)start;189start++;190bytes--;191}192return NULL;193}194195/**196* memchr_inv - Find an unmatching character in an area of memory.197* @start: The memory area198* @c: Find a character other than c199* @bytes: The size of the area.200*201* returns the address of the first character other than @c, or %NULL202* if the whole buffer contains just @c.203*/204void *memchr_inv(const void *start, int c, size_t bytes)205{206u8 value = c;207u64 value64;208unsigned int words, prefix;209210if (bytes <= 16)211return check_bytes8(start, value, bytes);212213value64 = value;214value64 |= value64 << 8;215value64 |= value64 << 16;216value64 |= value64 << 32;217218prefix = (unsigned long)start % 8;219if (prefix) {220u8 *r;221222prefix = 8 - prefix;223r = check_bytes8(start, value, prefix);224if (r)225return r;226start += prefix;227bytes -= prefix;228}229230words = bytes / 8;231232while (words) {233if (*(u64 *)start != value64)234return check_bytes8(start, value, 8);235start += 8;236words--;237}238239return check_bytes8(start, value, bytes % 8);240}241242243