forked from OSchip/llvm-project
[ADT] Add llvm::to_float
Summary: The function matches the interface of llvm::to_integer, but as we are calling out to a C library function, I let it take a Twine argument, so we can avoid a string copy at least in some cases. I add a test and replace a couple of existing uses of strtod with this function. Reviewers: zturner Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D34518 llvm-svn: 306096
This commit is contained in:
parent
d5f7711ebb
commit
ec000f42fa
|
@ -15,10 +15,12 @@
|
|||
#define LLVM_ADT_STRINGEXTRAS_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
@ -129,6 +131,32 @@ template <typename N> bool to_integer(StringRef S, N &Num, unsigned Base = 0) {
|
|||
return !S.getAsInteger(Base, Num);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <typename N>
|
||||
inline bool to_float(const Twine &T, N &Num, N (*StrTo)(const char *, char **)) {
|
||||
SmallString<32> Storage;
|
||||
StringRef S = T.toNullTerminatedStringRef(Storage);
|
||||
char *End;
|
||||
N Temp = StrTo(S.data(), &End);
|
||||
if (*End != '\0')
|
||||
return false;
|
||||
Num = Temp;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool to_float(const Twine &T, float &Num) {
|
||||
return detail::to_float(T, Num, std::strtof);
|
||||
}
|
||||
|
||||
inline bool to_float(const Twine &T, double &Num) {
|
||||
return detail::to_float(T, Num, std::strtod);
|
||||
}
|
||||
|
||||
inline bool to_float(const Twine &T, long double &Num) {
|
||||
return detail::to_float(T, Num, std::strtold);
|
||||
}
|
||||
|
||||
static inline std::string utostr(uint64_t X, bool isNeg = false) {
|
||||
char Buffer[21];
|
||||
char *BufPtr = std::end(Buffer);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Config/config.h"
|
||||
|
@ -1522,13 +1523,9 @@ bool parser<unsigned long long>::parse(Option &O, StringRef ArgName,
|
|||
// parser<double>/parser<float> implementation
|
||||
//
|
||||
static bool parseDouble(Option &O, StringRef Arg, double &Value) {
|
||||
SmallString<32> TmpStr(Arg.begin(), Arg.end());
|
||||
const char *ArgStart = TmpStr.c_str();
|
||||
char *End;
|
||||
Value = strtod(ArgStart, &End);
|
||||
if (*End != 0)
|
||||
return O.error("'" + Arg + "' value invalid for floating point argument!");
|
||||
return false;
|
||||
if (to_float(Arg, Value))
|
||||
return false;
|
||||
return O.error("'" + Arg + "' value invalid for floating point argument!");
|
||||
}
|
||||
|
||||
bool parser<double>::parse(Option &O, StringRef ArgName, StringRef Arg,
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
|
@ -912,12 +913,9 @@ void ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) {
|
|||
}
|
||||
|
||||
StringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) {
|
||||
SmallString<32> buff(Scalar.begin(), Scalar.end());
|
||||
char *end;
|
||||
Val = strtod(buff.c_str(), &end);
|
||||
if (*end != '\0')
|
||||
return "invalid floating point number";
|
||||
return StringRef();
|
||||
if (to_float(Scalar, Val))
|
||||
return StringRef();
|
||||
return "invalid floating point number";
|
||||
}
|
||||
|
||||
void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) {
|
||||
|
@ -925,12 +923,9 @@ void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) {
|
|||
}
|
||||
|
||||
StringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) {
|
||||
SmallString<32> buff(Scalar.begin(), Scalar.end());
|
||||
char *end;
|
||||
Val = strtod(buff.c_str(), &end);
|
||||
if (*end != '\0')
|
||||
return "invalid floating point number";
|
||||
return StringRef();
|
||||
if (to_float(Scalar, Val))
|
||||
return StringRef();
|
||||
return "invalid floating point number";
|
||||
}
|
||||
|
||||
void ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) {
|
||||
|
|
|
@ -65,4 +65,22 @@ TEST(StringExtrasTest, ToAndFromHex) {
|
|||
EvenBytes.size());
|
||||
EXPECT_EQ(EvenStr, toHex(EvenData));
|
||||
EXPECT_EQ(EvenData, fromHex(EvenStr));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(StringExtrasTest, to_float) {
|
||||
float F;
|
||||
EXPECT_TRUE(to_float("4.7", F));
|
||||
EXPECT_FLOAT_EQ(4.7, F);
|
||||
|
||||
double D;
|
||||
EXPECT_TRUE(to_float("4.7", D));
|
||||
EXPECT_DOUBLE_EQ(4.7, D);
|
||||
|
||||
long double LD;
|
||||
EXPECT_TRUE(to_float("4.7", LD));
|
||||
EXPECT_DOUBLE_EQ(4.7, LD);
|
||||
|
||||
EXPECT_FALSE(to_float("foo", F));
|
||||
EXPECT_FALSE(to_float("7.4 foo", F));
|
||||
EXPECT_FLOAT_EQ(4.7, F); // F should be unchanged
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue