1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * linux/tools/lib/string.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copied from linux/lib/string.c, where it is:
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (C) 1991, 1992 Linus Torvalds
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * More specifically, the first copied function was strtobool, which
10*4882a593Smuzhiyun * was introduced by:
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * d0f1fed29e6e ("Add a strtobool function matching semantics of existing in kernel equivalents")
13*4882a593Smuzhiyun * Author: Jonathan Cameron <jic23@cam.ac.uk>
14*4882a593Smuzhiyun */
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include <stdlib.h>
17*4882a593Smuzhiyun #include <string.h>
18*4882a593Smuzhiyun #include <errno.h>
19*4882a593Smuzhiyun #include <linux/string.h>
20*4882a593Smuzhiyun #include <linux/ctype.h>
21*4882a593Smuzhiyun #include <linux/compiler.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun /**
24*4882a593Smuzhiyun * memdup - duplicate region of memory
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun * @src: memory region to duplicate
27*4882a593Smuzhiyun * @len: memory region length
28*4882a593Smuzhiyun */
memdup(const void * src,size_t len)29*4882a593Smuzhiyun void *memdup(const void *src, size_t len)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun void *p = malloc(len);
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun if (p)
34*4882a593Smuzhiyun memcpy(p, src, len);
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun return p;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /**
40*4882a593Smuzhiyun * strtobool - convert common user inputs into boolean values
41*4882a593Smuzhiyun * @s: input string
42*4882a593Smuzhiyun * @res: result
43*4882a593Smuzhiyun *
44*4882a593Smuzhiyun * This routine returns 0 iff the first character is one of 'Yy1Nn0', or
45*4882a593Smuzhiyun * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL. Value
46*4882a593Smuzhiyun * pointed to by res is updated upon finding a match.
47*4882a593Smuzhiyun */
strtobool(const char * s,bool * res)48*4882a593Smuzhiyun int strtobool(const char *s, bool *res)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun if (!s)
51*4882a593Smuzhiyun return -EINVAL;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun switch (s[0]) {
54*4882a593Smuzhiyun case 'y':
55*4882a593Smuzhiyun case 'Y':
56*4882a593Smuzhiyun case '1':
57*4882a593Smuzhiyun *res = true;
58*4882a593Smuzhiyun return 0;
59*4882a593Smuzhiyun case 'n':
60*4882a593Smuzhiyun case 'N':
61*4882a593Smuzhiyun case '0':
62*4882a593Smuzhiyun *res = false;
63*4882a593Smuzhiyun return 0;
64*4882a593Smuzhiyun case 'o':
65*4882a593Smuzhiyun case 'O':
66*4882a593Smuzhiyun switch (s[1]) {
67*4882a593Smuzhiyun case 'n':
68*4882a593Smuzhiyun case 'N':
69*4882a593Smuzhiyun *res = true;
70*4882a593Smuzhiyun return 0;
71*4882a593Smuzhiyun case 'f':
72*4882a593Smuzhiyun case 'F':
73*4882a593Smuzhiyun *res = false;
74*4882a593Smuzhiyun return 0;
75*4882a593Smuzhiyun default:
76*4882a593Smuzhiyun break;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun default:
79*4882a593Smuzhiyun break;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun return -EINVAL;
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /**
86*4882a593Smuzhiyun * strlcpy - Copy a C-string into a sized buffer
87*4882a593Smuzhiyun * @dest: Where to copy the string to
88*4882a593Smuzhiyun * @src: Where to copy the string from
89*4882a593Smuzhiyun * @size: size of destination buffer
90*4882a593Smuzhiyun *
91*4882a593Smuzhiyun * Compatible with *BSD: the result is always a valid
92*4882a593Smuzhiyun * NUL-terminated string that fits in the buffer (unless,
93*4882a593Smuzhiyun * of course, the buffer size is zero). It does not pad
94*4882a593Smuzhiyun * out the result like strncpy() does.
95*4882a593Smuzhiyun *
96*4882a593Smuzhiyun * If libc has strlcpy() then that version will override this
97*4882a593Smuzhiyun * implementation:
98*4882a593Smuzhiyun */
99*4882a593Smuzhiyun #ifdef __clang__
100*4882a593Smuzhiyun #pragma clang diagnostic push
101*4882a593Smuzhiyun #pragma clang diagnostic ignored "-Wignored-attributes"
102*4882a593Smuzhiyun #endif
strlcpy(char * dest,const char * src,size_t size)103*4882a593Smuzhiyun size_t __weak strlcpy(char *dest, const char *src, size_t size)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun size_t ret = strlen(src);
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun if (size) {
108*4882a593Smuzhiyun size_t len = (ret >= size) ? size - 1 : ret;
109*4882a593Smuzhiyun memcpy(dest, src, len);
110*4882a593Smuzhiyun dest[len] = '\0';
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun return ret;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun #ifdef __clang__
115*4882a593Smuzhiyun #pragma clang diagnostic pop
116*4882a593Smuzhiyun #endif
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /**
119*4882a593Smuzhiyun * skip_spaces - Removes leading whitespace from @str.
120*4882a593Smuzhiyun * @str: The string to be stripped.
121*4882a593Smuzhiyun *
122*4882a593Smuzhiyun * Returns a pointer to the first non-whitespace character in @str.
123*4882a593Smuzhiyun */
skip_spaces(const char * str)124*4882a593Smuzhiyun char *skip_spaces(const char *str)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun while (isspace(*str))
127*4882a593Smuzhiyun ++str;
128*4882a593Smuzhiyun return (char *)str;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun /**
132*4882a593Smuzhiyun * strim - Removes leading and trailing whitespace from @s.
133*4882a593Smuzhiyun * @s: The string to be stripped.
134*4882a593Smuzhiyun *
135*4882a593Smuzhiyun * Note that the first trailing whitespace is replaced with a %NUL-terminator
136*4882a593Smuzhiyun * in the given string @s. Returns a pointer to the first non-whitespace
137*4882a593Smuzhiyun * character in @s.
138*4882a593Smuzhiyun */
strim(char * s)139*4882a593Smuzhiyun char *strim(char *s)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun size_t size;
142*4882a593Smuzhiyun char *end;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun size = strlen(s);
145*4882a593Smuzhiyun if (!size)
146*4882a593Smuzhiyun return s;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun end = s + size - 1;
149*4882a593Smuzhiyun while (end >= s && isspace(*end))
150*4882a593Smuzhiyun end--;
151*4882a593Smuzhiyun *(end + 1) = '\0';
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun return skip_spaces(s);
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun /**
157*4882a593Smuzhiyun * strreplace - Replace all occurrences of character in string.
158*4882a593Smuzhiyun * @s: The string to operate on.
159*4882a593Smuzhiyun * @old: The character being replaced.
160*4882a593Smuzhiyun * @new: The character @old is replaced with.
161*4882a593Smuzhiyun *
162*4882a593Smuzhiyun * Returns pointer to the nul byte at the end of @s.
163*4882a593Smuzhiyun */
strreplace(char * s,char old,char new)164*4882a593Smuzhiyun char *strreplace(char *s, char old, char new)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun for (; *s; ++s)
167*4882a593Smuzhiyun if (*s == old)
168*4882a593Smuzhiyun *s = new;
169*4882a593Smuzhiyun return s;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun
check_bytes8(const u8 * start,u8 value,unsigned int bytes)172*4882a593Smuzhiyun static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun while (bytes) {
175*4882a593Smuzhiyun if (*start != value)
176*4882a593Smuzhiyun return (void *)start;
177*4882a593Smuzhiyun start++;
178*4882a593Smuzhiyun bytes--;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun return NULL;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun /**
184*4882a593Smuzhiyun * memchr_inv - Find an unmatching character in an area of memory.
185*4882a593Smuzhiyun * @start: The memory area
186*4882a593Smuzhiyun * @c: Find a character other than c
187*4882a593Smuzhiyun * @bytes: The size of the area.
188*4882a593Smuzhiyun *
189*4882a593Smuzhiyun * returns the address of the first character other than @c, or %NULL
190*4882a593Smuzhiyun * if the whole buffer contains just @c.
191*4882a593Smuzhiyun */
memchr_inv(const void * start,int c,size_t bytes)192*4882a593Smuzhiyun void *memchr_inv(const void *start, int c, size_t bytes)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun u8 value = c;
195*4882a593Smuzhiyun u64 value64;
196*4882a593Smuzhiyun unsigned int words, prefix;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun if (bytes <= 16)
199*4882a593Smuzhiyun return check_bytes8(start, value, bytes);
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun value64 = value;
202*4882a593Smuzhiyun value64 |= value64 << 8;
203*4882a593Smuzhiyun value64 |= value64 << 16;
204*4882a593Smuzhiyun value64 |= value64 << 32;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun prefix = (unsigned long)start % 8;
207*4882a593Smuzhiyun if (prefix) {
208*4882a593Smuzhiyun u8 *r;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun prefix = 8 - prefix;
211*4882a593Smuzhiyun r = check_bytes8(start, value, prefix);
212*4882a593Smuzhiyun if (r)
213*4882a593Smuzhiyun return r;
214*4882a593Smuzhiyun start += prefix;
215*4882a593Smuzhiyun bytes -= prefix;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun words = bytes / 8;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun while (words) {
221*4882a593Smuzhiyun if (*(u64 *)start != value64)
222*4882a593Smuzhiyun return check_bytes8(start, value, 8);
223*4882a593Smuzhiyun start += 8;
224*4882a593Smuzhiyun words--;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun return check_bytes8(start, value, bytes % 8);
228*4882a593Smuzhiyun }
229