Handle quotes better
This allows to arbitrary characters like stars into strings. e.g. MYKEYWORD '123*456' 2*'Hello, World! (*)' / is now a valid record with three strings while it threw an exception before. This patch works by transferring the removal of the quotes from the RawDeck class to the readValueToken<T>() function which now has a specialization for strings that deals with quotes. One small complication is that the RawDeck needs to be adapted in order not to split tokens in the middle of strings. Finally, the StarToken class does not deal with the conversion from string to the value type of the item anymore which allows it to become a normal class instead of a template...
This commit is contained in:
parent
879f30e3ff
commit
6eb3421f38
@ -266,14 +266,14 @@ namespace Opm {
|
||||
else if (parserState->rawKeyword->getKeywordName() == Opm::RawConsts::paths) {
|
||||
for (size_t i = 0; i < parserState->rawKeyword->size(); i++) {
|
||||
RawRecordConstPtr record = parserState->rawKeyword->getRecord(i);
|
||||
std::string pathName = record->getItem(0);
|
||||
std::string pathValue = record->getItem(1);
|
||||
std::string pathName = readValueToken<std::string>(record->getItem(0));
|
||||
std::string pathValue = readValueToken<std::string>(record->getItem(1));
|
||||
parserState->pathMap.insert(std::pair<std::string, std::string>(pathName, pathValue));
|
||||
}
|
||||
}
|
||||
else if (parserState->rawKeyword->getKeywordName() == Opm::RawConsts::include) {
|
||||
RawRecordConstPtr firstRecord = parserState->rawKeyword->getRecord(0);
|
||||
std::string includeFileAsString = firstRecord->getItem(0);
|
||||
std::string includeFileAsString = readValueToken<std::string>(firstRecord->getItem(0));
|
||||
boost::filesystem::path includeFile = getIncludeFilePath(parserState, includeFileAsString);
|
||||
|
||||
if (verbose)
|
||||
|
@ -113,11 +113,11 @@ namespace Opm {
|
||||
std::string countString;
|
||||
std::string valueString;
|
||||
if (isStarToken(token, countString, valueString)) {
|
||||
StarToken<ValueType> st(token, countString, valueString);
|
||||
StarToken st(token, countString, valueString);
|
||||
ValueType value;
|
||||
|
||||
if (st.hasValue()) {
|
||||
value = st.value();
|
||||
value = readValueToken<ValueType>(st.valueString());
|
||||
deckItem->push_backMultiple( value , st.count());
|
||||
} else {
|
||||
value = self->getDefault();
|
||||
@ -141,12 +141,12 @@ namespace Opm {
|
||||
std::string countString;
|
||||
std::string valueString;
|
||||
if (isStarToken(token, countString, valueString)) {
|
||||
StarToken<ValueType> st(token, countString, valueString);
|
||||
StarToken st(token, countString, valueString);
|
||||
|
||||
if (!st.hasValue())
|
||||
deckItem->push_backDefault( self->getDefault() );
|
||||
else
|
||||
deckItem->push_back(st.value());
|
||||
deckItem->push_back(readValueToken<ValueType>(st.valueString()));
|
||||
|
||||
// replace the first occurence of "N*FOO" by a sequence of N-1 times
|
||||
// "1*FOO". this is slightly hacky, but it makes it work if the
|
||||
|
@ -576,7 +576,7 @@ BOOST_AUTO_TEST_CASE(init_defaultvalue_defaultset) {
|
||||
ParserStringItem itemString(std::string("ITEM1") , "DEFAULT");
|
||||
RawRecordPtr rawRecord(new RawRecord(("'1*'/")));
|
||||
DeckItemConstPtr deckItem = itemString.scan(rawRecord);
|
||||
BOOST_CHECK_EQUAL("DEFAULT", deckItem->getString(0));
|
||||
BOOST_CHECK_EQUAL("1*", deckItem->getString(0));
|
||||
|
||||
rawRecord.reset(new RawRecord("13*/"));
|
||||
deckItem = itemString.scan(rawRecord);
|
||||
@ -595,9 +595,9 @@ BOOST_AUTO_TEST_CASE(init_defaultvalue_defaultset) {
|
||||
BOOST_AUTO_TEST_CASE(scan_all_valuesCorrect) {
|
||||
ParserItemSizeEnum sizeType = ALL;
|
||||
ParserStringItem itemString("ITEMWITHMANY", sizeType);
|
||||
RawRecordPtr rawRecord(new RawRecord("'WELL1' FISK BANAN 3*X OPPLEGG_FOR_DATAANALYSE /"));
|
||||
RawRecordPtr rawRecord(new RawRecord("'WELL1' FISK BANAN 3*X OPPLEGG_FOR_DATAANALYSE 'Foo$*!% BAR' /"));
|
||||
DeckItemConstPtr deckItem = itemString.scan(rawRecord);
|
||||
BOOST_CHECK_EQUAL(7U, deckItem->size());
|
||||
BOOST_CHECK_EQUAL(8U, deckItem->size());
|
||||
|
||||
BOOST_CHECK_EQUAL("WELL1", deckItem->getString(0));
|
||||
BOOST_CHECK_EQUAL("FISK", deckItem->getString(1));
|
||||
@ -606,6 +606,7 @@ BOOST_AUTO_TEST_CASE(scan_all_valuesCorrect) {
|
||||
BOOST_CHECK_EQUAL("X", deckItem->getString(4));
|
||||
BOOST_CHECK_EQUAL("X", deckItem->getString(5));
|
||||
BOOST_CHECK_EQUAL("OPPLEGG_FOR_DATAANALYSE", deckItem->getString(6));
|
||||
BOOST_CHECK_EQUAL("Foo$*!% BAR", deckItem->getString(7));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(scan_all_withdefaults) {
|
||||
|
@ -103,12 +103,14 @@ namespace Opm {
|
||||
char currentChar;
|
||||
char tokenStartCharacter=' ';
|
||||
std::string currentToken = "";
|
||||
bool inQuote = false;
|
||||
for (unsigned i = 0; i < m_sanitizedRecordString.size(); i++) {
|
||||
currentChar = m_sanitizedRecordString[i];
|
||||
if (charIsSeparator(currentChar)) {
|
||||
if (!inQuote && charIsSeparator(currentChar)) {
|
||||
processSeparatorCharacter(currentToken, currentChar, tokenStartCharacter);
|
||||
} else if (currentChar == RawConsts::quote) {
|
||||
processQuoteCharacters(currentToken, currentChar, tokenStartCharacter);
|
||||
inQuote = !inQuote;
|
||||
processNonSpecialCharacters(currentToken, currentChar);
|
||||
} else {
|
||||
processNonSpecialCharacters(currentToken, currentChar);
|
||||
}
|
||||
@ -131,19 +133,6 @@ namespace Opm {
|
||||
}
|
||||
}
|
||||
|
||||
void RawRecord::processQuoteCharacters(std::string& currentToken, const char& currentChar, char& tokenStartCharacter) {
|
||||
if (currentChar == tokenStartCharacter) {
|
||||
if (currentToken.size() > 0) {
|
||||
m_recordItems.push_back(currentToken);
|
||||
currentToken.clear();
|
||||
}
|
||||
tokenStartCharacter = '\0';
|
||||
} else {
|
||||
tokenStartCharacter = currentChar;
|
||||
currentToken.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void RawRecord::processNonSpecialCharacters(std::string& currentToken, const char& currentChar) {
|
||||
currentToken += currentChar;
|
||||
}
|
||||
|
@ -31,17 +31,27 @@ namespace Opm {
|
||||
std::string& valueString);
|
||||
|
||||
template <class T>
|
||||
T readValueToken(const std::string& valueToken ) {
|
||||
T readValueToken(const std::string& valueString) {
|
||||
try {
|
||||
return boost::lexical_cast<T>(valueToken);
|
||||
return boost::lexical_cast<T>(valueString);
|
||||
}
|
||||
catch (boost::bad_lexical_cast&) {
|
||||
throw std::invalid_argument("Unable to parse string" + valueToken + " to typeid: " + typeid(T).name());
|
||||
throw std::invalid_argument("Unable to parse string" + valueString + " to typeid: " + typeid(T).name());
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
class StarToken {
|
||||
public:
|
||||
StarToken(const std::string& token)
|
||||
@ -62,12 +72,6 @@ public:
|
||||
return m_count;
|
||||
}
|
||||
|
||||
T value() const {
|
||||
if (!hasValue())
|
||||
throw std::invalid_argument("The input token did not specify a value ");
|
||||
return m_value;
|
||||
}
|
||||
|
||||
bool hasValue() const {
|
||||
return !m_valueString.empty();
|
||||
}
|
||||
@ -110,13 +114,9 @@ private:
|
||||
// TODO: decorate the deck with a warning instead?
|
||||
throw std::invalid_argument("Specifing zero repetitions is not allowed. Token: \'" + token + "\'.");
|
||||
}
|
||||
|
||||
if (!m_valueString.empty())
|
||||
m_value = readValueToken<T>( m_valueString );
|
||||
}
|
||||
|
||||
ssize_t m_count;
|
||||
T m_value;
|
||||
std::string m_countString;
|
||||
std::string m_valueString;
|
||||
};
|
||||
|
@ -33,8 +33,8 @@ BOOST_AUTO_TEST_CASE(RawRecordGetRecordsCorrectElementsReturned) {
|
||||
|
||||
BOOST_CHECK_EQUAL((unsigned) 4, record->size());
|
||||
|
||||
BOOST_CHECK_EQUAL("NODIR ", record->getItem(0));
|
||||
BOOST_CHECK_EQUAL("REVERS", record->getItem(1));
|
||||
BOOST_CHECK_EQUAL("'NODIR '", record->getItem(0));
|
||||
BOOST_CHECK_EQUAL("'REVERS'", record->getItem(1));
|
||||
BOOST_CHECK_EQUAL("1", record->getItem(2));
|
||||
BOOST_CHECK_EQUAL("20", record->getItem(3));
|
||||
}
|
||||
@ -55,8 +55,8 @@ BOOST_AUTO_TEST_CASE(Rawrecord_OperatorThis_OK) {
|
||||
Opm::RawRecord record(" 'NODIR ' 'REVERS' 1 20 /");
|
||||
Opm::RawRecordPtr recordPtr(new Opm::RawRecord(" 'NODIR ' 'REVERS' 1 20 /"));
|
||||
|
||||
BOOST_CHECK_EQUAL("NODIR ", record.getItem(0));
|
||||
BOOST_CHECK_EQUAL("REVERS", record.getItem(1));
|
||||
BOOST_CHECK_EQUAL("'NODIR '", record.getItem(0));
|
||||
BOOST_CHECK_EQUAL("'REVERS'", record.getItem(1));
|
||||
BOOST_CHECK_EQUAL("1", record.getItem(2));
|
||||
BOOST_CHECK_EQUAL("20", record.getItem(3));
|
||||
|
||||
|
@ -24,99 +24,69 @@
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(NoStarThrows) {
|
||||
BOOST_REQUIRE_THROW(Opm::StarToken<int> st("Hei...") , std::invalid_argument);
|
||||
BOOST_REQUIRE_THROW(Opm::StarToken st("Hei...") , std::invalid_argument);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(InvalidCountThrow) {
|
||||
BOOST_REQUIRE_THROW( Opm::StarToken<int> st("X*") , std::invalid_argument);
|
||||
BOOST_REQUIRE_THROW( Opm::StarToken<int> st("1.25*") , std::invalid_argument);
|
||||
BOOST_REQUIRE_THROW( Opm::StarToken<int> st("-3*") , std::invalid_argument);
|
||||
BOOST_REQUIRE_THROW( Opm::StarToken<int> st("0*") , std::invalid_argument);
|
||||
BOOST_REQUIRE_THROW( Opm::StarToken<int> st("*123") , std::invalid_argument);
|
||||
BOOST_REQUIRE_THROW( Opm::StarToken st("X*") , std::invalid_argument);
|
||||
BOOST_REQUIRE_THROW( Opm::StarToken st("1.25*") , std::invalid_argument);
|
||||
BOOST_REQUIRE_THROW( Opm::StarToken st("-3*") , std::invalid_argument);
|
||||
BOOST_REQUIRE_THROW( Opm::StarToken st("0*") , std::invalid_argument);
|
||||
BOOST_REQUIRE_THROW( Opm::StarToken st("*123") , std::invalid_argument);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CountCorrect) {
|
||||
Opm::StarToken<int> st1("*");
|
||||
Opm::StarToken<int> st2("5*");
|
||||
Opm::StarToken<int> st3("54*");
|
||||
BOOST_CHECK(st1.count() == 1);
|
||||
Opm::StarToken st1("*");
|
||||
Opm::StarToken st2("5*");
|
||||
Opm::StarToken st3("54*");
|
||||
BOOST_CHECK(st1.countString() == "");
|
||||
BOOST_CHECK(st2.countString() == "5");
|
||||
BOOST_CHECK(st3.countString() == "54");
|
||||
|
||||
BOOST_CHECK(st1.valueString() == "");
|
||||
BOOST_CHECK(st2.valueString() == "");
|
||||
BOOST_CHECK(st3.valueString() == "");
|
||||
|
||||
BOOST_CHECK(!st1.hasValue());
|
||||
BOOST_CHECK(!st2.hasValue());
|
||||
BOOST_CHECK(!st3.hasValue());
|
||||
|
||||
BOOST_REQUIRE_EQUAL(1U , st1.count());
|
||||
BOOST_REQUIRE_EQUAL(5U , st2.count());
|
||||
BOOST_REQUIRE_EQUAL(54U , st3.count());
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(NoValueGetValueThrow) {
|
||||
Opm::StarToken<int> st1("*");
|
||||
Opm::StarToken<int> st2("5*");
|
||||
BOOST_CHECK_THROW( st1.value() , std::invalid_argument );
|
||||
BOOST_CHECK_THROW( st2.value() , std::invalid_argument );
|
||||
Opm::StarToken st1("*");
|
||||
Opm::StarToken st2("5*");
|
||||
BOOST_CHECK_EQUAL( false , st1.hasValue());
|
||||
BOOST_CHECK_EQUAL( false , st2.hasValue());
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(IntMalformedValueThrows) {
|
||||
BOOST_CHECK_THROW( Opm::StarToken<int> st1("1*10X") , std::invalid_argument);
|
||||
BOOST_CHECK_THROW( Opm::StarToken<int> st1("1*X") , std::invalid_argument);
|
||||
BOOST_CHECK_THROW( Opm::StarToken<int> st1("1*10.25") , std::invalid_argument);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(StarNoCountThrows) {
|
||||
BOOST_CHECK_THROW( Opm::StarToken<int> st1("*10") , std::invalid_argument);
|
||||
BOOST_CHECK_THROW( Opm::StarToken<double> st1("*1.0") , std::invalid_argument);
|
||||
BOOST_CHECK_THROW( Opm::StarToken<std::string> st1("*String") , std::invalid_argument);
|
||||
BOOST_CHECK_THROW( Opm::StarToken st1("*10") , std::invalid_argument);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(DoubleMalformedValueThrows) {
|
||||
BOOST_CHECK_THROW( Opm::StarToken<double> st1("1*10X") , std::invalid_argument);
|
||||
BOOST_CHECK_THROW( Opm::StarToken<double> st1("1*X") , std::invalid_argument);
|
||||
BOOST_CHECK_THROW( Opm::StarToken<double> st1("1*10.25F") , std::invalid_argument);
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CorrectIntValue) {
|
||||
Opm::StarToken<int> st1("1*10");
|
||||
Opm::StarToken<int> st2("5*20");
|
||||
BOOST_AUTO_TEST_CASE(CorrectValueString) {
|
||||
Opm::StarToken st1("1*10.09");
|
||||
Opm::StarToken st2("5*20.13");
|
||||
Opm::StarToken st3("1*'123'");
|
||||
Opm::StarToken st4("1*123*456");
|
||||
BOOST_CHECK_EQUAL( true , st1.hasValue());
|
||||
BOOST_CHECK_EQUAL( true , st2.hasValue());
|
||||
BOOST_CHECK_EQUAL( true , st3.hasValue());
|
||||
BOOST_CHECK_EQUAL( true , st4.hasValue());
|
||||
|
||||
BOOST_CHECK_EQUAL( 10 , st1.value());
|
||||
BOOST_CHECK_EQUAL( 20 , st2.value());
|
||||
BOOST_CHECK_EQUAL( "10.09" , st1.valueString());
|
||||
BOOST_CHECK_EQUAL( "20.13" , st2.valueString());
|
||||
BOOST_CHECK_EQUAL( "'123'" , st3.valueString());
|
||||
BOOST_CHECK_EQUAL( "123*456" , st4.valueString());
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CorrectDoubleValue) {
|
||||
Opm::StarToken<double> st1("1*10.09");
|
||||
Opm::StarToken<double> st2("5*20.13");
|
||||
BOOST_CHECK_EQUAL( true , st1.hasValue());
|
||||
BOOST_CHECK_EQUAL( true , st2.hasValue());
|
||||
|
||||
BOOST_CHECK_EQUAL( 10.09 , st1.value());
|
||||
BOOST_CHECK_EQUAL( 20.13 , st2.value());
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CorrectStringValue) {
|
||||
Opm::StarToken<std::string> st1("1*10.09");
|
||||
Opm::StarToken<std::string> st2("5*20.13");
|
||||
BOOST_CHECK_EQUAL( true , st1.hasValue());
|
||||
BOOST_CHECK_EQUAL( true , st2.hasValue());
|
||||
|
||||
BOOST_CHECK_EQUAL( "10.09" , st1.value());
|
||||
BOOST_CHECK_EQUAL( "20.13" , st2.value());
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( ContainsStar_WithStar_ReturnsTrue ) {
|
||||
std::string countString, valueString;
|
||||
BOOST_CHECK_EQUAL( true , Opm::isStarToken("*", countString, valueString) );
|
||||
@ -125,6 +95,7 @@ BOOST_AUTO_TEST_CASE( ContainsStar_WithStar_ReturnsTrue ) {
|
||||
BOOST_CHECK_EQUAL( true , Opm::isStarToken("1*2", countString, valueString) );
|
||||
|
||||
BOOST_CHECK_EQUAL( false , Opm::isStarToken("12", countString, valueString) );
|
||||
BOOST_CHECK_EQUAL( false , Opm::isStarToken("'12*34'", countString, valueString) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( readValueToken_basic_validity_tests ) {
|
||||
@ -132,4 +103,7 @@ BOOST_AUTO_TEST_CASE( readValueToken_basic_validity_tests ) {
|
||||
BOOST_CHECK_THROW( Opm::readValueToken<double>("truls"), std::invalid_argument );
|
||||
BOOST_CHECK_EQUAL( "3.3", Opm::readValueToken<std::string>("3.3") );
|
||||
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") );
|
||||
BOOST_CHECK_EQUAL( "123*456", Opm::readValueToken<std::string>("'123*456'") );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user