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

namespace YAML
{
	Map::Map()
	{
	}
Jesse Beder's avatar
Jesse Beder committed
15
16
17
18
19
20
21
22
23
	
	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();
		}
	}
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

	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
39
40
41
42
43
	Content *Map::Clone() const
	{
		return new Map(m_data);
	}
	
44
45
46
47
48
49
50
51
52
53
54
55
	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;
	}

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

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

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

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

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

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

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

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

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

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

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

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

			Token& token = pScanner->peek();
			// first check for end
121
			if(token.type == Token::FLOW_MAP_END) {
122
123
124
125
126
				pScanner->pop();
				break;
			}

			// now it better be a key
127
			if(token.type != Token::KEY)
128
				throw ParserException(token.mark, ErrorMsg::END_OF_MAP_FLOW);
129
130
131

			pScanner->pop();

132
133
134
135
136
137
			std::auto_ptr <Node> pKey(new Node), pValue(new Node);

			// grab key
			pKey->Parse(pScanner, state);

			// now grab value (optional)
138
			if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
139
140
				pScanner->pop();
				pValue->Parse(pScanner, state);
141
			}
142
143
144

			// 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();
145
			if(nextToken.type == Token::FLOW_ENTRY)
146
				pScanner->pop();
147
			else if(nextToken.type != Token::FLOW_MAP_END)
148
				throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
149
150
151

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

155
	void Map::Write(Emitter& out) const
156
	{
157
158
159
160
		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;
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
	}

	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;
	}
}