diff --git a/modules/io/src/mol/star_parser.cc b/modules/io/src/mol/star_parser.cc index 25b71ed93c142386bb905f966b93b4ac97c6c8d0..33e235d0930a69aa038ed8dbf4e96c2e261ab4a0 100644 --- a/modules/io/src/mol/star_parser.cc +++ b/modules/io/src/mol/star_parser.cc @@ -45,7 +45,7 @@ StarParser::StarParser(const String& filename, bool items_as_row): } String StarParser::FormatDiagnostic(StarDiagType type, const String& message, - int line) + int line) const { std::stringstream ss; ss << filename_ << ":"; @@ -66,6 +66,45 @@ String StarParser::FormatDiagnostic(StarDiagType type, const String& message, return ss.str(); } +float StarParser::TryGetFloat(const StringRef& data, const String& name) const +{ + std::pair<bool, float> value = data.to_float(); + if (!value.first) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "Expecting floating point value for " + + name + ", found '" + data.str() + + "' instead.", line_num_)); + } + return value.second; +} + +int StarParser::TryGetInt(const StringRef& data, const String& name) const +{ + std::pair<bool, int> value = data.to_int(); + if (!value.first) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "Expecting integer value for " + + name + ", found '" + data.str() + + "' instead.", line_num_)); + } + return value.second; +} + +bool StarParser::TryGetBool(const StringRef& data, const String& name) const +{ + if (data.length() == 1) { + if (data[0] == 'Y' || data[0] == 'y') { + return true; + } else if (data[0] == 'N' || data[0] == 'n') { + return false; + } + } + + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "Expecting Boolean (Y/N) value for "+ + name + ", found '" + data.str() + + "' instead.", line_num_)); +} bool StarParser::SplitLine(const StringRef& line, std::vector<StringRef>& parts, bool clear) diff --git a/modules/io/src/mol/star_parser.hh b/modules/io/src/mol/star_parser.hh index cde608ccbae7a412919831bc860ad54723ba0ffe..96da40e73ed8126cc443ce66f971bcfd2e910750 100644 --- a/modules/io/src/mol/star_parser.hh +++ b/modules/io/src/mol/star_parser.hh @@ -148,9 +148,33 @@ public: /// OnBeginData() returned true. virtual void OnEndData() { } + /// \brief try to convert a value to float, on failure raise an exception. + /// + /// \param data value to be converted + /// \param name to be included in the message + /// + /// \return converted value + float TryGetFloat(const StringRef& data, const String& name) const; + + /// \brief try to convert a value to integer, on failure raise an exception. + /// + /// \param data value to be converted + /// \param name to be included in the message + /// + /// \return converted value + int TryGetInt(const StringRef& data, const String& name) const; + + /// \brief try to convert a value to bool, on failure raise an exception. + /// + /// \param data value to be converted + /// \param name to be included in the message + /// + /// \return converted value + bool TryGetBool(const StringRef& data, const String& name) const; + /// \brief format diagnostic and returns it as a string. String FormatDiagnostic(StarDiagType type, const String& message, - int line=-1); + int line=-1) const; void SetFilename(const String& filename) { diff --git a/modules/io/tests/test_star_parser.cc b/modules/io/tests/test_star_parser.cc index d91f19d6b1381a16a10cce3b66d2a0b20c3ed8d1..871740c045ceb87f8374f4fc71db73271187d976 100644 --- a/modules/io/tests/test_star_parser.cc +++ b/modules/io/tests/test_star_parser.cc @@ -395,5 +395,54 @@ BOOST_AUTO_TEST_CASE(star_loop_category_change_inplace) BOOST_CHECK_THROW(star_p.Parse(), IOException); } +BOOST_AUTO_TEST_CASE(star_try_float_conversions) +{ + BOOST_MESSAGE(" Running star_try_float_conversions tests..."); + std::ifstream s("testfiles/loop_category_change_inplace.cif"); + DataItemTestParser star_p(s); + StringRef data = StringRef("1.5", 3); + BOOST_CHECK_CLOSE(star_p.TryGetFloat(data,"positive float test"),1.5f,0.001f); + data = StringRef("foo", 3); + BOOST_CHECK_THROW(star_p.TryGetFloat(data, "negative float test"), + IOException); + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(star_try_int_conversions) +{ + BOOST_MESSAGE(" Running star_try_int_conversions tests..."); + std::ifstream s("testfiles/loop_category_change_inplace.cif"); + DataItemTestParser star_p(s); + StringRef data = StringRef("101", 3); + BOOST_CHECK_EQUAL(star_p.TryGetInt(data, "positive int test"), 101); + data = StringRef("foo", 3); + BOOST_CHECK_THROW(star_p.TryGetInt(data, "negative int test"), + IOException); + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(star_try_bool_conversions) +{ + BOOST_MESSAGE(" Running star_try_bool_conversions tests..."); + std::ifstream s("testfiles/loop_category_change_inplace.cif"); + DataItemTestParser star_p(s); + StringRef data = StringRef("Y", 1); + BOOST_CHECK(star_p.TryGetBool(data, "positive bool test ("+data.str()+")")); + data = StringRef("y", 1); + BOOST_CHECK(star_p.TryGetBool(data, "positive bool test ("+data.str()+")")); + data = StringRef("N", 1); + BOOST_CHECK(!star_p.TryGetBool(data, "positive bool test ("+data.str()+")")); + data = StringRef("n", 1); + BOOST_CHECK(!star_p.TryGetBool(data, "positive bool test ("+data.str()+")")); + data = StringRef("J", 1); + BOOST_CHECK_THROW(star_p.TryGetInt(data, + "negative bool test ("+data.str()+")"), + IOException); + data = StringRef("Foo", 3); + BOOST_CHECK_THROW(star_p.TryGetInt(data, + "negative bool test ("+data.str()+")"), + IOException); + BOOST_MESSAGE(" done."); +} BOOST_AUTO_TEST_SUITE_END();