mirror of
https://github.com/clearlinux/swupd-client.git
synced 2026-08-27 17:06:03 +00:00
string: Add function to convert from string to unsigned ints
Signed-off-by: Otavio Pontes <otavio.pontes@intel.com>
This commit is contained in:
@@ -165,6 +165,45 @@ int str_to_int(const char *str, int *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int str_to_uint_endptr(const char *str, char **endptr, unsigned int *value)
|
||||
{
|
||||
long num;
|
||||
int err;
|
||||
|
||||
errno = 0;
|
||||
num = strtol(str, endptr, 10);
|
||||
err = -errno;
|
||||
|
||||
/* When the return value of strtol overflows the int type, don't overflow
|
||||
* and return an overflow error code. */
|
||||
if (num > UINT_MAX) {
|
||||
num = UINT_MAX;
|
||||
err = -ERANGE;
|
||||
} else if (num < 0) {
|
||||
num = 0;
|
||||
err = -ERANGE;
|
||||
}
|
||||
*value = (unsigned int)num;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int str_to_uint(const char *str, unsigned int *value)
|
||||
{
|
||||
char *endptr;
|
||||
int err = str_to_uint_endptr(str, &endptr, value);
|
||||
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (*endptr != '\0' && !isspace(*endptr)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *str_to_lower(const char *str)
|
||||
{
|
||||
char *str_lower = malloc_or_die(str_len(str) + 1);
|
||||
|
||||
@@ -103,6 +103,34 @@ int str_to_int(const char *str, int *value);
|
||||
*/
|
||||
int str_to_int_endptr(const char *str, char **endptr, int *value);
|
||||
|
||||
/**
|
||||
* Safely convert string to an unsigned integer avoiding overflows
|
||||
*
|
||||
* The strtol function is commonly used to convert a string to a number and
|
||||
* the result is frequently stored in an int type, but type casting a long to
|
||||
* an int can cause overflows.
|
||||
*
|
||||
* This function returns negative error codes based on the errno table:
|
||||
* -ERANGE is returned when the string is out of range for int value
|
||||
* -EINVAL is returned when the string isn't a valid number or has any invalid
|
||||
* trailing character.
|
||||
*/
|
||||
int str_to_uint(const char *str, unsigned int *value);
|
||||
|
||||
/**
|
||||
* Safely convert and string to unsigned integer avoiding overflows.
|
||||
*
|
||||
* The strtol function is commonly used to convert a string to a number and
|
||||
* the result is frequently stored in an int type, but type casting a long to
|
||||
* an int can cause overflows.
|
||||
*
|
||||
* This function returns negative error codes based on the errno table:
|
||||
* -ERANGE is returned when the string is out of range for int value
|
||||
*
|
||||
* endptr is set with the value of the first invalid character in the string.
|
||||
*/
|
||||
int str_to_uint_endptr(const char *str, char **endptr, unsigned int *value);
|
||||
|
||||
/**
|
||||
* Creates a new string converting all characters from the original string
|
||||
* to its lower case values.
|
||||
|
||||
@@ -239,6 +239,123 @@ static void test_str_to_int_endptr()
|
||||
|
||||
}
|
||||
|
||||
static void test_str_to_uint()
|
||||
{
|
||||
char tmp_str[100];
|
||||
int err;
|
||||
unsigned int value = 0;
|
||||
size_t i;
|
||||
|
||||
// test some standard values
|
||||
char *str_values[] = { "0", "-0", "123", "000123" };
|
||||
unsigned int values[] = { 0, 0, 123, 123 };
|
||||
|
||||
for (i = 0; i < sizeof(values) / sizeof(int); i++) {
|
||||
value = 0xffffff;
|
||||
err = str_to_uint(str_values[i], &value);
|
||||
check(err == 0);
|
||||
check(value == values[i]);
|
||||
}
|
||||
|
||||
// test limits
|
||||
value = 0xffffff;
|
||||
snprintf(tmp_str, sizeof(tmp_str), "%u", UINT_MAX - 1);
|
||||
err = str_to_uint(tmp_str, &value);
|
||||
check(err == 0);
|
||||
check(value == UINT_MAX - 1);
|
||||
|
||||
value = 0xffffff;
|
||||
snprintf(tmp_str, sizeof(tmp_str), "%u", UINT_MAX);
|
||||
err = str_to_uint(tmp_str, &value);
|
||||
check(err == 0);
|
||||
check(value == UINT_MAX);
|
||||
|
||||
// test errors
|
||||
value = 0xffffff;
|
||||
snprintf(tmp_str, sizeof(tmp_str), "%ld", (long)UINT_MAX + 1);
|
||||
err = str_to_uint(tmp_str, &value);
|
||||
check(err == -ERANGE);
|
||||
check(value == UINT_MAX);
|
||||
|
||||
value = 0xffffff;
|
||||
snprintf(tmp_str, sizeof(tmp_str), "%ld", (long)UINT_MAX + 1000);
|
||||
err = str_to_uint(tmp_str, &value);
|
||||
check(err == -ERANGE);
|
||||
check(value == UINT_MAX);
|
||||
|
||||
// Negative
|
||||
value = 0xffffff;
|
||||
snprintf(tmp_str, sizeof(tmp_str), "%d", -1);
|
||||
err = str_to_uint(tmp_str, &value);
|
||||
check(err == -ERANGE);
|
||||
check(value == 0);
|
||||
|
||||
value = 0xffffff;
|
||||
snprintf(tmp_str, sizeof(tmp_str), "%d", INT_MIN);
|
||||
err = str_to_uint(tmp_str, &value);
|
||||
check(err == -ERANGE);
|
||||
check(value == 0);
|
||||
|
||||
// test EINVAL errors
|
||||
char *einval_errors[] = { "string", "123.456", "123a", "a123a", "456b123", "0x12345", "4f"};
|
||||
|
||||
for (i = 0; i < sizeof(einval_errors) / sizeof(char *); i++) {
|
||||
err = str_to_uint(einval_errors[i], &value);
|
||||
check(err == -EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_str_to_uint_endptr()
|
||||
{
|
||||
char *endptr;
|
||||
int err;
|
||||
unsigned int value = 0;
|
||||
|
||||
// Test endptr trailing chars
|
||||
value = 0xffffff;
|
||||
endptr = NULL;
|
||||
err = str_to_uint_endptr("123.456", &endptr, &value);
|
||||
check(err == 0);
|
||||
check(value == 123);
|
||||
check(endptr != NULL);
|
||||
check(*endptr == '.');
|
||||
|
||||
value = 0xffffff;
|
||||
endptr = NULL;
|
||||
err = str_to_uint_endptr("123a456", &endptr, &value);
|
||||
check(err == 0);
|
||||
check(value == 123);
|
||||
check(endptr != NULL);
|
||||
check(*endptr == 'a');
|
||||
|
||||
value = 0xffffff;
|
||||
endptr = NULL;
|
||||
err = str_to_uint_endptr("123testing456", &endptr, &value);
|
||||
check(err == 0);
|
||||
check(value == 123);
|
||||
check(endptr != NULL);
|
||||
check(*endptr == 't');
|
||||
|
||||
value = 0xffffff;
|
||||
endptr = NULL;
|
||||
err = str_to_uint_endptr("123-456", &endptr, &value);
|
||||
check(err == 0);
|
||||
check(value == 123);
|
||||
check(endptr != NULL);
|
||||
check(*endptr == '-');
|
||||
|
||||
value = 0xffffff;
|
||||
endptr = NULL;
|
||||
err = str_to_uint_endptr("-123.456", &endptr, &value);
|
||||
check(err == -ERANGE);
|
||||
|
||||
value = 0xffffff;
|
||||
endptr = NULL;
|
||||
err = str_to_uint_endptr("-123a456", &endptr, &value);
|
||||
check(err == -ERANGE);
|
||||
|
||||
}
|
||||
|
||||
void test_str_join()
|
||||
{
|
||||
struct list *str_list = NULL;
|
||||
@@ -280,6 +397,8 @@ int main() {
|
||||
test_str_to_int();
|
||||
test_str_to_int_endptr();
|
||||
test_str_join();
|
||||
test_str_to_uint();
|
||||
test_str_to_uint_endptr();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user