simplekey.cpp 3.23 KB
Newer Older
1
2
3
4
5
6
7
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include "exp.h"

namespace YAML
{
8
	Scanner::SimpleKey::SimpleKey(const Mark& mark_, int flowLevel_)
9
		: mark(mark_), flowLevel(flowLevel_), pIndent(0), pMapStart(0), pKey(0)
10
11
12
13
14
	{
	}

	void Scanner::SimpleKey::Validate()
	{
15
16
17
		// Note: pIndent will *not* be garbage here;
		//       we "garbage collect" them so we can
		//       always refer to them
18
		if(pIndent)
19
			pIndent->status = IndentMarker::VALID;
20
		if(pMapStart)
jbeder's avatar
jbeder committed
21
			pMapStart->status = Token::VALID;
22
		if(pKey)
jbeder's avatar
jbeder committed
23
			pKey->status = Token::VALID;
24
25
26
27
	}

	void Scanner::SimpleKey::Invalidate()
	{
28
29
		if(pIndent)
			pIndent->status = IndentMarker::INVALID;
30
		if(pMapStart)
jbeder's avatar
jbeder committed
31
			pMapStart->status = Token::INVALID;
32
		if(pKey)
jbeder's avatar
jbeder committed
33
			pKey->status = Token::INVALID;
34
	}
35
36
37
38
39
40
41
42
43
	
	// CanInsertPotentialSimpleKey
	bool Scanner::CanInsertPotentialSimpleKey() const
	{
		if(!m_simpleKeyAllowed)
			return false;

		return !ExistsActiveSimpleKey();
	}
44

45
46
47
48
	// ExistsActiveSimpleKey
	// . Returns true if there's a potential simple key at our flow level
	//   (there's allowed at most one per flow level, i.e., at the start of the flow start token)
	bool Scanner::ExistsActiveSimpleKey() const
49
	{
50
51
52
53
		if(m_simpleKeys.empty())
			return false;
		
		const SimpleKey& key = m_simpleKeys.top();
54
		return key.flowLevel == GetFlowLevel();
55
56
57
58
59
60
61
	}

	// InsertPotentialSimpleKey
	// . If we can, add a potential simple key to the queue,
	//   and save it on a stack.
	void Scanner::InsertPotentialSimpleKey()
	{
62
		if(!CanInsertPotentialSimpleKey())
63
64
			return;
		
65
		SimpleKey key(INPUT.mark(), GetFlowLevel());
66
67

		// first add a map start, if necessary
68
69
70
71
72
73
74
75
76
		if(InBlockContext()) {
			key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
			if(key.pIndent) {
				key.pIndent->status = IndentMarker::UNKNOWN;
				key.pMapStart = key.pIndent->pStartToken;
				key.pMapStart->status = Token::UNVERIFIED;
			}
		} else if(m_flows.top() == FLOW_SEQ) {
			key.pMapStart = PushToken(Token::FLOW_MAP_COMPACT);
jbeder's avatar
jbeder committed
77
			key.pMapStart->status = Token::UNVERIFIED;
78
		}
79
80

		// then add the (now unverified) key
jbeder's avatar
jbeder committed
81
		m_tokens.push(Token(Token::KEY, INPUT.mark()));
82
		key.pKey = &m_tokens.back();
jbeder's avatar
jbeder committed
83
		key.pKey->status = Token::UNVERIFIED;
84
85
86
87

		m_simpleKeys.push(key);
	}

88
89
90
91
92
93
94
95
96
	// InvalidateSimpleKey
	// . Automatically invalidate the simple key in our flow level
	void Scanner::InvalidateSimpleKey()
	{
		if(m_simpleKeys.empty())
			return;
		
		// grab top key
		SimpleKey& key = m_simpleKeys.top();
97
		if(key.flowLevel != GetFlowLevel())
98
99
100
101
102
103
			return;
		
		key.Invalidate();
		m_simpleKeys.pop();
	}

104
105
106
	// VerifySimpleKey
	// . Determines whether the latest simple key to be added is valid,
	//   and if so, makes it valid.
107
	bool Scanner::VerifySimpleKey()
108
109
	{
		if(m_simpleKeys.empty())
110
			return false;
111
112
113
114
115

		// grab top key
		SimpleKey key = m_simpleKeys.top();

		// only validate if we're in the correct flow level
116
		if(key.flowLevel != GetFlowLevel())
117
118
119
120
121
122
			return false;

		m_simpleKeys.pop();

		bool isValid = true;

123
		// needs to be less than 1024 characters and inline
124
		if(INPUT.line() != key.mark.line || INPUT.pos() - key.mark.pos > 1024)
125
126
127
128
129
130
131
132
133
134
135
			isValid = false;

		// invalidate key
		if(isValid)
			key.Validate();
		else
			key.Invalidate();

		return isValid;
	}

136
	void Scanner::PopAllSimpleKeys()
137
138
	{
		while(!m_simpleKeys.empty())
139
			m_simpleKeys.pop();
140
141
	}
}
142