Add char* constructor to string_view
Mostly relevant for testing, this enables string_view to work as expected with string literals.
This commit is contained in:
@@ -647,7 +647,7 @@ bool Parser::parseState(std::shared_ptr<ParserState> parserState) const {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
parserState->rawKeyword->addRawRecordString(line.string());
|
||||
parserState->rawKeyword->addRawRecordString(line);
|
||||
}
|
||||
|
||||
if (parserState->rawKeyword
|
||||
|
||||
@@ -127,15 +127,14 @@ static ParserRecordPtr createSimpleParserRecord() {
|
||||
|
||||
BOOST_AUTO_TEST_CASE(parse_validRecord_noThrow) {
|
||||
ParserRecordPtr record = createSimpleParserRecord();
|
||||
RawRecord rawRecord( "100 443 /" );
|
||||
ParseContext parseContext;
|
||||
rawRecord.dump();
|
||||
BOOST_CHECK_NO_THROW(record->parse(parseContext , rawRecord));
|
||||
RawRecord raw( string_view( "100 443" ) );
|
||||
BOOST_CHECK_NO_THROW(record->parse(parseContext, raw ) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(parse_validRecord_deckRecordCreated) {
|
||||
ParserRecordPtr record = createSimpleParserRecord();
|
||||
RawRecord rawRecord( "100 443 /" );
|
||||
RawRecord rawRecord( string_view( "100 443" ) );
|
||||
ParseContext parseContext;
|
||||
const auto deckRecord = record->parse(parseContext , rawRecord);
|
||||
BOOST_CHECK_EQUAL(2U, deckRecord.size());
|
||||
@@ -168,7 +167,7 @@ static ParserRecordPtr createMixedParserRecord() {
|
||||
|
||||
BOOST_AUTO_TEST_CASE(parse_validMixedRecord_noThrow) {
|
||||
ParserRecordPtr record = createMixedParserRecord();
|
||||
RawRecord rawRecord( "1 2 10.0 20.0 4 90.0 /" );
|
||||
RawRecord rawRecord( string_view( "1 2 10.0 20.0 4 90.0") );
|
||||
ParseContext parseContext;
|
||||
BOOST_CHECK_NO_THROW(record->parse(parseContext , rawRecord));
|
||||
}
|
||||
@@ -217,7 +216,7 @@ BOOST_AUTO_TEST_CASE(ParseWithDefault_defaultAppliedCorrectInDeck) {
|
||||
// according to the RM, this is invalid ("an asterisk by itself is not sufficient"),
|
||||
// but it seems to appear in the wild. Thus, we interpret this as "1*"...
|
||||
{
|
||||
RawRecord rawRecord( "* /" );
|
||||
RawRecord rawRecord( "* " );
|
||||
const auto deckStringItem = itemString->scan(rawRecord);
|
||||
const auto deckIntItem = itemInt->scan(rawRecord);
|
||||
const auto deckDoubleItem = itemDouble->scan(rawRecord);
|
||||
@@ -232,7 +231,7 @@ BOOST_AUTO_TEST_CASE(ParseWithDefault_defaultAppliedCorrectInDeck) {
|
||||
}
|
||||
|
||||
{
|
||||
RawRecord rawRecord( "/" );
|
||||
RawRecord rawRecord( "" );
|
||||
const auto deckStringItem = itemString->scan(rawRecord);
|
||||
const auto deckIntItem = itemInt->scan(rawRecord);
|
||||
const auto deckDoubleItem = itemDouble->scan(rawRecord);
|
||||
@@ -248,7 +247,7 @@ BOOST_AUTO_TEST_CASE(ParseWithDefault_defaultAppliedCorrectInDeck) {
|
||||
|
||||
|
||||
{
|
||||
RawRecord rawRecord( "TRYGVE 10 2.9 /" );
|
||||
RawRecord rawRecord( "TRYGVE 10 2.9 " );
|
||||
|
||||
// let the raw record be "consumed" by the items. Note that the scan() method
|
||||
// modifies the rawRecord object!
|
||||
@@ -267,7 +266,7 @@ BOOST_AUTO_TEST_CASE(ParseWithDefault_defaultAppliedCorrectInDeck) {
|
||||
|
||||
// again this is invalid according to the RM, but it is used anyway in the wild...
|
||||
{
|
||||
RawRecord rawRecord( "* * * /" );
|
||||
RawRecord rawRecord( "* * *" );
|
||||
const auto deckStringItem = itemString->scan(rawRecord);
|
||||
const auto deckIntItem = itemInt->scan(rawRecord);
|
||||
const auto deckDoubleItem = itemDouble->scan(rawRecord);
|
||||
@@ -282,7 +281,7 @@ BOOST_AUTO_TEST_CASE(ParseWithDefault_defaultAppliedCorrectInDeck) {
|
||||
}
|
||||
|
||||
{
|
||||
RawRecord rawRecord( "3* /" );
|
||||
RawRecord rawRecord( "3*" );
|
||||
const auto deckStringItem = itemString->scan(rawRecord);
|
||||
const auto deckIntItem = itemInt->scan(rawRecord);
|
||||
const auto deckDoubleItem = itemDouble->scan(rawRecord);
|
||||
@@ -309,13 +308,13 @@ BOOST_AUTO_TEST_CASE(Parse_RawRecordTooManyItems_Throws) {
|
||||
parserRecord->addItem(itemK);
|
||||
|
||||
|
||||
RawRecord rawRecord( "3 3 3 /" );
|
||||
RawRecord rawRecord( "3 3 3 " );
|
||||
BOOST_CHECK_NO_THROW(parserRecord->parse(parseContext , rawRecord));
|
||||
|
||||
RawRecord rawRecordOneExtra( "3 3 3 4 /" );
|
||||
RawRecord rawRecordOneExtra( "3 3 3 4 " );
|
||||
BOOST_CHECK_THROW(parserRecord->parse(parseContext , rawRecordOneExtra), std::invalid_argument);
|
||||
|
||||
RawRecord rawRecordForgotRecordTerminator( "3 3 3 \n 4 4 4 /" );
|
||||
RawRecord rawRecordForgotRecordTerminator( "3 3 3 \n 4 4 4 " );
|
||||
BOOST_CHECK_THROW(parserRecord->parse(parseContext , rawRecordForgotRecordTerminator), std::invalid_argument);
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Opm {
|
||||
const unsigned int maxKeywordLength = 8;
|
||||
|
||||
static inline bool is_separator( char ch ) {
|
||||
return ch == '\t' || ch == ' ';
|
||||
return ch == '\t' || ch == ' ' || ch == '\n';
|
||||
}
|
||||
|
||||
static inline bool is_quote( char ch ) {
|
||||
|
||||
@@ -26,8 +26,10 @@
|
||||
|
||||
namespace Opm {
|
||||
|
||||
static const std::string emptystr = "";
|
||||
|
||||
RawKeyword::RawKeyword(const string_view& name, Raw::KeywordSizeEnum sizeType , const std::string& filename, size_t lineNR) {
|
||||
RawKeyword::RawKeyword(const string_view& name, Raw::KeywordSizeEnum sizeType , const std::string& filename, size_t lineNR) :
|
||||
m_partialRecordString( emptystr ) {
|
||||
if (sizeType == Raw::SLASH_TERMINATED || sizeType == Raw::UNKNOWN) {
|
||||
commonInit(name.string(),filename,lineNR);
|
||||
m_sizeType = sizeType;
|
||||
@@ -74,17 +76,16 @@ namespace Opm {
|
||||
return m_records.size();
|
||||
}
|
||||
|
||||
static inline bool isTerminator( const std::string& line ) {
|
||||
auto fst = std::find_if_not( line.begin(), line.end(),
|
||||
RawConsts::is_separator );
|
||||
return fst != line.end() && *fst == RawConsts::slash;
|
||||
static inline bool isTerminator( const string_view& line ) {
|
||||
return line.size() == 1 && line.back() == RawConsts::slash;
|
||||
}
|
||||
|
||||
/// Important method, being repeatedly called. When a record is terminated,
|
||||
/// it is added to the list of records, and a new record is started.
|
||||
|
||||
void RawKeyword::addRawRecordString(const std::string& partialRecordString) {
|
||||
m_partialRecordString += " " + partialRecordString;
|
||||
void RawKeyword::addRawRecordString(const string_view& partialRecordString) {
|
||||
if( m_partialRecordString == emptystr ) m_partialRecordString = partialRecordString;
|
||||
else m_partialRecordString = { m_partialRecordString.begin(), partialRecordString.end() };
|
||||
|
||||
|
||||
if( m_sizeType != Raw::FIXED && isTerminator( m_partialRecordString ) ) {
|
||||
@@ -92,12 +93,12 @@ namespace Opm {
|
||||
m_currentNumTables += 1;
|
||||
if (m_currentNumTables == m_numTables) {
|
||||
m_isFinished = true;
|
||||
m_partialRecordString.clear();
|
||||
m_partialRecordString = emptystr;
|
||||
return;
|
||||
}
|
||||
} else if( m_sizeType != Raw::UNKNOWN ) {
|
||||
m_isFinished = true;
|
||||
m_partialRecordString.clear();
|
||||
m_partialRecordString = emptystr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -107,14 +108,21 @@ namespace Opm {
|
||||
if( this->getKeywordName() == "TITLE"
|
||||
|| RawRecord::isTerminatedRecordString( partialRecordString ) ) {
|
||||
|
||||
m_records.emplace_back( std::move( m_partialRecordString ), m_filename, m_name );
|
||||
m_partialRecordString.clear();
|
||||
auto recstr = partialRecordString.back() == '/'
|
||||
? string_view{ m_partialRecordString.begin(), m_partialRecordString.end() - 1 }
|
||||
: m_partialRecordString;
|
||||
|
||||
m_records.emplace_back( recstr, m_filename, m_name );
|
||||
m_partialRecordString = emptystr;
|
||||
|
||||
if( m_sizeType == Raw::FIXED && m_records.size() == m_fixedSize )
|
||||
m_isFinished = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RawKeyword::addRawRecordString(const std::string& rec ) {
|
||||
addRawRecordString( string_view( rec ) );
|
||||
}
|
||||
|
||||
const RawRecord& RawKeyword::getFirstRecord() const {
|
||||
return *m_records.begin();
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <list>
|
||||
|
||||
#include <opm/parser/eclipse/RawDeck/RawEnums.hpp>
|
||||
#include <opm/parser/eclipse/Utility/Stringview.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
@@ -46,7 +47,9 @@ namespace Opm {
|
||||
RawKeyword(const std::string& name , const std::string& filename, size_t lineNR , size_t inputSize , bool isTableCollection = false);
|
||||
|
||||
const std::string& getKeywordName() const;
|
||||
void addRawRecordString(const std::string& partialRecordString);
|
||||
void addRawRecordString( const string_view& );
|
||||
/* The string overload exists for testing only */
|
||||
void addRawRecordString( const std::string& );
|
||||
size_t size() const;
|
||||
Raw::KeywordSizeEnum getSizeType() const;
|
||||
|
||||
@@ -82,7 +85,7 @@ namespace Opm {
|
||||
size_t m_currentNumTables;
|
||||
std::string m_name;
|
||||
std::list< RawRecord > m_records;
|
||||
std::string m_partialRecordString;
|
||||
string_view m_partialRecordString;
|
||||
|
||||
size_t m_lineNR;
|
||||
std::string m_filename;
|
||||
|
||||
@@ -33,45 +33,13 @@ using namespace std;
|
||||
|
||||
namespace Opm {
|
||||
|
||||
static inline std::string::const_iterator findTerminatingSlash( const std::string& rec ) {
|
||||
|
||||
if( rec.back() == RawConsts::slash ) return rec.end() - 1;
|
||||
|
||||
/* possible fast path: no terminating slash in record */
|
||||
const auto rslash = std::find( rec.rbegin(), rec.rend(), RawConsts::slash );
|
||||
if( rslash == rec.rend() ) return rec.end();
|
||||
|
||||
/* heuristic: since slash makes everything to the right of it into a
|
||||
* no-op, if there is more than whitespace to its right before newline
|
||||
* we guess that this is in fact not the terminating slash but rather
|
||||
* some comment or description. Most of the time this is not the case,
|
||||
* and it is slower, so avoid doing it if possible.
|
||||
*/
|
||||
|
||||
auto slash = (rslash + 1).base();
|
||||
if( std::find_if_not( slash, rec.end(), RawConsts::is_separator ) == rec.end() )
|
||||
return slash;
|
||||
|
||||
/*
|
||||
* left-to-right search after last closing quote. Like the previous
|
||||
* implementation, assumes there are no quote marks past the
|
||||
* terminating slash (as per the Eclipse manual). Search past last
|
||||
* quote because slashes can appear in quotes in filenames etc, but
|
||||
* will always be quoted.
|
||||
*/
|
||||
|
||||
const auto quote = std::find( rec.rbegin(), rec.rend(), RawConsts::quote );
|
||||
const auto begin = quote == rec.rend() ? rec.begin() : (quote + 1).base();
|
||||
return std::find( begin, rec.end(), RawConsts::slash );
|
||||
}
|
||||
|
||||
static inline const char* first_nonspace (
|
||||
const char* begin,
|
||||
const char* end ) {
|
||||
static inline std::string::const_iterator first_nonspace (
|
||||
std::string::const_iterator begin,
|
||||
std::string::const_iterator end ) {
|
||||
return std::find_if_not( begin, end, RawConsts::is_separator );
|
||||
}
|
||||
|
||||
static std::deque< string_view > splitSingleRecordString( const std::string& rec ) {
|
||||
static std::deque< string_view > splitSingleRecordString( const string_view& record ) {
|
||||
|
||||
std::deque< string_view > dst;
|
||||
string_view record( rec );
|
||||
@@ -84,13 +52,6 @@ namespace Opm {
|
||||
auto quote_end = std::find( current + 1, record.end(), RawConsts::quote ) + 1;
|
||||
dst.push_back( { current, quote_end } );
|
||||
current = quote_end;
|
||||
} else if( *current == RawConsts::slash ) {
|
||||
/* some records are break the optimistic algorithm of
|
||||
* findTerminatingSlash and contain multiple trailing slashes
|
||||
* with nothing inbetween. The first occuring one is the actual
|
||||
* terminator and we simply ignore everything following it.
|
||||
*/
|
||||
break;
|
||||
} else {
|
||||
auto token_end = std::find_if( current, record.end(), RawConsts::is_separator );
|
||||
dst.push_back( { current, token_end } );
|
||||
@@ -111,23 +72,15 @@ namespace Opm {
|
||||
*
|
||||
*/
|
||||
|
||||
static inline bool even_quotes( const std::string& str ) {
|
||||
template< typename T >
|
||||
static inline bool even_quotes( const T& str ) {
|
||||
return std::count( str.begin(), str.end(), RawConsts::quote ) % 2 == 0;
|
||||
}
|
||||
|
||||
static inline std::string&& trim_record( std::string& str ) {
|
||||
auto end = findTerminatingSlash( str );
|
||||
/* type hack to work around findTerminatingSlash returning a const_iterator */
|
||||
std::string::iterator mut_end( str.begin() );
|
||||
std::advance( mut_end, std::distance< decltype( end ) >( mut_end, end ) );
|
||||
str.erase( mut_end, str.end() );
|
||||
return std::move( str );
|
||||
}
|
||||
|
||||
RawRecord::RawRecord(std::string&& singleRecordString,
|
||||
RawRecord::RawRecord(const string_view& singleRecordString,
|
||||
const std::string& fileName,
|
||||
const std::string& keywordName) :
|
||||
m_sanitizedRecordString( trim_record( singleRecordString ) ),
|
||||
m_sanitizedRecordString( singleRecordString ),
|
||||
m_recordItems( splitSingleRecordString( m_sanitizedRecordString ) ),
|
||||
m_fileName(fileName),
|
||||
m_keywordName(keywordName)
|
||||
@@ -136,7 +89,7 @@ namespace Opm {
|
||||
if( !even_quotes( singleRecordString ) )
|
||||
throw std::invalid_argument(
|
||||
"Input string is not a complete record string, "
|
||||
"offending string: " + singleRecordString
|
||||
"offending string: '" + singleRecordString + "'"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -163,14 +116,15 @@ namespace Opm {
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
const std::string& RawRecord::getRecordString() const {
|
||||
return m_sanitizedRecordString;
|
||||
std::string RawRecord::getRecordString() const {
|
||||
return m_sanitizedRecordString.string();
|
||||
}
|
||||
|
||||
bool RawRecord::isTerminatedRecordString(const std::string& candidateRecordString) {
|
||||
const auto terminatingSlash = findTerminatingSlash(candidateRecordString);
|
||||
bool hasTerminatingSlash = terminatingSlash != candidateRecordString.end();
|
||||
return hasTerminatingSlash && even_quotes( candidateRecordString );
|
||||
bool RawRecord::isTerminatedRecordString( const string_view& str ) {
|
||||
return str.back() == RawConsts::slash;
|
||||
}
|
||||
|
||||
bool RawRecord::isTerminatedRecordString( const std::string& str ) {
|
||||
return isTerminatedRecordString( string_view( str ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,23 +35,24 @@ namespace Opm {
|
||||
|
||||
class RawRecord {
|
||||
public:
|
||||
RawRecord(std::string&&, const std::string& fileName = "", const std::string& keywordName = "");
|
||||
RawRecord( const string_view&, const std::string& fileName = "", const std::string& keywordName = "");
|
||||
|
||||
inline string_view pop_front();
|
||||
void push_front(std::string token);
|
||||
inline size_t size() const;
|
||||
|
||||
const std::string& getRecordString() const;
|
||||
std::string getRecordString() const;
|
||||
inline string_view getItem(size_t index) const;
|
||||
const std::string& getFileName() const;
|
||||
const std::string& getKeywordName() const;
|
||||
|
||||
static bool isTerminatedRecordString(const std::string& candidateRecordString);
|
||||
static bool isTerminatedRecordString( const string_view& );
|
||||
static bool isTerminatedRecordString( const std::string& );
|
||||
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
std::string m_sanitizedRecordString;
|
||||
string_view m_sanitizedRecordString;
|
||||
std::deque< string_view > m_recordItems;
|
||||
std::list< std::string > expanded_items;
|
||||
const std::string m_fileName;
|
||||
|
||||
@@ -54,6 +54,7 @@ namespace Opm {
|
||||
inline string_view( const_iterator, size_t );
|
||||
inline string_view( const std::string& );
|
||||
inline string_view( const std::string&, size_t );
|
||||
inline string_view( const char* );
|
||||
|
||||
inline const_iterator begin() const;
|
||||
inline const_iterator end() const;
|
||||
@@ -166,6 +167,10 @@ namespace Opm {
|
||||
string_view( str.data(), count )
|
||||
{}
|
||||
|
||||
inline string_view::string_view( const char* str ) :
|
||||
string_view( str, str + std::strlen( str ) + 1 )
|
||||
{}
|
||||
|
||||
inline string_view::const_iterator string_view::begin() const {
|
||||
return this->fst;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user