sequence.cpp 3.52 KB
Newer Older
1
2
3
4
5
#include "crt.h"
#include "sequence.h"
#include "node.h"
#include "scanner.h"
#include "token.h"
6
#include "emitter.h"
7
#include <stdexcept>
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

namespace YAML
{
	Sequence::Sequence()
	{

	}

	Sequence::~Sequence()
	{
		Clear();
	}

	void Sequence::Clear()
	{
23
		for(std::size_t i=0;i<m_data.size();i++)
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
			delete m_data[i];
		m_data.clear();
	}

	bool Sequence::GetBegin(std::vector <Node *>::const_iterator& it) const
	{
		it = m_data.begin();
		return true;
	}

	bool Sequence::GetEnd(std::vector <Node *>::const_iterator& it) const
	{
		it = m_data.end();
		return true;
	}

40
	Node *Sequence::GetNode(std::size_t i) const
41
42
43
44
45
46
	{
		if(i < m_data.size())
			return m_data[i];
		return 0;
	}

47
	std::size_t Sequence::GetSize() const
48
49
50
51
52
53
54
55
56
57
58
59
60
	{
		return m_data.size();
	}

	void Sequence::Parse(Scanner *pScanner, const ParserState& state)
	{
		Clear();

		// split based on start token
		switch(pScanner->peek().type) {
			case TT_BLOCK_SEQ_START: ParseBlock(pScanner, state); break;
			case TT_BLOCK_ENTRY: ParseImplicit(pScanner, state); break;
			case TT_FLOW_SEQ_START: ParseFlow(pScanner, state); break;
Jesse Beder's avatar
Jesse Beder committed
61
			default: break;
62
63
64
65
66
67
68
69
70
71
		}
	}

	void Sequence::ParseBlock(Scanner *pScanner, const ParserState& state)
	{
		// eat start token
		pScanner->pop();

		while(1) {
			if(pScanner->empty())
72
				throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ);
73
74
75

			Token token = pScanner->peek();
			if(token.type != TT_BLOCK_ENTRY && token.type != TT_BLOCK_END)
76
				throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
77
78
79
80
81
82
83

			pScanner->pop();
			if(token.type == TT_BLOCK_END)
				break;

			Node *pNode = new Node;
			m_data.push_back(pNode);
84
85
86
87
88
89
90
91
			
			// check for null
			if(!pScanner->empty()) {
				const Token& token = pScanner->peek();
				if(token.type == TT_BLOCK_ENTRY || token.type == TT_BLOCK_END)
					continue;
			}
			
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
			pNode->Parse(pScanner, state);
		}
	}

	void Sequence::ParseImplicit(Scanner *pScanner, const ParserState& state)
	{
		while(1) {
			// we're actually *allowed* to have no tokens at some point
			if(pScanner->empty())
				break;

			// and we end at anything other than a block entry
			Token& token = pScanner->peek();
			if(token.type != TT_BLOCK_ENTRY)
				break;

			pScanner->pop();

			Node *pNode = new Node;
			m_data.push_back(pNode);
			pNode->Parse(pScanner, state);
		}
	}

	void Sequence::ParseFlow(Scanner *pScanner, const ParserState& state)
	{
		// eat start token
		pScanner->pop();

		while(1) {
			if(pScanner->empty())
123
				throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW);
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

			// first check for end
			if(pScanner->peek().type == TT_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 == TT_FLOW_ENTRY)
				pScanner->pop();
			else if(token.type != TT_FLOW_SEQ_END)
141
				throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
142
143
144
		}
	}

145
	void Sequence::Write(Emitter& out) const
146
	{
147
		out << BeginSeq;
148
		for(std::size_t i=0;i<m_data.size();i++)
149
150
			out << *m_data[i];
		out << EndSeq;
151
152
153
154
155
156
157
158
159
	}

	int Sequence::Compare(Content *pContent)
	{
		return -pContent->Compare(this);
	}

	int Sequence::Compare(Sequence *pSeq)
	{
160
		std::size_t n = m_data.size(), m = pSeq->m_data.size();
161
162
163
164
165
		if(n < m)
			return -1;
		else if(n > m)
			return 1;

166
		for(std::size_t i=0;i<n;i++) {
167
168
169
170
171
172
173
174
			int cmp = m_data[i]->Compare(*pSeq->m_data[i]);
			if(cmp != 0)
				return cmp;
		}

		return 0;
	}
}