mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 06:15:47 +00:00
util: Library routines for printing and scanning large hex integers.
Geneve options are variable length and up to 124 bytes long, which means that they can't be easily manipulated by the integer string functions like we do for other fields. This adds a few helper routines to make these operations easier. Signed-off-by: Jesse Gross <jesse@nicira.com> Acked-by: Andy Zhou <azhou@nicira.com>
This commit is contained in:
81
lib/util.c
81
lib/util.c
@@ -738,6 +738,87 @@ hexits_value(const char *s, size_t n, bool *ok)
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Parses the string in 's' as an integer in either hex or decimal format and
|
||||
* puts the result right justified in the array 'valuep' that is 'field_width'
|
||||
* big. If the string is in hex format, the value may be arbitrarily large;
|
||||
* integers are limited to 64-bit values. (The rationale is that decimal is
|
||||
* likely to represent a number and 64 bits is a reasonable maximum whereas
|
||||
* hex could either be a number or a byte string.)
|
||||
*
|
||||
* On return 'tail' points to the first character in the string that was
|
||||
* not parsed as part of the value. ERANGE is returned if the value is too
|
||||
* large to fit in the given field. */
|
||||
int
|
||||
parse_int_string(const char *s, uint8_t *valuep, int field_width, char **tail)
|
||||
{
|
||||
unsigned long long int integer;
|
||||
int i;
|
||||
|
||||
if (!strncmp(s, "0x", 2) || !strncmp(s, "0X", 2)) {
|
||||
uint8_t *hexit_str;
|
||||
int len = 0;
|
||||
int val_idx;
|
||||
int err = 0;
|
||||
|
||||
s += 2;
|
||||
hexit_str = xmalloc(field_width * 2);
|
||||
|
||||
for (;;) {
|
||||
uint8_t hexit;
|
||||
bool ok;
|
||||
|
||||
s += strspn(s, " \t\r\n");
|
||||
hexit = hexits_value(s, 1, &ok);
|
||||
if (!ok) {
|
||||
*tail = CONST_CAST(char *, s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (hexit != 0 || len) {
|
||||
if (DIV_ROUND_UP(len + 1, 2) > field_width) {
|
||||
err = ERANGE;
|
||||
goto free;
|
||||
}
|
||||
|
||||
hexit_str[len] = hexit;
|
||||
len++;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
|
||||
val_idx = field_width;
|
||||
for (i = len - 1; i >= 0; i -= 2) {
|
||||
val_idx--;
|
||||
valuep[val_idx] = hexit_str[i];
|
||||
if (i > 0) {
|
||||
valuep[val_idx] += hexit_str[i - 1] << 4;
|
||||
}
|
||||
}
|
||||
|
||||
memset(valuep, 0, val_idx);
|
||||
|
||||
free:
|
||||
free(hexit_str);
|
||||
return err;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
integer = strtoull(s, tail, 0);
|
||||
if (errno) {
|
||||
return errno;
|
||||
}
|
||||
|
||||
for (i = field_width - 1; i >= 0; i--) {
|
||||
valuep[i] = integer;
|
||||
integer >>= 8;
|
||||
}
|
||||
if (integer) {
|
||||
return ERANGE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns the current working directory as a malloc()'d string, or a null
|
||||
* pointer if the current working directory cannot be determined. */
|
||||
char *
|
||||
|
Reference in New Issue
Block a user