map.cpp 5.05 KB
Newer Older
1
2
3
4
5
#include "map.h"
#include "node.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
6
#include "emitter.h"
7
#include <memory>
8
9
10
11
12
13

namespace YAML
{
	Map::Map()
	{
	}
Jesse Beder's avatar
Jesse Beder committed
14
15
16
17
18
19
20
21
22
	
	Map::Map(const node_map& data)
	{
		for(node_map::const_iterator it=data.begin();it!=data.end();++it) {
			std::auto_ptr<Node> pKey = it->first->Clone();
			std::auto_ptr<Node> pValue = it->second->Clone();
			m_data[pKey.release()] = pValue.release();
		}
	}
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

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

	void Map::Clear()
	{
		for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) {
			delete it->first;
			delete it->second;
		}
		m_data.clear();
	}

Jesse Beder's avatar
Jesse Beder committed
38
39
40
41
42
	Content *Map::Clone() const
	{
		return new Map(m_data);
	}
	
43
44
45
46
47
48
49
50
51
52
53
54
	bool Map::GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const
	{
		it = m_data.begin();
		return true;
	}

	bool Map::GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const
	{
		it = m_data.end();
		return true;
	}

55
56
57
58
59
	std::size_t Map::GetSize() const
	{
		return m_data.size();
	}

60
61
62
63
64
65
	void Map::Parse(Scanner *pScanner, const ParserState& state)
	{
		Clear();

		// split based on start token
		switch(pScanner->peek().type) {
66
67
			case Token::BLOCK_MAP_START: ParseBlock(pScanner, state); break;
			case Token::FLOW_MAP_START: ParseFlow(pScanner, state); break;
68
			case Token::KEY: ParseCompact(pScanner, state); break;
69
			case Token::VALUE: ParseCompactWithNoKey(pScanner, state); break;
Jesse Beder's avatar
Jesse Beder committed
70
			default: break;
71
72
73
74
75
76
77
78
79
80
		}
	}

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

		while(1) {
			if(pScanner->empty())
81
				throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
82
83

			Token token = pScanner->peek();
84
			if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
85
				throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
86

87
			if(token.type == Token::BLOCK_MAP_END) {
88
				pScanner->pop();
89
				break;
90
			}
91

92
			std::auto_ptr <Node> pKey(new Node), pValue(new Node);
93
94
			
			// grab key (if non-null)
95
			if(token.type == Token::KEY) {
96
97
98
				pScanner->pop();
				pKey->Parse(pScanner, state);
			}
99

100
			// now grab value (optional)
101
			if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
102
103
				pScanner->pop();
				pValue->Parse(pScanner, state);
104
			}
105
106
107

			// assign the map with the actual pointers
			m_data[pKey.release()] = pValue.release();
108
109
110
111
112
113
114
115
116
117
		}
	}

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

		while(1) {
			if(pScanner->empty())
118
				throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW);
119
120
121

			Token& token = pScanner->peek();
			// first check for end
122
			if(token.type == Token::FLOW_MAP_END) {
123
124
125
				pScanner->pop();
				break;
			}
126
			
127
128
			std::auto_ptr <Node> pKey(new Node), pValue(new Node);

129
130
131
132
133
134
			// grab key (if non-null)
			if(token.type == Token::KEY) {
				pScanner->pop();
				pKey->Parse(pScanner, state);
			}
			
135
			// now grab value (optional)
136
			if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
137
138
				pScanner->pop();
				pValue->Parse(pScanner, state);
139
			}
140
			
141
142
			// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
			Token& nextToken = pScanner->peek();
143
			if(nextToken.type == Token::FLOW_ENTRY)
144
				pScanner->pop();
145
			else if(nextToken.type != Token::FLOW_MAP_END)
146
				throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
147
148
149

			// assign the map with the actual pointers
			m_data[pKey.release()] = pValue.release();
150
151
152
		}
	}

153
	// ParseCompact
154
	// . Single "key: value" pair in a flow sequence
155
156
157
158
	void Map::ParseCompact(Scanner *pScanner, const ParserState& state)
	{
		std::auto_ptr <Node> pKey(new Node), pValue(new Node);

159
160
161
		// grab key
		pScanner->pop();
		pKey->Parse(pScanner, state);
162
163
164
165
166
167
168
169
170
171
172
			
		// now grab value (optional)
		if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
			pScanner->pop();
			pValue->Parse(pScanner, state);
		}
			
		// assign the map with the actual pointers
		m_data[pKey.release()] = pValue.release();
	}
	
173
	// ParseCompactWithNoKey
174
	// . Single ": value" pair in a flow sequence
175
176
177
178
179
180
181
182
183
184
185
186
	void Map::ParseCompactWithNoKey(Scanner *pScanner, const ParserState& state)
	{
		std::auto_ptr <Node> pKey(new Node), pValue(new Node);

		// grab value
		pScanner->pop();
		pValue->Parse(pScanner, state);
			
		// assign the map with the actual pointers
		m_data[pKey.release()] = pValue.release();
	}
	
187
	void Map::Write(Emitter& out) const
188
	{
189
190
191
192
		out << BeginMap;
		for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it)
			out << Key << *it->first << Value << *it->second;
		out << EndMap;
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
	}

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

	int Map::Compare(Map *pMap)
	{
		node_map::const_iterator it = m_data.begin(), jt = pMap->m_data.begin();
		while(1) {
			if(it == m_data.end()) {
				if(jt == pMap->m_data.end())
					return 0;
				else
					return -1;
			}
			if(jt == pMap->m_data.end())
				return 1;

			int cmp = it->first->Compare(*jt->first);
			if(cmp != 0)
				return cmp;

			cmp = it->second->Compare(*jt->second);
			if(cmp != 0)
				return cmp;
		}

		return 0;
	}
}