yaml-cpp

FORK: A YAML parser and emitter in C++
git clone https://git.neptards.moe/neptards/yaml-cpp.git
Log | Files | Refs | README | LICENSE

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