Skip to content
Snippets Groups Projects
Commit 0a16b9bc authored by Simon Praetorius's avatar Simon Praetorius
Browse files

allow trailing whitespaces in lexicalCast

parent 7818611e
No related branches found
No related tags found
1 merge request!564WIP: A generic string-to-number conversion function
......@@ -13,6 +13,7 @@
#include <dune/common/exceptions.hh>
#include <dune/common/fvector.hh>
#include <dune/common/densematrix.hh>
#include <dune/common/lexicalcast.hh>
#include <dune/common/precision.hh>
#include <dune/common/typetraits.hh>
......@@ -334,6 +335,15 @@ namespace Dune
return s;
}
namespace Impl
{
// specialization of LexicalCast
template<typename K>
struct LexicalCast<FieldMatrix<K,1,1>> {
static FieldMatrix<K,1,1> eval (const char* str) { return LexicalCast<K>::eval(str); }
};
}
#endif // DOXYGEN
namespace FMatrixHelp {
......
......@@ -21,6 +21,7 @@
#include "unused.hh"
#include "boundschecking.hh"
#include <dune/common/lexicalcast.hh>
#include <dune/common/math.hh>
namespace Dune {
......@@ -515,6 +516,16 @@ namespace Dune {
{
return a!=b[0];
}
namespace Impl
{
// specialization of LexicalCast
template<typename K>
struct LexicalCast<FieldVector<K,1>> {
static FieldVector<K,1> eval (const char* str) { return LexicalCast<K>::eval(str); }
};
}
#endif
/* Overloads for common classification functions */
......
......@@ -10,14 +10,10 @@
#include <limits>
#include <dune/common/exceptions.hh>
#include <dune/common/quadmath.hh>
namespace Dune
{
// forward declarations
template<class K, int SIZE> class FieldVector;
template<class K, int ROWS, int COLS> class FieldMatrix;
/// An exception thrown whenever interpretation of the argument is not possible.
class InvalidArgument : public Exception {};
namespace Impl
......@@ -30,7 +26,7 @@ namespace Dune
/// \brief Implementation of the acual number converter.
/**
* It is required that the whole string is interpreted, i.e. no trailing whitespaces are allowed.
* Allows leading and trailing whitespace characters.
*
* \tparam T Target numeric type
* \tparam S Output type of the parser [=T]
......@@ -45,7 +41,13 @@ namespace Dune
char* end;
errno = 0;
S x = parser(str, &end);
if (std::strlen(str) > end - str) {
// test whether all non-space characters are consumed during conversion
bool all_consumed = (end != str);
while (all_consumed && (*end != '\0'))
all_consumed = std::isspace(*end++);
if (!all_consumed) {
DUNE_THROW(InvalidArgument,
"Conversion to number failed. Possible reason: invalid string or locale format");
}
......@@ -195,34 +197,6 @@ namespace Dune
}
};
// Dune scalar-like vector/matrix
template<typename T>
struct LexicalCast<FieldVector<T,1>> {
static FieldVector<T,1> eval (const char* str) { return LexicalCast<T>::eval(str); }
};
template<typename T>
struct LexicalCast<FieldMatrix<T,1,1>> {
static FieldMatrix<T,1,1> eval (const char* str) { return LexicalCast<T>::eval(str); }
};
#if HAVE_QUADMATH
// specialization for quadprecision floating-point type.
template<>
struct LexicalCast<__float128> {
static __float128 eval (const char* str)
{
return LexicalCastImpl<__float128>::evalImpl(str, strtoflt128);
}
};
template<>
struct LexicalCast<Float128> {
static Float128 eval (const char* str) { return {LexicalCast<__float128>::eval(str)}; }
};
#endif
} // end namespace Impl
......@@ -236,11 +210,16 @@ namespace Dune
* for conversion. All other types by default call the constructor with strings.
*
* The conversion is locale-dependent and throws an \ref InvalidArgument exception if not all
* characters are consumed during conversion. This means, that no trailing non-numeric characters
* are allowed.
* characters are consumed during conversion, except leading and trailing whitespaces.
*
* In case the represented number is out of range of the number type T, a \ref RangeError exception
* is thrown.
*
* \tparam T The target number type to convert the string to.
* \param str A pointer to the null-terminated byte string to be interpreted.
*
* \throws InvalidArgument
* \throws RangeError
**/
template<typename T>
T lexicalCast(const char* str) { return Impl::LexicalCast<T>::eval(str); }
......
......@@ -15,6 +15,7 @@
#include <type_traits>
#include <utility>
#include <dune/common/lexicalcast.hh>
#include <dune/common/typetraits.hh>
namespace Dune
......@@ -327,6 +328,20 @@ namespace Dune
return Float128{scalbnq(float128_t(u), e)};
}
// specialization of LexicalCast to quad precision types
template<>
struct LexicalCast<__float128> {
static __float128 eval (const char* str)
{
return LexicalCastImpl<__float128>::evalImpl(str, strtoflt128);
}
};
template<>
struct LexicalCast<Float128> {
static Float128 eval (const char* str) { return {LexicalCast<__float128>::eval(str)}; }
};
} // end namespace Impl
template <>
......
......@@ -18,6 +18,7 @@
#include <dune/common/hybridutilities.hh>
#include <dune/common/float_cmp.hh>
#include <dune/common/lexicalcast.hh>
#include <dune/common/quadmath.hh>
#include <dune/common/timer.hh>
#include <dune/common/test/testsuite.hh>
......@@ -200,8 +201,15 @@ int main()
} catch(Dune::Exception const&) {
exception = true;
}
test.check(exception, "InvalidArgument Exception: locale");
test.check(exception, "InvalidArgument Exception");
exception = false;
try {
T val2 = lexicalCast<T>("1.5__");
} catch(Dune::Exception const&) {
exception = true;
}
test.check(exception, "InvalidArgument Exception: trailing characters");
exception = false;
try {
......@@ -209,8 +217,15 @@ int main()
} catch(Dune::Exception const&) {
exception = true;
}
test.check(!exception, "InvalidArgument Exception: trailing whitespace");
test.check(exception, "InvalidArgument Exception");
exception = false;
try {
T val2 = lexicalCast<T>(" 1.5");
} catch(Dune::Exception const&) {
exception = true;
}
test.check(!exception, "InvalidArgument Exception: leading whitespace");
});
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment