blob: 3906ca590417481eb3519950d7702844ef9229b8 [file] [log] [blame]
/*
* This file is part of the coreboot project.
*
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
* Copyright 2018-present Facebook, Inc.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* string.c: hastily cobbled-together string functions
*/
#include <assert.h>
#include <ctype.h>
#include <string.h>
#include <lame_string.h>
static int char_to_val(char c)
{
if (c >= '0' && c <= '9') /* digits */
return c - '0';
if (c >= 'A' && c <= 'F') /* uppercase */
return c - 'A' + 10;
if (c >= 'a' && c <= 'f') /* lowercase */
return c - 'a' + 10;
return -1;
}
unsigned long long int strtoull(const char *nptr, char **endptr, int base)
{
unsigned long long int val;
size_t i, error = 0;
/* TODO: enforce lameness of this API for now... */
assert((base == 0) || (base == 16) || base == 10);
if (!nptr)
return 0;
/* Trim whitespace */
for (i = 0; i < strlen(nptr); i++)
if (nptr[i] != ' ')
break;
if (base == 0) {
/* Autodetect base */
if (strlen(&nptr[i]) >= 2 && ((nptr[i] == '0') &&
((nptr[i + 1] == 'x') || (nptr[i + 1] == 'X')))) {
base = 16;
i += 2; /* start loop after prefix */
} else
base = 10;
}
val = 0;
for (; i < strlen(nptr); i++) {
if (base == 16) {
if (!isxdigit(nptr[i])) {
if (*endptr)
*endptr = (char *)&nptr[i];
error = 1;
break;
}
} else {
if (!isdigit(nptr[i])) {
if (*endptr)
*endptr = (char *)&nptr[i];
error = 1;
break;
}
}
val *= base;
val += char_to_val(nptr[i]);
}
if (error) {
printk(BIOS_ERR, "Failed to convert string '%s', base %d to "
"int\n", nptr, base);
return 0;
}
return val;
}
unsigned long int strtoul(const char *nptr, char **endptr, int base)
{
unsigned long long int u = strtol(nptr, endptr, base);
/* FIXME: check for overflow (u > max) */
return (unsigned long int)u;
}
long int strtol(const char *nptr, char **endptr, int base)
{
unsigned long long int u;
int is_neg = 0;
const char *p;
long int ret;
if (nptr[0] == '-') {
is_neg = 1;
p = &nptr[1];
} else {
p = &nptr[0];
}
u = strtoull(p, NULL, base);
/* FIXME: check for overflow (u > max) */
if (is_neg)
ret = 0 - (long int)u;
else
ret = (long int)u;
return ret;
}
long long int strtoll(const char *nptr, char **endptr, int base)
{
unsigned long long int u;
int is_neg = 0;
const char *p;
long long int ret;
if (nptr[0] == '-') {
is_neg = 1;
p = &nptr[1];
} else {
p = &nptr[0];
}
u = strtoull(p, NULL, base);
/* FIXME: check for overflow (sign-bit set) */
if (is_neg)
ret = 0 - (long long int)u;
else
ret = (long long int)u;
return ret;
}
/* FIXME: replace sscanf() usage for bdk_config_get_int. returns number of
* strings converted, so 1 if successful and 0 if not */
int str_to_int(const char *str, int64_t *val)
{
*val = strtol(str, NULL, 10);
return 1;
}
/* FIXME: replace sscanf() usage for bdk_config_get_int. returns number of
* strings converted, so 1 if successful and 0 if not */
int str_to_hex(const char *str, int64_t *val)
{
*val = strtol(str, NULL, 16);
return 1;
}