emitterstate.h 6.41 KB
Newer Older
1
2
3
#ifndef EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

4
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
5
6
7
#pragma once
#endif

8

9
#include "ptr_stack.h"
10
#include "setting.h"
11
#include "yaml-cpp/emittermanip.h"
12
13
14
15
16
17
18
#include <cassert>
#include <vector>
#include <stack>
#include <memory>

namespace YAML
{
19
20
21
22
	struct FmtScope { enum value { Local, Global }; };
	struct GroupType { enum value { None, Seq, Map }; };
	struct FlowType { enum value { None, Flow, Block }; };

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
	enum NODE_STATE {
		NS_START,
		NS_READY_FOR_ATOM,
		NS_END
	};
	
	enum EMITTER_STATE {
		ES_WAITING_FOR_DOC,
		ES_WRITING_DOC,
		ES_DONE_WITH_DOC,
		
		// block seq
		ES_WAITING_FOR_BLOCK_SEQ_ENTRY,
		ES_WRITING_BLOCK_SEQ_ENTRY,
		ES_DONE_WITH_BLOCK_SEQ_ENTRY,
		
		// flow seq
		ES_WAITING_FOR_FLOW_SEQ_ENTRY,
		ES_WRITING_FLOW_SEQ_ENTRY,
		ES_DONE_WITH_FLOW_SEQ_ENTRY,
		
		// block map
		ES_WAITING_FOR_BLOCK_MAP_ENTRY,
		ES_WAITING_FOR_BLOCK_MAP_KEY,
		ES_WRITING_BLOCK_MAP_KEY,
		ES_DONE_WITH_BLOCK_MAP_KEY,
		ES_WAITING_FOR_BLOCK_MAP_VALUE,
		ES_WRITING_BLOCK_MAP_VALUE,
		ES_DONE_WITH_BLOCK_MAP_VALUE,
		
		// flow map
		ES_WAITING_FOR_FLOW_MAP_ENTRY,
		ES_WAITING_FOR_FLOW_MAP_KEY,
		ES_WRITING_FLOW_MAP_KEY,
		ES_DONE_WITH_FLOW_MAP_KEY,
		ES_WAITING_FOR_FLOW_MAP_VALUE,
		ES_WRITING_FLOW_MAP_VALUE,
60
		ES_DONE_WITH_FLOW_MAP_VALUE
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
	};
	
	class EmitterState
	{
	public:
		EmitterState();
		~EmitterState();
		
		// basic state checking
		bool good() const { return m_isGood; }
		const std::string GetLastError() const { return m_lastError; }
		void SetError(const std::string& error) { m_isGood = false; m_lastError = error; }
		
		// main state of the machine
		EMITTER_STATE GetCurState() const { return m_stateStack.top(); }
		void SwitchState(EMITTER_STATE state) { PopState(); PushState(state); }
		void PushState(EMITTER_STATE state) { m_stateStack.push(state); }
		void PopState() { m_stateStack.pop(); }
		
		void SetLocalValue(EMITTER_MANIP value);
		
		// group handling
83
84
		void BeginGroup(GroupType::value type);
		void EndGroup(GroupType::value type);
85
		
86
87
		GroupType::value GetCurGroupType() const;
        FlowType::value GetCurGroupFlowType() const;
88
89
90
91
92
93
		int GetCurIndent() const { return m_curIndent; }
		
		bool CurrentlyInLongKey();
		void StartLongKey();
		void StartSimpleKey();

94
95
96
97
98
99
		bool RequiresSoftSeparation() const { return m_requiresSoftSeparation; }
		bool RequiresHardSeparation() const { return m_requiresHardSeparation; }
		void RequireSoftSeparation() { m_requiresSoftSeparation = true; }
		void RequireHardSeparation() { m_requiresSoftSeparation = true; m_requiresHardSeparation = true; }
		void ForceHardSeparation() { m_requiresSoftSeparation = false; }
		void UnsetSeparation() { m_requiresSoftSeparation = false; m_requiresHardSeparation = false; }
100
101
102
103

		void ClearModifiedSettings();

		// formatters
104
		bool SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope);
105
106
		EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); }

107
		bool SetStringFormat(EMITTER_MANIP value, FmtScope::value scope);
108
109
		EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }
		
110
		bool SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope);
111
112
		EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); }

113
		bool SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope);
114
115
		EMITTER_MANIP GetBoolLengthFormat() const { return m_boolLengthFmt.get(); }

116
		bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope);
117
118
		EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }

119
		bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
120
121
		EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }

122
		bool SetIndent(unsigned value, FmtScope::value scope);
123
124
		int GetIndent() const { return m_indent.get(); }
		
125
		bool SetPreCommentIndent(unsigned value, FmtScope::value scope);
126
		int GetPreCommentIndent() const { return m_preCommentIndent.get(); }
127
		bool SetPostCommentIndent(unsigned value, FmtScope::value scope);
128
129
		int GetPostCommentIndent() const { return m_postCommentIndent.get(); }
		
130
131
		bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value, FmtScope::value scope);
		EMITTER_MANIP GetFlowType(GroupType::value groupType) const;
132
		
133
		bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
134
		EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }
135
        
136
        bool SetFloatPrecision(int value, FmtScope::value scope);
137
        unsigned GetFloatPrecision() const { return m_floatPrecision.get(); }
138
        bool SetDoublePrecision(int value, FmtScope::value scope);
139
        unsigned GetDoublePrecision() const { return m_doublePrecision.get(); }
140
141
142
		
	private:
		template <typename T>
143
		void _Set(Setting<T>& fmt, T value, FmtScope::value scope);
144
145
146
147
148
149
150
		
	private:
		// basic state ok?
		bool m_isGood;
		std::string m_lastError;
		
		// other state
151
152
153
154
155
156
157
158
159
160
161
162
163
		std::stack<EMITTER_STATE> m_stateStack;
		
		Setting<EMITTER_MANIP> m_charset;
		Setting<EMITTER_MANIP> m_strFmt;
		Setting<EMITTER_MANIP> m_boolFmt;
		Setting<EMITTER_MANIP> m_boolLengthFmt;
		Setting<EMITTER_MANIP> m_boolCaseFmt;
		Setting<EMITTER_MANIP> m_intFmt;
		Setting<unsigned> m_indent;
		Setting<unsigned> m_preCommentIndent, m_postCommentIndent;
		Setting<EMITTER_MANIP> m_seqFmt;
		Setting<EMITTER_MANIP> m_mapFmt;
		Setting<EMITTER_MANIP> m_mapKeyFmt;
164
165
        Setting<int> m_floatPrecision;
        Setting<int> m_doublePrecision;
166
167
168
169
170
		
		SettingChanges m_modifiedSettings;
		SettingChanges m_globalModifiedSettings;
		
		struct Group {
171
			Group(GroupType::value type_): type(type_), usingLongKey(false), indent(0) {}
172
			
173
            GroupType::value type;
174
175
176
177
178
179
			EMITTER_MANIP flow;
			bool usingLongKey;
			int indent;
			
			SettingChanges modifiedSettings;
		};
180
181

		ptr_stack<Group> m_groups;
182
		unsigned m_curIndent;
183
184
		bool m_requiresSoftSeparation;
		bool m_requiresHardSeparation;
185
186
187
	};

	template <typename T>
188
	void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) {
189
		switch(scope) {
190
			case FmtScope::Local:
191
192
				m_modifiedSettings.push(fmt.set(value));
				break;
193
			case FmtScope::Global:
194
195
196
197
198
199
200
201
202
				fmt.set(value);
				m_globalModifiedSettings.push(fmt.set(value));  // this pushes an identity set, so when we restore,
				                                                // it restores to the value here, and not the previous one
				break;
			default:
				assert(false);
		}
	}
}
203
204

#endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66