Merge pull request #705 from jokva/remove-boost-from-startoken

Moves readValueToken implementation to source file
This commit is contained in:
Joakim Hove
2016-03-08 17:37:31 +01:00
4 changed files with 71 additions and 74 deletions

View File

@@ -17,6 +17,8 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <boost/lexical_cast.hpp>
#include <opm/json/JsonObject.hpp>
#include <opm/parser/eclipse/Parser/ParserItem.hpp>

View File

@@ -69,4 +69,71 @@ namespace Opm {
valueString = token.substr(pos + 1);
return true;
}
template< typename T >
T readValueToken(const std::string& valueString) {
try {
return boost::lexical_cast<T>(valueString);
}
catch (boost::bad_lexical_cast&) {
throw std::invalid_argument("Unable to convert string '" + valueString + "' to typeid: " + typeid(T).name());
}
}
template <>
double readValueToken< double >(const std::string& valueString) {
try {
return boost::lexical_cast<double>(valueString);
}
catch (boost::bad_lexical_cast&) {
// Eclipse supports Fortran syntax for specifying exponents of floating point
// numbers ('D' and 'E', e.g., 1.234d5) while C++ only supports the 'e' (e.g.,
// 1.234e5). the quick fix is to replace 'D' by 'E' and 'd' by 'e' before trying
// to convert the string into a floating point value. This may not be the most
// performant thing to do, but it is probably fast enough.
std::string vs(valueString);
std::replace(vs.begin(), vs.end(), 'D', 'E');
std::replace(vs.begin(), vs.end(), 'd', 'e');
try { return boost::lexical_cast<double>(vs); }
catch (boost::bad_lexical_cast&) {
throw std::invalid_argument("Unable to convert string '" + valueString + "' to double");
}
}
}
template <>
std::string readValueToken< std::string >(const std::string& valueString) {
if (valueString.size() > 0 && valueString[0] == '\'') {
if (valueString.size() < 2 || valueString[valueString.size() - 1] != '\'')
throw std::invalid_argument("Unable to parse string '" + valueString + "' as a string token");
return valueString.substr(1, valueString.size() - 2);
}
else
return valueString;
}
void StarToken::init_( const std::string& token ) {
// special-case the interpretation of a lone star as "1*" but do not
// allow constructs like "*123"...
if (m_countString == "") {
if (m_valueString != "")
// TODO: decorate the deck with a warning instead?
throw std::invalid_argument("Not specifying a count also implies not specifying a value. Token: \'" + token + "\'.");
// TODO: since this is explicitly forbidden by the documentation it might
// be a good idea to decorate the deck with a warning?
m_count = 1;
}
else {
m_count = std::stoi( m_countString );
if (m_count == 0)
// TODO: decorate the deck with a warning instead?
throw std::invalid_argument("Specifing zero repetitions is not allowed. Token: \'" + token + "\'.");
}
}
template int readValueToken< int >(const std::string& );
}

View File

@@ -21,9 +21,6 @@
#define STAR_TOKEN_HPP
#include <string>
#include <algorithm>
#include <boost/lexical_cast.hpp>
namespace Opm {
bool isStarToken(const std::string& token,
@@ -31,53 +28,7 @@ namespace Opm {
std::string& valueString);
template <class T>
T readValueToken(const std::string& valueString) {
try {
return boost::lexical_cast<T>(valueString);
}
catch (boost::bad_lexical_cast&) {
throw std::invalid_argument("Unable to convert string '" + valueString + "' to typeid: " + typeid(T).name());
}
}
template <>
inline double readValueToken<double>(const std::string& valueString) {
try {
return boost::lexical_cast<double>(valueString);
}
catch (boost::bad_lexical_cast&) {
// Eclipse supports Fortran syntax for specifying exponents of floating point
// numbers ('D' and 'E', e.g., 1.234d5) while C++ only supports the 'e' (e.g.,
// 1.234e5). the quick fix is to replace 'D' by 'E' and 'd' by 'e' before trying
// to convert the string into a floating point value. This may not be the most
// performant thing to do, but it is probably fast enough.
std::string vs(valueString);
std::replace(vs.begin(), vs.end(), 'D', 'E');
std::replace(vs.begin(), vs.end(), 'd', 'e');
try { return boost::lexical_cast<double>(vs); }
catch (boost::bad_lexical_cast&) {
throw std::invalid_argument("Unable to convert string '" + valueString + "' to double");
}
}
}
template <>
inline float readValueToken<float>(const std::string& valueString) {
return readValueToken<double>(valueString);
}
template <>
inline std::string readValueToken<std::string>(const std::string& valueString) {
if (valueString.size() > 0 && valueString[0] == '\'') {
if (valueString.size() < 2 || valueString[valueString.size() - 1] != '\'')
throw std::invalid_argument("Unable to parse string '" + valueString + "' as a string token");
return valueString.substr(1, valueString.size() - 2);
}
else
return valueString;
}
T readValueToken(const std::string& valueString);
class StarToken {
public:
@@ -122,26 +73,7 @@ public:
private:
// internal initialization method. the m_countString and m_valueString attributes
// must be set before calling this method.
void init_(const std::string& token) {
// special-case the interpretation of a lone star as "1*" but do not
// allow constructs like "*123"...
if (m_countString == "") {
if (m_valueString != "")
// TODO: decorate the deck with a warning instead?
throw std::invalid_argument("Not specifying a count also implies not specifying a value. Token: \'" + token + "\'.");
// TODO: since this is explicitly forbidden by the documentation it might
// be a good idea to decorate the deck with a warning?
m_count = 1;
}
else {
m_count = boost::lexical_cast<int>(m_countString);
if (m_count == 0)
// TODO: decorate the deck with a warning instead?
throw std::invalid_argument("Specifing zero repetitions is not allowed. Token: \'" + token + "\'.");
}
}
void init_(const std::string& token);
ssize_t m_count;
std::string m_countString;

View File

@@ -106,10 +106,6 @@ BOOST_AUTO_TEST_CASE( readValueToken_basic_validity_tests ) {
BOOST_CHECK_CLOSE( 3.3, Opm::readValueToken<double>("3.3d0"), 1e-6 );
BOOST_CHECK_CLOSE( 3.3, Opm::readValueToken<double>("3.3E0"), 1e-6 );
BOOST_CHECK_CLOSE( 3.3, Opm::readValueToken<double>("3.3D0"), 1e-6 );
BOOST_CHECK_CLOSE( 3.3, Opm::readValueToken<float>("3.3e0"), 1e-4 );
BOOST_CHECK_CLOSE( 3.3, Opm::readValueToken<float>("3.3d0"), 1e-4 );
BOOST_CHECK_CLOSE( 3.3, Opm::readValueToken<float>("3.3E0"), 1e-4 );
BOOST_CHECK_CLOSE( 3.3, Opm::readValueToken<float>("3.3D0"), 1e-4 );
BOOST_CHECK_EQUAL( "OLGA", Opm::readValueToken<std::string>("OLGA") );
BOOST_CHECK_EQUAL( "OLGA", Opm::readValueToken<std::string>("'OLGA'") );
BOOST_CHECK_EQUAL( "123*456", Opm::readValueToken<std::string>("123*456") );