diff options
Diffstat (limited to 'lib/libcxx/utils/google-benchmark/src/string_util.cc')
-rw-r--r-- | lib/libcxx/utils/google-benchmark/src/string_util.cc | 107 |
1 files changed, 98 insertions, 9 deletions
diff --git a/lib/libcxx/utils/google-benchmark/src/string_util.cc b/lib/libcxx/utils/google-benchmark/src/string_util.cc index cd4e7cfde57..05ac5b4ea36 100644 --- a/lib/libcxx/utils/google-benchmark/src/string_util.cc +++ b/lib/libcxx/utils/google-benchmark/src/string_util.cc @@ -27,8 +27,6 @@ static_assert(arraysize(kSmallSIUnits) == arraysize(kBigSIUnits), static const int64_t kUnitsSize = arraysize(kBigSIUnits); -} // end anonymous namespace - void ToExponentAndMantissa(double val, double thresh, int precision, double one_k, std::string* mantissa, int64_t* exponent) { @@ -100,14 +98,16 @@ std::string ExponentToPrefix(int64_t exponent, bool iec) { } std::string ToBinaryStringFullySpecified(double value, double threshold, - int precision) { + int precision, double one_k = 1024.0) { std::string mantissa; int64_t exponent; - ToExponentAndMantissa(value, threshold, precision, 1024.0, &mantissa, + ToExponentAndMantissa(value, threshold, precision, one_k, &mantissa, &exponent); return mantissa + ExponentToPrefix(exponent, false); } +} // end namespace + void AppendHumanReadable(int n, std::string* str) { std::stringstream ss; // Round down to the nearest SI prefix. @@ -115,14 +115,14 @@ void AppendHumanReadable(int n, std::string* str) { *str += ss.str(); } -std::string HumanReadableNumber(double n) { +std::string HumanReadableNumber(double n, double one_k) { // 1.1 means that figures up to 1.1k should be shown with the next unit down; // this softens edge effects. // 1 means that we should show one decimal place of precision. - return ToBinaryStringFullySpecified(n, 1.1, 1); + return ToBinaryStringFullySpecified(n, 1.1, 1, one_k); } -std::string StringPrintFImp(const char* msg, va_list args) { +std::string StrFormatImp(const char* msg, va_list args) { // we might need a second shot at this, so pre-emptivly make a copy va_list args_cp; va_copy(args_cp, args); @@ -152,10 +152,10 @@ std::string StringPrintFImp(const char* msg, va_list args) { return std::string(buff_ptr.get()); } -std::string StringPrintF(const char* format, ...) { +std::string StrFormat(const char* format, ...) { va_list args; va_start(args, format); - std::string tmp = StringPrintFImp(format, args); + std::string tmp = StrFormatImp(format, args); va_end(args); return tmp; } @@ -169,4 +169,93 @@ void ReplaceAll(std::string* str, const std::string& from, } } +#ifdef BENCHMARK_STL_ANDROID_GNUSTL +/* + * GNU STL in Android NDK lacks support for some C++11 functions, including + * stoul, stoi, stod. We reimplement them here using C functions strtoul, + * strtol, strtod. Note that reimplemented functions are in benchmark:: + * namespace, not std:: namespace. + */ +unsigned long stoul(const std::string& str, size_t* pos, int base) { + /* Record previous errno */ + const int oldErrno = errno; + errno = 0; + + const char* strStart = str.c_str(); + char* strEnd = const_cast<char*>(strStart); + const unsigned long result = strtoul(strStart, &strEnd, base); + + const int strtoulErrno = errno; + /* Restore previous errno */ + errno = oldErrno; + + /* Check for errors and return */ + if (strtoulErrno == ERANGE) { + throw std::out_of_range( + "stoul failed: " + str + " is outside of range of unsigned long"); + } else if (strEnd == strStart || strtoulErrno != 0) { + throw std::invalid_argument( + "stoul failed: " + str + " is not an integer"); + } + if (pos != nullptr) { + *pos = static_cast<size_t>(strEnd - strStart); + } + return result; +} + +int stoi(const std::string& str, size_t* pos, int base) { + /* Record previous errno */ + const int oldErrno = errno; + errno = 0; + + const char* strStart = str.c_str(); + char* strEnd = const_cast<char*>(strStart); + const long result = strtol(strStart, &strEnd, base); + + const int strtolErrno = errno; + /* Restore previous errno */ + errno = oldErrno; + + /* Check for errors and return */ + if (strtolErrno == ERANGE || long(int(result)) != result) { + throw std::out_of_range( + "stoul failed: " + str + " is outside of range of int"); + } else if (strEnd == strStart || strtolErrno != 0) { + throw std::invalid_argument( + "stoul failed: " + str + " is not an integer"); + } + if (pos != nullptr) { + *pos = static_cast<size_t>(strEnd - strStart); + } + return int(result); +} + +double stod(const std::string& str, size_t* pos) { + /* Record previous errno */ + const int oldErrno = errno; + errno = 0; + + const char* strStart = str.c_str(); + char* strEnd = const_cast<char*>(strStart); + const double result = strtod(strStart, &strEnd); + + /* Restore previous errno */ + const int strtodErrno = errno; + errno = oldErrno; + + /* Check for errors and return */ + if (strtodErrno == ERANGE) { + throw std::out_of_range( + "stoul failed: " + str + " is outside of range of int"); + } else if (strEnd == strStart || strtodErrno != 0) { + throw std::invalid_argument( + "stoul failed: " + str + " is not an integer"); + } + if (pos != nullptr) { + *pos = static_cast<size_t>(strEnd - strStart); + } + return result; +} +#endif + } // end namespace benchmark |