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

Jesse Beder's avatar
Jesse Beder committed
4
5
6
#if defined(_MSC_VER) ||                                            \
    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
7
8
9
#pragma once
#endif

10
#include "setting.h"
11
#include "yaml-cpp/emitterdef.h"
12
#include "yaml-cpp/emittermanip.h"
13

14
15
#include <cassert>
#include <memory>
16
#include <stack>
Jesse Beder's avatar
Jesse Beder committed
17
#include <stdexcept>
18
#include <vector>
19

Jesse Beder's avatar
Jesse Beder committed
20
21
namespace YAML {
struct FmtScope {
Jesse Beder's avatar
Jesse Beder committed
22
  enum value { Local, Global };
Jesse Beder's avatar
Jesse Beder committed
23
24
};
struct GroupType {
25
  enum value { NoType, Seq, Map };
Jesse Beder's avatar
Jesse Beder committed
26
27
};
struct FlowType {
28
  enum value { NoType, Flow, Block };
Jesse Beder's avatar
Jesse Beder committed
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
60
};

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

  // node handling
  void SetAnchor();
  void SetTag();
  void SetNonContent();
  void SetLongKey();
  void ForceFlow();
  void StartedDoc();
  void EndedDoc();
  void StartedScalar();
  void StartedGroup(GroupType::value type);
  void EndedGroup(GroupType::value type);

  EmitterNodeType::value NextGroupType(GroupType::value type) const;
  EmitterNodeType::value CurGroupNodeType() const;

  GroupType::value CurGroupType() const;
  FlowType::value CurGroupFlowType() const;
61
  std::size_t CurGroupIndent() const;
Jesse Beder's avatar
Jesse Beder committed
62
63
64
  std::size_t CurGroupChildCount() const;
  bool CurGroupLongKey() const;

65
66
  std::size_t LastIndent() const;
  std::size_t CurIndent() const { return m_curIndent; }
Jesse Beder's avatar
Jesse Beder committed
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
  bool HasAnchor() const { return m_hasAnchor; }
  bool HasTag() const { return m_hasTag; }
  bool HasBegunNode() const {
    return m_hasAnchor || m_hasTag || m_hasNonContent;
  }
  bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }

  void ClearModifiedSettings();

  // formatters
  void SetLocalValue(EMITTER_MANIP value);

  bool SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope);
  EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); }

  bool SetStringFormat(EMITTER_MANIP value, FmtScope::value scope);
  EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }

  bool SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope);
  EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); }

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

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

94
95
96
  bool SetNullFormat(EMITTER_MANIP value, FmtScope::value scope);
  EMITTER_MANIP GetNullFormat() const { return m_nullFmt.get(); }

Jesse Beder's avatar
Jesse Beder committed
97
98
99
  bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
  EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }

100
  bool SetIndent(std::size_t value, FmtScope::value scope);
101
  std::size_t GetIndent() const { return m_indent.get(); }
Jesse Beder's avatar
Jesse Beder committed
102

103
  bool SetPreCommentIndent(std::size_t value, FmtScope::value scope);
104
  std::size_t GetPreCommentIndent() const { return m_preCommentIndent.get(); }
105
  bool SetPostCommentIndent(std::size_t value, FmtScope::value scope);
106
  std::size_t GetPostCommentIndent() const { return m_postCommentIndent.get(); }
Jesse Beder's avatar
Jesse Beder committed
107
108
109
110
111
112
113
114

  bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
                   FmtScope::value scope);
  EMITTER_MANIP GetFlowType(GroupType::value groupType) const;

  bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
  EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }

115
  bool SetFloatPrecision(std::size_t value, FmtScope::value scope);
116
  std::size_t GetFloatPrecision() const { return m_floatPrecision.get(); }
117
  bool SetDoublePrecision(std::size_t value, FmtScope::value scope);
118
  std::size_t GetDoublePrecision() const { return m_doublePrecision.get(); }
Jesse Beder's avatar
Jesse Beder committed
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

 private:
  template <typename T>
  void _Set(Setting<T>& fmt, T value, FmtScope::value scope);

  void StartedNode();

 private:
  // basic state ok?
  bool m_isGood;
  std::string m_lastError;

  // other state
  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;
137
  Setting<EMITTER_MANIP> m_nullFmt;
Jesse Beder's avatar
Jesse Beder committed
138
  Setting<EMITTER_MANIP> m_intFmt;
139
140
  Setting<std::size_t> m_indent;
  Setting<std::size_t> m_preCommentIndent, m_postCommentIndent;
Jesse Beder's avatar
Jesse Beder committed
141
142
143
  Setting<EMITTER_MANIP> m_seqFmt;
  Setting<EMITTER_MANIP> m_mapFmt;
  Setting<EMITTER_MANIP> m_mapKeyFmt;
144
145
  Setting<std::size_t> m_floatPrecision;
  Setting<std::size_t> m_doublePrecision;
Jesse Beder's avatar
Jesse Beder committed
146
147
148
149
150
151

  SettingChanges m_modifiedSettings;
  SettingChanges m_globalModifiedSettings;

  struct Group {
    explicit Group(GroupType::value type_)
152
153
154
155
156
157
        : type(type_),
          flowType{},
          indent(0),
          childCount(0),
          longKey(false),
          modifiedSettings{} {}
Jesse Beder's avatar
Jesse Beder committed
158
159
160

    GroupType::value type;
    FlowType::value flowType;
161
    std::size_t indent;
Jesse Beder's avatar
Jesse Beder committed
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
    std::size_t childCount;
    bool longKey;

    SettingChanges modifiedSettings;

    EmitterNodeType::value NodeType() const {
      if (type == GroupType::Seq) {
        if (flowType == FlowType::Flow)
          return EmitterNodeType::FlowSeq;
        else
          return EmitterNodeType::BlockSeq;
      } else {
        if (flowType == FlowType::Flow)
          return EmitterNodeType::FlowMap;
        else
          return EmitterNodeType::BlockMap;
      }

      // can't get here
      assert(false);
182
      return EmitterNodeType::NoType;
Jesse Beder's avatar
Jesse Beder committed
183
184
185
    }
  };

186
  std::vector<std::unique_ptr<Group>> m_groups;
187
  std::size_t m_curIndent;
Jesse Beder's avatar
Jesse Beder committed
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
  bool m_hasAnchor;
  bool m_hasTag;
  bool m_hasNonContent;
  std::size_t m_docCount;
};

template <typename T>
void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) {
  switch (scope) {
    case FmtScope::Local:
      m_modifiedSettings.push(fmt.set(value));
      break;
    case FmtScope::Global:
      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);
  }
}
210
}  // namespace YAML
211

Jesse Beder's avatar
Jesse Beder committed
212
#endif  // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66