Further simplify the code, and update the manpage.
Submitted by: Christoph Mallon <christoph.mallon@gmx.de>
This commit is contained in:
parent
fb26ece72c
commit
a2e0c5ae31
lib/libutil
@ -25,7 +25,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd April 16, 2007
|
.Dd August 15, 2010
|
||||||
.Dt EXPAND_NUMBER 3
|
.Dt EXPAND_NUMBER 3
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -37,14 +37,14 @@
|
|||||||
.In libutil.h
|
.In libutil.h
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fo expand_number
|
.Fo expand_number
|
||||||
.Fa "const char *buf" "int64_t *num"
|
.Fa "const char *buf" "uint64_t *num"
|
||||||
.Fc
|
.Fc
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
The
|
The
|
||||||
.Fn expand_number
|
.Fn expand_number
|
||||||
function unformats the
|
function unformats the
|
||||||
.Fa buf
|
.Fa buf
|
||||||
string and stores a signed 64-bit quantity at address pointed out by the
|
string and stores a unsigned 64-bit quantity at address pointed out by the
|
||||||
.Fa num
|
.Fa num
|
||||||
argument.
|
argument.
|
||||||
.Pp
|
.Pp
|
||||||
|
@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert an expression of the following forms to a int64_t.
|
* Convert an expression of the following forms to a uint64_t.
|
||||||
* 1) A positive decimal number.
|
* 1) A positive decimal number.
|
||||||
* 2) A positive decimal number followed by a 'b' or 'B' (mult by 1).
|
* 2) A positive decimal number followed by a 'b' or 'B' (mult by 1).
|
||||||
* 3) A positive decimal number followed by a 'k' or 'K' (mult by 1 << 10).
|
* 3) A positive decimal number followed by a 'k' or 'K' (mult by 1 << 10).
|
||||||
@ -50,6 +50,7 @@ int
|
|||||||
expand_number(const char *buf, uint64_t *num)
|
expand_number(const char *buf, uint64_t *num)
|
||||||
{
|
{
|
||||||
uint64_t number;
|
uint64_t number;
|
||||||
|
unsigned shift;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
||||||
number = strtoumax(buf, &endptr, 0);
|
number = strtoumax(buf, &endptr, 0);
|
||||||
@ -60,41 +61,41 @@ expand_number(const char *buf, uint64_t *num)
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*endptr == '\0') {
|
|
||||||
/* No unit. */
|
|
||||||
*num = number;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SHIFT(n, b) \
|
|
||||||
do { if (((n << b) >> b) != n) goto overflow; n <<= b; } while (0)
|
|
||||||
|
|
||||||
switch (tolower((unsigned char)*endptr)) {
|
switch (tolower((unsigned char)*endptr)) {
|
||||||
case 'e':
|
case 'e':
|
||||||
SHIFT(number, 10);
|
shift = 60;
|
||||||
case 'p':
|
|
||||||
SHIFT(number, 10);
|
|
||||||
case 't':
|
|
||||||
SHIFT(number, 10);
|
|
||||||
case 'g':
|
|
||||||
SHIFT(number, 10);
|
|
||||||
case 'm':
|
|
||||||
SHIFT(number, 10);
|
|
||||||
case 'k':
|
|
||||||
SHIFT(number, 10);
|
|
||||||
case 'b':
|
|
||||||
break;
|
break;
|
||||||
|
case 'p':
|
||||||
|
shift = 50;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
shift = 40;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
shift = 30;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
shift = 20;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
shift = 10;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
case '\0': /* No unit. */
|
||||||
|
*num = number;
|
||||||
|
return (0);
|
||||||
default:
|
default:
|
||||||
/* Unrecognized unit. */
|
/* Unrecognized unit. */
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
*num = number;
|
if ((number << shift) >> shift != number) {
|
||||||
return (0);
|
/* Overflow */
|
||||||
|
errno = ERANGE;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
overflow:
|
*num = number << shift;
|
||||||
/* Overflow */
|
return (0);
|
||||||
errno = ERANGE;
|
|
||||||
return (-1);
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user