DeckRecord ParserRecord::parse(const ParseContext& parseContext , MessageContainer& msgContainer, RawRecord& rawRecord ) const { std::vector< DeckItem > items; items.reserve( this->size() + 20 ); for( const auto& parserItem : *this ) items.emplace_back( parserItem->scan( rawRecord ) ); if (rawRecord.size() > 0) { std::string msg = "The RawRecord for keyword \"" + rawRecord.getKeywordName() + "\" in file\"" + rawRecord.getFileName() + "\" contained " + std::to_string(rawRecord.size()) + " too many items according to the spec. RawRecord was: " + rawRecord.getRecordString(); parseContext.handleError(ParseContext::PARSE_EXTRA_DATA , msgContainer, msg); } return { std::move( items ) }; }
DeckRecord ParserRecord::parse(const ParseContext& parseContext , MessageContainer& msgContainer, RawRecord& rawRecord ) const { DeckRecord deckRecord( size() + 20 ); for (size_t i = 0; i < size(); i++) { auto parserItem = get(i); deckRecord.addItem( parserItem->scan( rawRecord ) ); } if (rawRecord.size() > 0) { std::string msg = "The RawRecord for keyword \"" + rawRecord.getKeywordName() + "\" in file\"" + rawRecord.getFileName() + "\" contained " + std::to_string(rawRecord.size()) + " too many items according to the spec. RawRecord was: " + rawRecord.getRecordString(); parseContext.handleError(ParseContext::PARSE_EXTRA_DATA , msgContainer, msg); } return deckRecord; }
DeckItem ParserItemScan(const ParserItemType * self, RawRecord& rawRecord ) { auto deckItem = DeckItem::make< ValueType >( self->name(), rawRecord.size() ); if (self->sizeType() == ALL) { while (rawRecord.size() > 0) { auto token = rawRecord.pop_front(); std::string countString; std::string valueString; if (isStarToken(token, countString, valueString)) { StarToken st(token, countString, valueString); ValueType value; if (st.hasValue()) { value = readValueToken<ValueType>(st.valueString()); deckItem.push_back( value , st.count()); } else { value = self->getDefault(); for (size_t i=0; i < st.count(); i++) deckItem.push_backDefault( value ); } } else { deckItem.push_back( readValueToken<ValueType>( token ) ); } } } else { if (rawRecord.size() == 0) { // if the record was ended prematurely, if (self->hasDefault()) { // use the default value for the item, if there is one... deckItem.push_backDefault( self->getDefault() ); } else { // ... otherwise indicate that the deck item should throw once the // item's data is accessed. deckItem.push_backDummyDefault(); } } else { // The '*' should be interpreted as a repetition indicator, but it must // be preceeded by an integer... auto token = rawRecord.pop_front(); std::string countString; std::string valueString; if (isStarToken(token, countString, valueString)) { StarToken st(token, countString, valueString); if (!st.hasValue()) { if (self->hasDefault()) deckItem.push_backDefault( self->getDefault() ); else deckItem.push_backDummyDefault(); } else deckItem.push_back(readValueToken<ValueType>(st.valueString())); const auto value_start = token.size() - valueString.size(); // replace the first occurence of "N*FOO" by a sequence of N-1 times // "FOO". this is slightly hacky, but it makes it work if the // number of defaults pass item boundaries... // We can safely make a string_view of one_star because it // has static storage static const char* one_star = "1*"; string_view rep = !st.hasValue() ? string_view{ one_star } : string_view{ token.begin() + value_start, token.end() }; rawRecord.prepend( st.count() - 1, rep ); } else { deckItem.push_back( readValueToken<ValueType>( token ) ); } } } return deckItem; }