brintos

brintos / linux-shallow public Read only

0
0
Text · 7.4 KiB · 116a642 Raw
352 lines · c
1// SPDX-License-Identifier: GPL-2.02#include "string2.h"3#include <linux/kernel.h>4#include <linux/string.h>5#include <stdlib.h>6 7#include <linux/ctype.h>8 9const char *graph_dotted_line =10	"---------------------------------------------------------------------"11	"---------------------------------------------------------------------"12	"---------------------------------------------------------------------";13const char *dots =14	"....................................................................."15	"....................................................................."16	".....................................................................";17 18/*19 * perf_atoll()20 * Parse (\d+)(b|B|kb|KB|mb|MB|gb|GB|tb|TB) (e.g. "256MB")21 * and return its numeric value22 */23s64 perf_atoll(const char *str)24{25	s64 length;26	char *p;27	char c;28 29	if (!isdigit(str[0]))30		goto out_err;31 32	length = strtoll(str, &p, 10);33	switch (c = *p++) {34		case 'b': case 'B':35			if (*p)36				goto out_err;37 38			fallthrough;39		case '\0':40			return length;41		default:42			goto out_err;43		/* two-letter suffices */44		case 'k': case 'K':45			length <<= 10;46			break;47		case 'm': case 'M':48			length <<= 20;49			break;50		case 'g': case 'G':51			length <<= 30;52			break;53		case 't': case 'T':54			length <<= 40;55			break;56	}57	/* we want the cases to match */58	if (islower(c)) {59		if (strcmp(p, "b") != 0)60			goto out_err;61	} else {62		if (strcmp(p, "B") != 0)63			goto out_err;64	}65	return length;66 67out_err:68	return -1;69}70 71/* Character class matching */72static bool __match_charclass(const char *pat, char c, const char **npat)73{74	bool complement = false, ret = true;75 76	if (*pat == '!') {77		complement = true;78		pat++;79	}80	if (*pat++ == c)	/* First character is special */81		goto end;82 83	while (*pat && *pat != ']') {	/* Matching */84		if (*pat == '-' && *(pat + 1) != ']') {	/* Range */85			if (*(pat - 1) <= c && c <= *(pat + 1))86				goto end;87			if (*(pat - 1) > *(pat + 1))88				goto error;89			pat += 2;90		} else if (*pat++ == c)91			goto end;92	}93	if (!*pat)94		goto error;95	ret = false;96 97end:98	while (*pat && *pat != ']')	/* Searching closing */99		pat++;100	if (!*pat)101		goto error;102	*npat = pat + 1;103	return complement ? !ret : ret;104 105error:106	return false;107}108 109/* Glob/lazy pattern matching */110static bool __match_glob(const char *str, const char *pat, bool ignore_space,111			bool case_ins)112{113	while (*str && *pat && *pat != '*') {114		if (ignore_space) {115			/* Ignore spaces for lazy matching */116			if (isspace(*str)) {117				str++;118				continue;119			}120			if (isspace(*pat)) {121				pat++;122				continue;123			}124		}125		if (*pat == '?') {	/* Matches any single character */126			str++;127			pat++;128			continue;129		} else if (*pat == '[')	/* Character classes/Ranges */130			if (__match_charclass(pat + 1, *str, &pat)) {131				str++;132				continue;133			} else134				return false;135		else if (*pat == '\\') /* Escaped char match as normal char */136			pat++;137		if (case_ins) {138			if (tolower(*str) != tolower(*pat))139				return false;140		} else if (*str != *pat)141			return false;142		str++;143		pat++;144	}145	/* Check wild card */146	if (*pat == '*') {147		while (*pat == '*')148			pat++;149		if (!*pat)	/* Tail wild card matches all */150			return true;151		while (*str)152			if (__match_glob(str++, pat, ignore_space, case_ins))153				return true;154	}155	return !*str && !*pat;156}157 158/**159 * strglobmatch - glob expression pattern matching160 * @str: the target string to match161 * @pat: the pattern string to match162 *163 * This returns true if the @str matches @pat. @pat can includes wildcards164 * ('*','?') and character classes ([CHARS], complementation and ranges are165 * also supported). Also, this supports escape character ('\') to use special166 * characters as normal character.167 *168 * Note: if @pat syntax is broken, this always returns false.169 */170bool strglobmatch(const char *str, const char *pat)171{172	return __match_glob(str, pat, false, false);173}174 175bool strglobmatch_nocase(const char *str, const char *pat)176{177	return __match_glob(str, pat, false, true);178}179 180/**181 * strlazymatch - matching pattern strings lazily with glob pattern182 * @str: the target string to match183 * @pat: the pattern string to match184 *185 * This is similar to strglobmatch, except this ignores spaces in186 * the target string.187 */188bool strlazymatch(const char *str, const char *pat)189{190	return __match_glob(str, pat, true, false);191}192 193/**194 * strtailcmp - Compare the tail of two strings195 * @s1: 1st string to be compared196 * @s2: 2nd string to be compared197 *198 * Return 0 if whole of either string is same as another's tail part.199 */200int strtailcmp(const char *s1, const char *s2)201{202	int i1 = strlen(s1);203	int i2 = strlen(s2);204	while (--i1 >= 0 && --i2 >= 0) {205		if (s1[i1] != s2[i2])206			return s1[i1] - s2[i2];207	}208	return 0;209}210 211char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints)212{213	/*214	 * FIXME: replace this with an expression using log10() when we215	 * find a suitable implementation, maybe the one in the dvb drivers...216	 *217	 * "%s == %d || " = log10(MAXINT) * 2 + 8 chars for the operators218	 */219	size_t size = nints * 28 + 1; /* \0 */220	size_t i, printed = 0;221	char *expr = malloc(size);222 223	if (expr) {224		const char *or_and = "||", *eq_neq = "==";225		char *e = expr;226 227		if (!in) {228			or_and = "&&";229			eq_neq = "!=";230		}231 232		for (i = 0; i < nints; ++i) {233			if (printed == size)234				goto out_err_overflow;235 236			if (i > 0)237				printed += scnprintf(e + printed, size - printed, " %s ", or_and);238			printed += scnprintf(e + printed, size - printed,239					     "%s %s %d", var, eq_neq, ints[i]);240		}241	}242 243	return expr;244 245out_err_overflow:246	free(expr);247	return NULL;248}249 250/* Like strpbrk(), but not break if it is right after a backslash (escaped) */251char *strpbrk_esc(char *str, const char *stopset)252{253	char *ptr;254 255	do {256		ptr = strpbrk(str, stopset);257		if (ptr == str ||258		    (ptr == str + 1 && *(ptr - 1) != '\\'))259			break;260		str = ptr + 1;261	} while (ptr && *(ptr - 1) == '\\' && *(ptr - 2) != '\\');262 263	return ptr;264}265 266/* Like strdup, but do not copy a single backslash */267char *strdup_esc(const char *str)268{269	char *s, *d, *p, *ret = strdup(str);270 271	if (!ret)272		return NULL;273 274	d = strchr(ret, '\\');275	if (!d)276		return ret;277 278	s = d + 1;279	do {280		if (*s == '\0') {281			*d = '\0';282			break;283		}284		p = strchr(s + 1, '\\');285		if (p) {286			memmove(d, s, p - s);287			d += p - s;288			s = p + 1;289		} else290			memmove(d, s, strlen(s) + 1);291	} while (p);292 293	return ret;294}295 296unsigned int hex(char c)297{298	if (c >= '0' && c <= '9')299		return c - '0';300	if (c >= 'a' && c <= 'f')301		return c - 'a' + 10;302	return c - 'A' + 10;303}304 305/*306 * Replace all occurrences of character 'needle' in string 'haystack' with307 * string 'replace'308 *309 * The new string could be longer so a new string is returned which must be310 * freed.311 */312char *strreplace_chars(char needle, const char *haystack, const char *replace)313{314	int replace_len = strlen(replace);315	char *new_s, *to;316	const char *loc = strchr(haystack, needle);317	const char *from = haystack;318	int num = 0;319 320	/* Count occurrences */321	while (loc) {322		loc = strchr(loc + 1, needle);323		num++;324	}325 326	/* Allocate enough space for replacements and reset first location */327	new_s = malloc(strlen(haystack) + (num * (replace_len - 1) + 1));328	if (!new_s)329		return NULL;330	loc = strchr(haystack, needle);331	to = new_s;332 333	while (loc) {334		/* Copy original string up to found char and update positions */335		memcpy(to, from, 1 + loc - from);336		to += loc - from;337		from = loc + 1;338 339		/* Copy replacement string and update positions */340		memcpy(to, replace, replace_len);341		to += replace_len;342 343		/* needle next occurrence or end of string */344		loc = strchr(from, needle);345	}346 347	/* Copy any remaining chars + null */348	strcpy(to, from);349 350	return new_s;351}352