#include "sequence.h" #include "node.h" #include "scanner.h" #include "token.h" #include "emitter.h" #include namespace YAML { Sequence::Sequence() { } Sequence::Sequence(const std::vector& data) { for(std::size_t i=0;iClone().release()); } Sequence::~Sequence() { Clear(); } void Sequence::Clear() { for(std::size_t i=0;i::const_iterator& it) const { it = m_data.begin(); return true; } bool Sequence::GetEnd(std::vector ::const_iterator& it) const { it = m_data.end(); return true; } Node *Sequence::GetNode(std::size_t i) const { if(i < m_data.size()) return m_data[i]; return 0; } std::size_t Sequence::GetSize() const { return m_data.size(); } void Sequence::Parse(Scanner *pScanner, ParserState& state) { Clear(); // split based on start token switch(pScanner->peek().type) { case Token::BLOCK_SEQ_START: ParseBlock(pScanner, state); break; case Token::FLOW_SEQ_START: ParseFlow(pScanner, state); break; default: break; } } void Sequence::ParseBlock(Scanner *pScanner, ParserState& state) { // eat start token pScanner->pop(); state.PushCollectionType(ParserState::BLOCK_SEQ); while(1) { if(pScanner->empty()) throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ); Token token = pScanner->peek(); if(token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END) throw ParserException(token.mark, ErrorMsg::END_OF_SEQ); pScanner->pop(); if(token.type == Token::BLOCK_SEQ_END) break; Node *pNode = new Node; m_data.push_back(pNode); // check for null if(!pScanner->empty()) { const Token& token = pScanner->peek(); if(token.type == Token::BLOCK_ENTRY || token.type == Token::BLOCK_SEQ_END) continue; } pNode->Parse(pScanner, state); } state.PopCollectionType(ParserState::BLOCK_SEQ); } void Sequence::ParseFlow(Scanner *pScanner, ParserState& state) { // eat start token pScanner->pop(); state.PushCollectionType(ParserState::FLOW_SEQ); while(1) { if(pScanner->empty()) throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW); // first check for end if(pScanner->peek().type == Token::FLOW_SEQ_END) { pScanner->pop(); break; } // then read the node Node *pNode = new Node; m_data.push_back(pNode); pNode->Parse(pScanner, state); // now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node) Token& token = pScanner->peek(); if(token.type == Token::FLOW_ENTRY) pScanner->pop(); else if(token.type != Token::FLOW_SEQ_END) throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW); } state.PopCollectionType(ParserState::FLOW_SEQ); } void Sequence::Write(Emitter& out) const { out << BeginSeq; for(std::size_t i=0;iCompare(this); } int Sequence::Compare(Sequence *pSeq) { std::size_t n = m_data.size(), m = pSeq->m_data.size(); if(n < m) return -1; else if(n > m) return 1; for(std::size_t i=0;iCompare(*pSeq->m_data[i]); if(cmp != 0) return cmp; } return 0; } }