diff --git a/io/EptReader.cpp b/io/EptReader.cpp index 294a321a06..892357bceb 100644 --- a/io/EptReader.cpp +++ b/io/EptReader.cpp @@ -84,7 +84,7 @@ class EptBounds : public SrsBounds namespace Utils { template<> - bool fromString(const std::string& s, EptBounds& bounds) + StatusWithReason fromString(const std::string& s, EptBounds& bounds) { if (!fromString(s, (SrsBounds&)bounds)) return false; diff --git a/pdal/EigenUtils.hpp b/pdal/EigenUtils.hpp index eab7b822f0..7247791ee7 100644 --- a/pdal/EigenUtils.hpp +++ b/pdal/EigenUtils.hpp @@ -279,7 +279,9 @@ namespace Utils { template <> -inline bool fromString(const std::string& s, Eigen::MatrixXd& matrix) { +inline StatusWithReason fromString(const std::string& s, + Eigen::MatrixXd& matrix) +{ std::stringstream ss(s); std::string line; std::vector> rows; diff --git a/pdal/SrsBounds.hpp b/pdal/SrsBounds.hpp index f4c6b2f55a..01720476fa 100644 --- a/pdal/SrsBounds.hpp +++ b/pdal/SrsBounds.hpp @@ -64,7 +64,7 @@ class PDAL_DLL SrsBounds : public Bounds namespace Utils { template<> - inline bool fromString(const std::string& s, + inline StatusWithReason fromString(const std::string& s, SrsBounds& srsBounds) { std::string::size_type pos(0); diff --git a/pdal/util/ProgramArgs.hpp b/pdal/util/ProgramArgs.hpp index 93fe65f366..86852fd239 100644 --- a/pdal/util/ProgramArgs.hpp +++ b/pdal/util/ProgramArgs.hpp @@ -407,13 +407,20 @@ class TArg : public Arg } m_rawVal = s; - if (!Utils::fromString(s, m_var)) + auto status = Utils::fromString(s, m_var); + if (!status) { std::string error(m_error); if (error.empty()) - error = "Invalid value '" + s + "' for argument '" + - m_longname + "'."; + { + if (status.what().size()) + error = "Invalid value for argument '" + m_longname + + "': " + status.what(); + else + error = "Invalid value '" + s + "' for argument '" + + m_longname + "'."; + } throw arg_val_error(error); } m_set = true; @@ -755,12 +762,20 @@ class VArg : public BaseVArg T var; m_rawVal = s; - if (!Utils::fromString(s, var)) + auto status = Utils::fromString(s, var); + if (!status) { std::string error(m_error); if (error.empty()) - error = "Invalid value for argument '" + m_longname + "'."; + { + if (status.what().size()) + error = "Invalid value for argument '" + m_longname + + "': " + status.what(); + else + error = "Invalid value '" + s + "' for argument '" + + m_longname + "'."; + } throw arg_val_error(error); } if (!m_set) diff --git a/pdal/util/Utils.hpp b/pdal/util/Utils.hpp index 7c0b2fdd6f..01bc907fd7 100644 --- a/pdal/util/Utils.hpp +++ b/pdal/util/Utils.hpp @@ -82,6 +82,14 @@ namespace Utils public: StatusWithReason() : m_code(0) {} + StatusWithReason(bool ok) + { + if (ok) + m_code = 0; + else + m_code = -1; + } + StatusWithReason(int code); // Not defined StatusWithReason(int code, const std::string& what) : m_code(code), m_what(what) {} @@ -929,7 +937,7 @@ namespace Utils template - bool fromString(const std::string& from, T* & to) + StatusWithReason fromString(const std::string& from, T* & to) { void *v; // Uses sscanf instead of operator>>(istream, void*&) as a workaround @@ -951,7 +959,7 @@ namespace Utils \return \c true if the conversion was successful, \c false otherwise. */ template - bool fromString(const std::string& from, T& to) + StatusWithReason fromString(const std::string& from, T& to) { std::istringstream iss(from); @@ -961,7 +969,7 @@ namespace Utils // Optimization of above. template<> - inline bool fromString(const std::string& from, std::string& to) + inline StatusWithReason fromString(const std::string& from, std::string& to) { to = from; return true; @@ -975,7 +983,7 @@ namespace Utils \return \c true if the conversion was successful, \c false otherwise. */ template<> - inline bool fromString(const std::string& s, char& to) + inline StatusWithReason fromString(const std::string& s, char& to) { try { @@ -1006,8 +1014,7 @@ namespace Utils \return \c true if the conversion was successful, \c false otherwise. */ template<> - inline bool fromString(const std::string& s, - unsigned char& to) + inline StatusWithReason fromString(const std::string& s, unsigned char& to) { try { @@ -1039,7 +1046,7 @@ namespace Utils \return \c true if the conversion was successful, \c false otherwise. */ template<> - inline bool fromString(const std::string& s, signed char& to) + inline StatusWithReason fromString(const std::string& s, signed char& to) { try { @@ -1070,7 +1077,7 @@ namespace Utils \return \c true if the conversion was successful, \c false otherwise. */ template<> - inline bool fromString(const std::string& s, double& d) + inline StatusWithReason fromString(const std::string& s, double& d) { if (s == "nan" || s == "NaN") {