"vscode:/vscode.git/clone" did not exist on "3ca84d920f2c51bcb7d94885e5dde1c662df6802"
map.cpp 4.01 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
56
57
58
59
60
61
62
63
	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;
	}

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

		// split based on start token
		switch(pScanner->peek().type) {
			case TT_BLOCK_MAP_START: ParseBlock(pScanner, state); break;
			case TT_FLOW_MAP_START: ParseFlow(pScanner, state); break;
Jesse Beder's avatar
Jesse Beder committed
64
			default: break;
65
66
67
68
69
70
71
72
73
74
		}
	}

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

		while(1) {
			if(pScanner->empty())
75
				throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
76
77

			Token token = pScanner->peek();
78
			if(token.type != TT_KEY && token.type != TT_VALUE && token.type != TT_BLOCK_MAP_END)
79
				throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
80

81
			if(token.type == TT_BLOCK_MAP_END) {
82
				pScanner->pop();
83
				break;
84
			}
85

86
			std::auto_ptr <Node> pKey(new Node), pValue(new Node);
87
88
89
90
91
92
			
			// grab key (if non-null)
			if(token.type == TT_KEY) {
				pScanner->pop();
				pKey->Parse(pScanner, state);
			}
93

94
95
96
97
			// now grab value (optional)
			if(!pScanner->empty() && pScanner->peek().type == TT_VALUE) {
				pScanner->pop();
				pValue->Parse(pScanner, state);
98
			}
99
100
101

			// assign the map with the actual pointers
			m_data[pKey.release()] = pValue.release();
102
103
104
105
106
107
108
109
110
111
		}
	}

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

		while(1) {
			if(pScanner->empty())
112
				throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW);
113
114
115
116
117
118
119
120
121
122

			Token& token = pScanner->peek();
			// first check for end
			if(token.type == TT_FLOW_MAP_END) {
				pScanner->pop();
				break;
			}

			// now it better be a key
			if(token.type != TT_KEY)
123
				throw ParserException(token.mark, ErrorMsg::END_OF_MAP_FLOW);
124
125
126

			pScanner->pop();

127
128
129
130
131
132
133
134
135
			std::auto_ptr <Node> pKey(new Node), pValue(new Node);

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

			// now grab value (optional)
			if(!pScanner->empty() && pScanner->peek().type == TT_VALUE) {
				pScanner->pop();
				pValue->Parse(pScanner, state);
136
			}
137
138
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();
			if(nextToken.type == TT_FLOW_ENTRY)
				pScanner->pop();
			else if(nextToken.type != TT_FLOW_MAP_END)
143
				throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
144
145
146

			// assign the map with the actual pointers
			m_data[pKey.release()] = pValue.release();
147
148
149
		}
	}

150
	void Map::Write(Emitter& out) const
151
	{
152
153
154
155
		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;
156
157
158
159
160
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
	}

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