Commit 36194671 authored by Mikhail Okunev's avatar Mikhail Okunev Committed by Sara Golemon

Utility that converts from prettyPrint format back to double (e.g. 10M = 10 000 000)

Summary: Utility is doing reverse of prettyPrint. This is a first sketch.

Test Plan:
1) We can reverse all tests from prettyPrint test and use for our function. For now I just reversed several of them
2) We can also test prettyPrint and prettyToDouble together by checking whether prettyToDouble(prettyPrint(X)) == X. This is implemented.

Reviewed By: marcelo.juchem@fb.com

FB internal diff: D1159879
parent 72c2a0d3
...@@ -180,6 +180,31 @@ const PrettySuffix kPrettyUnitsBinaryIECSuffixes[] = { ...@@ -180,6 +180,31 @@ const PrettySuffix kPrettyUnitsBinaryIECSuffixes[] = {
{ 0, 0 }, { 0, 0 },
}; };
const PrettySuffix kPrettySISuffixes[] = {
{ "Y", 1e24L },
{ "Z", 1e21L },
{ "E", 1e18L },
{ "P", 1e15L },
{ "T", 1e12L },
{ "G", 1e9L },
{ "M", 1e6L },
{ "k", 1e3L },
{ "h", 1e2L },
{ "da", 1e1L },
{ "d", 1e-1L },
{ "c", 1e-2L },
{ "m", 1e-3L },
{ "u", 1e-6L },
{ "n", 1e-9L },
{ "p", 1e-12L },
{ "f", 1e-15L },
{ "a", 1e-18L },
{ "z", 1e-21L },
{ "y", 1e-24L },
{ " ", 0 },
{ 0, 0}
};
const PrettySuffix* const kPrettySuffixes[PRETTY_NUM_TYPES] = { const PrettySuffix* const kPrettySuffixes[PRETTY_NUM_TYPES] = {
kPrettyTimeSuffixes, kPrettyTimeSuffixes,
kPrettyBytesMetricSuffixes, kPrettyBytesMetricSuffixes,
...@@ -188,6 +213,7 @@ const PrettySuffix* const kPrettySuffixes[PRETTY_NUM_TYPES] = { ...@@ -188,6 +213,7 @@ const PrettySuffix* const kPrettySuffixes[PRETTY_NUM_TYPES] = {
kPrettyUnitsMetricSuffixes, kPrettyUnitsMetricSuffixes,
kPrettyUnitsBinarySuffixes, kPrettyUnitsBinarySuffixes,
kPrettyUnitsBinaryIECSuffixes, kPrettyUnitsBinaryIECSuffixes,
kPrettySISuffixes,
}; };
} // namespace } // namespace
...@@ -218,6 +244,50 @@ std::string prettyPrint(double val, PrettyType type, bool addSpace) { ...@@ -218,6 +244,50 @@ std::string prettyPrint(double val, PrettyType type, bool addSpace) {
return std::string(buf); return std::string(buf);
} }
//TODO:
//1) Benchmark & optimize
double prettyToDouble(folly::StringPiece *const prettyString,
const PrettyType type) {
double value = folly::to<double>(prettyString);
while (prettyString->size() > 0 && std::isspace(prettyString->front())) {
prettyString->advance(1); //Skipping spaces between number and suffix
}
const PrettySuffix* suffixes = kPrettySuffixes[type];
int longestPrefixLen = -1;
int bestPrefixId = -1;
for (int j = 0 ; suffixes[j].suffix; ++j) {
if (suffixes[j].suffix[0] == ' '){//Checking for " " -> number rule.
if (longestPrefixLen == -1) {
longestPrefixLen = 0; //No characters to skip
bestPrefixId = j;
}
} else if (prettyString->startsWith(suffixes[j].suffix)) {
int suffixLen = strlen(suffixes[j].suffix);
//We are looking for a longest suffix matching prefix of the string
//after numeric value. We need this in case suffixes have common prefix.
if (suffixLen > longestPrefixLen) {
longestPrefixLen = suffixLen;
bestPrefixId = j;
}
}
}
if (bestPrefixId == -1) { //No valid suffix rule found
throw std::invalid_argument(folly::to<std::string>(
"Unable to parse suffix \"",
prettyString->toString(), "\""));
}
prettyString->advance(longestPrefixLen);
return suffixes[bestPrefixId].val ? value * suffixes[bestPrefixId].val :
value;
}
double prettyToDouble(folly::StringPiece prettyString, const PrettyType type){
double result = prettyToDouble(&prettyString, type);
detail::enforceWhitespace(prettyString.data(),
prettyString.data() + prettyString.size());
return result;
}
std::string hexDump(const void* ptr, size_t size) { std::string hexDump(const void* ptr, size_t size) {
std::ostringstream os; std::ostringstream os;
hexDump(ptr, size, std::ostream_iterator<StringPiece>(os, "\n")); hexDump(ptr, size, std::ostream_iterator<StringPiece>(os, "\n"));
......
...@@ -268,7 +268,8 @@ bool unhexlify(const InputString& input, OutputString& output); ...@@ -268,7 +268,8 @@ bool unhexlify(const InputString& input, OutputString& output);
* PRETTY_UNITS_METRIC - k, M, G, etc (goes up by 10^3 = 1000 each time) * PRETTY_UNITS_METRIC - k, M, G, etc (goes up by 10^3 = 1000 each time)
* PRETTY_UNITS_BINARY - k, M, G, etc (goes up by 2^10 = 1024 each time) * PRETTY_UNITS_BINARY - k, M, G, etc (goes up by 2^10 = 1024 each time)
* PRETTY_UNITS_BINARY_IEC - Ki, Mi, Gi, etc * PRETTY_UNITS_BINARY_IEC - Ki, Mi, Gi, etc
* * PRETTY_SI - full SI metric prefixes from yocto to Yotta
* http://en.wikipedia.org/wiki/Metric_prefix
* @author Mark Rabkin <mrabkin@fb.com> * @author Mark Rabkin <mrabkin@fb.com>
*/ */
enum PrettyType { enum PrettyType {
...@@ -284,11 +285,38 @@ enum PrettyType { ...@@ -284,11 +285,38 @@ enum PrettyType {
PRETTY_UNITS_BINARY, PRETTY_UNITS_BINARY,
PRETTY_UNITS_BINARY_IEC, PRETTY_UNITS_BINARY_IEC,
PRETTY_NUM_TYPES PRETTY_SI,
PRETTY_NUM_TYPES,
}; };
std::string prettyPrint(double val, PrettyType, bool addSpace = true); std::string prettyPrint(double val, PrettyType, bool addSpace = true);
/**
* This utility converts StringPiece in pretty format (look above) to double,
* with progress information. Alters the StringPiece parameter
* to get rid of the already-parsed characters.
* Expects string in form <floating point number> {space}* [<suffix>]
* If string is not in correct format, utility finds longest valid prefix and
* if there at least one, returns double value based on that prefix and
* modifies string to what is left after parsing. Throws and std::range_error
* exception if there is no correct parse.
* Examples(for PRETTY_UNITS_METRIC):
* '10M' => 10 000 000
* '10 M' => 10 000 000
* '10' => 10
* '10 Mx' => 10 000 000, prettyString == "x"
* 'abc' => throws std::range_error
*/
double prettyToDouble(folly::StringPiece *const prettyString,
const PrettyType type);
/*
* Same as prettyToDouble(folly::StringPiece*, PrettyType), but
* expects whole string to be correctly parseable. Throws std::range_error
* otherwise
*/
double prettyToDouble(folly::StringPiece prettyString, const PrettyType type);
/** /**
* Write a hex dump of size bytes starting at ptr to out. * Write a hex dump of size bytes starting at ptr to out.
* *
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment