emitterstate.cpp (10054B)
1 #include <limits> 2 3 #include "emitterstate.h" 4 #include "yaml-cpp/exceptions.h" // IWYU pragma: keep 5 6 namespace YAML { 7 EmitterState::EmitterState() 8 : m_isGood(true), 9 m_lastError{}, 10 // default global manipulators 11 m_charset(EmitNonAscii), 12 m_strFmt(Auto), 13 m_boolFmt(TrueFalseBool), 14 m_boolLengthFmt(LongBool), 15 m_boolCaseFmt(LowerCase), 16 m_nullFmt(TildeNull), 17 m_intFmt(Dec), 18 m_indent(2), 19 m_preCommentIndent(2), 20 m_postCommentIndent(1), 21 m_seqFmt(Block), 22 m_mapFmt(Block), 23 m_mapKeyFmt(Auto), 24 m_floatPrecision(std::numeric_limits<float>::max_digits10), 25 m_doublePrecision(std::numeric_limits<double>::max_digits10), 26 // 27 m_modifiedSettings{}, 28 m_globalModifiedSettings{}, 29 m_groups{}, 30 m_curIndent(0), 31 m_hasAnchor(false), 32 m_hasAlias(false), 33 m_hasTag(false), 34 m_hasNonContent(false), 35 m_docCount(0) {} 36 37 EmitterState::~EmitterState() = default; 38 39 // SetLocalValue 40 // . We blindly tries to set all possible formatters to this value 41 // . Only the ones that make sense will be accepted 42 void EmitterState::SetLocalValue(EMITTER_MANIP value) { 43 SetOutputCharset(value, FmtScope::Local); 44 SetStringFormat(value, FmtScope::Local); 45 SetBoolFormat(value, FmtScope::Local); 46 SetBoolCaseFormat(value, FmtScope::Local); 47 SetBoolLengthFormat(value, FmtScope::Local); 48 SetNullFormat(value, FmtScope::Local); 49 SetIntFormat(value, FmtScope::Local); 50 SetFlowType(GroupType::Seq, value, FmtScope::Local); 51 SetFlowType(GroupType::Map, value, FmtScope::Local); 52 SetMapKeyFormat(value, FmtScope::Local); 53 } 54 55 void EmitterState::SetAnchor() { m_hasAnchor = true; } 56 57 void EmitterState::SetAlias() { m_hasAlias = true; } 58 59 void EmitterState::SetTag() { m_hasTag = true; } 60 61 void EmitterState::SetNonContent() { m_hasNonContent = true; } 62 63 void EmitterState::SetLongKey() { 64 assert(!m_groups.empty()); 65 if (m_groups.empty()) { 66 return; 67 } 68 69 assert(m_groups.back()->type == GroupType::Map); 70 m_groups.back()->longKey = true; 71 } 72 73 void EmitterState::ForceFlow() { 74 assert(!m_groups.empty()); 75 if (m_groups.empty()) { 76 return; 77 } 78 79 m_groups.back()->flowType = FlowType::Flow; 80 } 81 82 void EmitterState::StartedNode() { 83 if (m_groups.empty()) { 84 m_docCount++; 85 } else { 86 m_groups.back()->childCount++; 87 if (m_groups.back()->childCount % 2 == 0) { 88 m_groups.back()->longKey = false; 89 } 90 } 91 92 m_hasAnchor = false; 93 m_hasAlias = false; 94 m_hasTag = false; 95 m_hasNonContent = false; 96 } 97 98 EmitterNodeType::value EmitterState::NextGroupType( 99 GroupType::value type) const { 100 if (type == GroupType::Seq) { 101 if (GetFlowType(type) == Block) 102 return EmitterNodeType::BlockSeq; 103 return EmitterNodeType::FlowSeq; 104 } 105 106 if (GetFlowType(type) == Block) 107 return EmitterNodeType::BlockMap; 108 return EmitterNodeType::FlowMap; 109 110 // can't happen 111 assert(false); 112 return EmitterNodeType::NoType; 113 } 114 115 void EmitterState::StartedDoc() { 116 m_hasAnchor = false; 117 m_hasTag = false; 118 m_hasNonContent = false; 119 } 120 121 void EmitterState::EndedDoc() { 122 m_hasAnchor = false; 123 m_hasTag = false; 124 m_hasNonContent = false; 125 } 126 127 void EmitterState::StartedScalar() { 128 StartedNode(); 129 ClearModifiedSettings(); 130 } 131 132 void EmitterState::StartedGroup(GroupType::value type) { 133 StartedNode(); 134 135 const std::size_t lastGroupIndent = 136 (m_groups.empty() ? 0 : m_groups.back()->indent); 137 m_curIndent += lastGroupIndent; 138 139 // TODO: Create move constructors for settings types to simplify transfer 140 std::unique_ptr<Group> pGroup(new Group(type)); 141 142 // transfer settings (which last until this group is done) 143 // 144 // NB: if pGroup->modifiedSettings == m_modifiedSettings, 145 // m_modifiedSettings is not changed! 146 pGroup->modifiedSettings = std::move(m_modifiedSettings); 147 148 // set up group 149 if (GetFlowType(type) == Block) { 150 pGroup->flowType = FlowType::Block; 151 } else { 152 pGroup->flowType = FlowType::Flow; 153 } 154 pGroup->indent = GetIndent(); 155 156 m_groups.push_back(std::move(pGroup)); 157 } 158 159 void EmitterState::EndedGroup(GroupType::value type) { 160 if (m_groups.empty()) { 161 if (type == GroupType::Seq) { 162 return SetError(ErrorMsg::UNEXPECTED_END_SEQ); 163 } 164 return SetError(ErrorMsg::UNEXPECTED_END_MAP); 165 } 166 167 if (m_hasTag) { 168 SetError(ErrorMsg::INVALID_TAG); 169 } 170 if (m_hasAnchor) { 171 SetError(ErrorMsg::INVALID_ANCHOR); 172 } 173 174 // get rid of the current group 175 { 176 std::unique_ptr<Group> pFinishedGroup = std::move(m_groups.back()); 177 m_groups.pop_back(); 178 if (pFinishedGroup->type != type) { 179 return SetError(ErrorMsg::UNMATCHED_GROUP_TAG); 180 } 181 } 182 183 // reset old settings 184 std::size_t lastIndent = (m_groups.empty() ? 0 : m_groups.back()->indent); 185 assert(m_curIndent >= lastIndent); 186 m_curIndent -= lastIndent; 187 188 // some global settings that we changed may have been overridden 189 // by a local setting we just popped, so we need to restore them 190 m_globalModifiedSettings.restore(); 191 192 ClearModifiedSettings(); 193 m_hasAnchor = false; 194 m_hasTag = false; 195 m_hasNonContent = false; 196 } 197 198 EmitterNodeType::value EmitterState::CurGroupNodeType() const { 199 if (m_groups.empty()) { 200 return EmitterNodeType::NoType; 201 } 202 203 return m_groups.back()->NodeType(); 204 } 205 206 GroupType::value EmitterState::CurGroupType() const { 207 return m_groups.empty() ? GroupType::NoType : m_groups.back()->type; 208 } 209 210 FlowType::value EmitterState::CurGroupFlowType() const { 211 return m_groups.empty() ? FlowType::NoType : m_groups.back()->flowType; 212 } 213 214 std::size_t EmitterState::CurGroupIndent() const { 215 return m_groups.empty() ? 0 : m_groups.back()->indent; 216 } 217 218 std::size_t EmitterState::CurGroupChildCount() const { 219 return m_groups.empty() ? m_docCount : m_groups.back()->childCount; 220 } 221 222 bool EmitterState::CurGroupLongKey() const { 223 return m_groups.empty() ? false : m_groups.back()->longKey; 224 } 225 226 std::size_t EmitterState::LastIndent() const { 227 if (m_groups.size() <= 1) { 228 return 0; 229 } 230 231 return m_curIndent - m_groups[m_groups.size() - 2]->indent; 232 } 233 234 void EmitterState::ClearModifiedSettings() { m_modifiedSettings.clear(); } 235 236 void EmitterState::RestoreGlobalModifiedSettings() { 237 m_globalModifiedSettings.restore(); 238 } 239 240 bool EmitterState::SetOutputCharset(EMITTER_MANIP value, 241 FmtScope::value scope) { 242 switch (value) { 243 case EmitNonAscii: 244 case EscapeNonAscii: 245 case EscapeAsJson: 246 _Set(m_charset, value, scope); 247 return true; 248 default: 249 return false; 250 } 251 } 252 253 bool EmitterState::SetStringFormat(EMITTER_MANIP value, FmtScope::value scope) { 254 switch (value) { 255 case Auto: 256 case SingleQuoted: 257 case DoubleQuoted: 258 case Literal: 259 _Set(m_strFmt, value, scope); 260 return true; 261 default: 262 return false; 263 } 264 } 265 266 bool EmitterState::SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope) { 267 switch (value) { 268 case OnOffBool: 269 case TrueFalseBool: 270 case YesNoBool: 271 _Set(m_boolFmt, value, scope); 272 return true; 273 default: 274 return false; 275 } 276 } 277 278 bool EmitterState::SetBoolLengthFormat(EMITTER_MANIP value, 279 FmtScope::value scope) { 280 switch (value) { 281 case LongBool: 282 case ShortBool: 283 _Set(m_boolLengthFmt, value, scope); 284 return true; 285 default: 286 return false; 287 } 288 } 289 290 bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value, 291 FmtScope::value scope) { 292 switch (value) { 293 case UpperCase: 294 case LowerCase: 295 case CamelCase: 296 _Set(m_boolCaseFmt, value, scope); 297 return true; 298 default: 299 return false; 300 } 301 } 302 303 bool EmitterState::SetNullFormat(EMITTER_MANIP value, FmtScope::value scope) { 304 switch (value) { 305 case LowerNull: 306 case UpperNull: 307 case CamelNull: 308 case TildeNull: 309 _Set(m_nullFmt, value, scope); 310 return true; 311 default: 312 return false; 313 } 314 } 315 316 bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope) { 317 switch (value) { 318 case Dec: 319 case Hex: 320 case Oct: 321 _Set(m_intFmt, value, scope); 322 return true; 323 default: 324 return false; 325 } 326 } 327 328 bool EmitterState::SetIndent(std::size_t value, FmtScope::value scope) { 329 if (value <= 1) 330 return false; 331 332 _Set(m_indent, value, scope); 333 return true; 334 } 335 336 bool EmitterState::SetPreCommentIndent(std::size_t value, 337 FmtScope::value scope) { 338 if (value == 0) 339 return false; 340 341 _Set(m_preCommentIndent, value, scope); 342 return true; 343 } 344 345 bool EmitterState::SetPostCommentIndent(std::size_t value, 346 FmtScope::value scope) { 347 if (value == 0) 348 return false; 349 350 _Set(m_postCommentIndent, value, scope); 351 return true; 352 } 353 354 bool EmitterState::SetFlowType(GroupType::value groupType, EMITTER_MANIP value, 355 FmtScope::value scope) { 356 switch (value) { 357 case Block: 358 case Flow: 359 _Set(groupType == GroupType::Seq ? m_seqFmt : m_mapFmt, value, scope); 360 return true; 361 default: 362 return false; 363 } 364 } 365 366 EMITTER_MANIP EmitterState::GetFlowType(GroupType::value groupType) const { 367 // force flow style if we're currently in a flow 368 if (CurGroupFlowType() == FlowType::Flow) 369 return Flow; 370 371 // otherwise, go with what's asked of us 372 return (groupType == GroupType::Seq ? m_seqFmt.get() : m_mapFmt.get()); 373 } 374 375 bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope) { 376 switch (value) { 377 case Auto: 378 case LongKey: 379 _Set(m_mapKeyFmt, value, scope); 380 return true; 381 default: 382 return false; 383 } 384 } 385 386 bool EmitterState::SetFloatPrecision(std::size_t value, FmtScope::value scope) { 387 if (value > std::numeric_limits<float>::max_digits10) 388 return false; 389 _Set(m_floatPrecision, value, scope); 390 return true; 391 } 392 393 bool EmitterState::SetDoublePrecision(std::size_t value, 394 FmtScope::value scope) { 395 if (value > std::numeric_limits<double>::max_digits10) 396 return false; 397 _Set(m_doublePrecision, value, scope); 398 return true; 399 } 400 } // namespace YAML