lib/kstrtox.c

Source file repositories/reference/linux-study-clean/lib/kstrtox.c

File Facts

System
Linux kernel
Corpus path
lib/kstrtox.c
Extension
.c
Size
11483 bytes
Lines
443
Domain
Kernel Services
Bucket
lib
Inferred role
Kernel Services: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

if (s[0] == '0') {
			if (_tolower(s[1]) == 'x' && isxdigit(s[2]))
				*base = 16;
			else
				*base = 8;
		} else
			*base = 10;
	}
	if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
		s += 2;
	return s;
}

/**
 * _parse_integer_limit - Convert integer string representation to an integer
 * @s: Integer string representation
 * @base: Radix
 * @p: Where to store result
 * @max_chars: Maximum amount of characters to convert
 *
 * Convert non-negative integer string representation in explicitly given
 * radix to an integer. If overflow occurs, value at @p is set to ULLONG_MAX.
 *
 * This function is the workhorse of other string conversion functions and it
 * is discouraged to use it explicitly. Consider kstrto*() family instead.
 *
 * Return: Number of characters consumed, maybe ORed with overflow bit
 */
noinline
unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *p,
				  size_t max_chars)
{
	unsigned int rv, overflow = 0;
	unsigned long long res;

	res = 0;
	for (rv = 0; rv < max_chars; rv++, s++) {
		unsigned int c = *s;
		unsigned int lc = _tolower(c);
		unsigned int val;

		if ('0' <= c && c <= '9')
			val = c - '0';
		else if ('a' <= lc && lc <= 'f')
			val = lc - 'a' + 10;
		else
			break;

		if (val >= base)
			break;
		/*
		 * Check for overflow only if we are within range of
		 * it in the max base we support (16)
		 */
		if (unlikely(res & (~0ull << 60))) {
			if (check_mul_overflow(res, base, &res) ||
			    check_add_overflow(res, val, &res)) {
				res = ULLONG_MAX;
				overflow = KSTRTOX_OVERFLOW;
			}
		} else {
			res = res * base + val;
		}
	}
	*p = res;
	return rv | overflow;
}

noinline
unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
{
	return _parse_integer_limit(s, base, p, INT_MAX);
}

static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
{
	unsigned long long _res;
	unsigned int rv;

	s = _parse_integer_fixup_radix(s, &base);
	rv = _parse_integer(s, base, &_res);
	if (rv & KSTRTOX_OVERFLOW)
		return -ERANGE;
	if (rv == 0)
		return -EINVAL;
	s += rv;
	if (*s == '\n')
		s++;
	if (*s)
		return -EINVAL;

Annotation

Implementation Notes