mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 11:22:23 +00:00
util: new function for scaling numbers
Scaling an integer based on a suffix is something we plan on reusing in several contexts: XML parsing, virsh CLI parsing, and possibly elsewhere. Make it easy to reuse, as well as adding in support for powers of 1000. * src/util/util.h (virScaleInteger): New function. * src/util/util.c (virScaleInteger): Implement it. * src/libvirt_private.syms (util.h): Export it.
This commit is contained in:
parent
239fb8c46b
commit
0d90823e87
@ -1134,6 +1134,7 @@ virKillProcess;
|
||||
virParseNumber;
|
||||
virParseVersionString;
|
||||
virPipeReadUntilEOF;
|
||||
virScaleInteger;
|
||||
virSetBlocking;
|
||||
virSetCloseExec;
|
||||
virSetInherit;
|
||||
|
@ -1632,6 +1632,76 @@ virHexToBin(unsigned char c)
|
||||
}
|
||||
}
|
||||
|
||||
/* Scale an integer VALUE in-place by an optional case-insensitive
|
||||
* SUFFIX, defaulting to SCALE if suffix is NULL or empty (scale is
|
||||
* typically 1 or 1024). Recognized suffixes include 'b' or 'bytes',
|
||||
* as well as power-of-two scaling via binary abbreviations ('KiB',
|
||||
* 'MiB', ...) or their one-letter counterpart ('k', 'M', ...), and
|
||||
* power-of-ten scaling via SI abbreviations ('KB', 'MB', ...).
|
||||
* Ensure that the result does not exceed LIMIT. Return 0 on success,
|
||||
* -1 with error message raised on failure. */
|
||||
int
|
||||
virScaleInteger(unsigned long long *value, const char *suffix,
|
||||
unsigned long long scale, unsigned long long limit)
|
||||
{
|
||||
if (!suffix || !*suffix) {
|
||||
if (!scale) {
|
||||
virUtilError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("invalid scale %llu"), scale);
|
||||
return -1;
|
||||
}
|
||||
suffix = "";
|
||||
} else if (STRCASEEQ(suffix, "b") || STRCASEEQ(suffix, "byte") ||
|
||||
STRCASEEQ(suffix, "bytes")) {
|
||||
scale = 1;
|
||||
} else {
|
||||
int base;
|
||||
|
||||
if (!suffix[1] || STRCASEEQ(suffix + 1, "iB")) {
|
||||
base = 1024;
|
||||
} else if (c_tolower(suffix[1]) == 'b' && !suffix[2]) {
|
||||
base = 1000;
|
||||
} else {
|
||||
virUtilError(VIR_ERR_INVALID_ARG,
|
||||
_("unknown suffix '%s'"), suffix);
|
||||
return -1;
|
||||
}
|
||||
scale = 1;
|
||||
switch (c_tolower(*suffix)) {
|
||||
case 'e':
|
||||
scale *= base;
|
||||
/* fallthrough */
|
||||
case 'p':
|
||||
scale *= base;
|
||||
/* fallthrough */
|
||||
case 't':
|
||||
scale *= base;
|
||||
/* fallthrough */
|
||||
case 'g':
|
||||
scale *= base;
|
||||
/* fallthrough */
|
||||
case 'm':
|
||||
scale *= base;
|
||||
/* fallthrough */
|
||||
case 'k':
|
||||
scale *= base;
|
||||
break;
|
||||
default:
|
||||
virUtilError(VIR_ERR_INVALID_ARG,
|
||||
_("unknown suffix '%s'"), suffix);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (*value && *value >= (limit / scale)) {
|
||||
virUtilError(VIR_ERR_OVERFLOW, _("value too large: %llu%s"),
|
||||
*value, suffix);
|
||||
return -1;
|
||||
}
|
||||
*value *= scale;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* virSkipSpaces:
|
||||
* @str: pointer to the char pointer used
|
||||
|
@ -157,6 +157,10 @@ int virStrToDouble(char const *s,
|
||||
char **end_ptr,
|
||||
double *result);
|
||||
|
||||
int virScaleInteger(unsigned long long *value, const char *suffix,
|
||||
unsigned long long scale, unsigned long long limit)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
|
||||
|
||||
int virHexToBin(unsigned char c);
|
||||
|
||||
void virSkipSpaces(const char **str) ATTRIBUTE_NONNULL(1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user