emitter.cpp
Go to the documentation of this file.
00001 #include "yaml-cpp-pm/emitter.h"
00002 #include "emitterstate.h"
00003 #include "emitterutils.h"
00004 #include "indentation.h"
00005 #include "yaml-cpp-pm/exceptions.h"
00006 #include <sstream>
00007 
00008 namespace YAML_PM
00009 {       
00010         Emitter::Emitter(): m_pState(new EmitterState)
00011         {
00012         }
00013         
00014         Emitter::~Emitter()
00015         {
00016         }
00017         
00018         const char *Emitter::c_str() const
00019         {
00020                 return m_stream.str();
00021         }
00022         
00023         unsigned Emitter::size() const
00024         {
00025                 return m_stream.pos();
00026         }
00027         
00028         // state checking
00029         bool Emitter::good() const
00030         {
00031                 return m_pState->good();
00032         }
00033         
00034         const std::string Emitter::GetLastError() const
00035         {
00036                 return m_pState->GetLastError();
00037         }
00038 
00039         // global setters
00040         bool Emitter::SetOutputCharset(EMITTER_MANIP value)
00041         {
00042                 return m_pState->SetOutputCharset(value, GLOBAL);
00043         }
00044 
00045         bool Emitter::SetStringFormat(EMITTER_MANIP value)
00046         {
00047                 return m_pState->SetStringFormat(value, GLOBAL);
00048         }
00049         
00050         bool Emitter::SetBoolFormat(EMITTER_MANIP value)
00051         {
00052                 bool ok = false;
00053                 if(m_pState->SetBoolFormat(value, GLOBAL))
00054                         ok = true;
00055                 if(m_pState->SetBoolCaseFormat(value, GLOBAL))
00056                         ok = true;
00057                 if(m_pState->SetBoolLengthFormat(value, GLOBAL))
00058                         ok = true;
00059                 return ok;
00060         }
00061         
00062         bool Emitter::SetIntBase(EMITTER_MANIP value)
00063         {
00064                 return m_pState->SetIntFormat(value, GLOBAL);
00065         }
00066         
00067         bool Emitter::SetSeqFormat(EMITTER_MANIP value)
00068         {
00069                 return m_pState->SetFlowType(GT_SEQ, value, GLOBAL);
00070         }
00071         
00072         bool Emitter::SetMapFormat(EMITTER_MANIP value)
00073         {
00074                 bool ok = false;
00075                 if(m_pState->SetFlowType(GT_MAP, value, GLOBAL))
00076                         ok = true;
00077                 if(m_pState->SetMapKeyFormat(value, GLOBAL))
00078                         ok = true;
00079                 return ok;
00080         }
00081         
00082         bool Emitter::SetIndent(unsigned n)
00083         {
00084                 return m_pState->SetIndent(n, GLOBAL);
00085         }
00086         
00087         bool Emitter::SetPreCommentIndent(unsigned n)
00088         {
00089                 return m_pState->SetPreCommentIndent(n, GLOBAL);
00090         }
00091         
00092         bool Emitter::SetPostCommentIndent(unsigned n)
00093         {
00094                 return m_pState->SetPostCommentIndent(n, GLOBAL);
00095         }
00096     
00097     bool Emitter::SetFloatPrecision(unsigned n)
00098     {
00099         return m_pState->SetFloatPrecision(n, GLOBAL);
00100     }
00101 
00102     bool Emitter::SetDoublePrecision(unsigned n)
00103     {
00104         return m_pState->SetDoublePrecision(n, GLOBAL);
00105     }
00106 
00107         // SetLocalValue
00108         // . Either start/end a group, or set a modifier locally
00109         Emitter& Emitter::SetLocalValue(EMITTER_MANIP value)
00110         {
00111                 if(!good())
00112                         return *this;
00113                 
00114                 switch(value) {
00115                         case BeginDoc:
00116                                 EmitBeginDoc();
00117                                 break;
00118                         case EndDoc:
00119                                 EmitEndDoc();
00120                                 break;
00121                         case BeginSeq:
00122                                 EmitBeginSeq();
00123                                 break;
00124                         case EndSeq:
00125                                 EmitEndSeq();
00126                                 break;
00127                         case BeginMap:
00128                                 EmitBeginMap();
00129                                 break;
00130                         case EndMap:
00131                                 EmitEndMap();
00132                                 break;
00133                         case Key:
00134                                 EmitKey();
00135                                 break;
00136                         case Value:
00137                                 EmitValue();
00138                                 break;
00139                         case TagByKind:
00140                                 EmitKindTag();
00141                                 break;
00142                         case Newline:
00143                                 EmitNewline();
00144                                 break;
00145                         default:
00146                                 m_pState->SetLocalValue(value);
00147                                 break;
00148                 }
00149                 return *this;
00150         }
00151         
00152         Emitter& Emitter::SetLocalIndent(const _Indent& indent)
00153         {
00154                 m_pState->SetIndent(indent.value, LOCAL);
00155                 return *this;
00156         }
00157 
00158     Emitter& Emitter::SetLocalPrecision(const _Precision& precision)
00159     {
00160         if(precision.floatPrecision >= 0)
00161             m_pState->SetFloatPrecision(precision.floatPrecision, LOCAL);
00162         if(precision.doublePrecision >= 0)
00163             m_pState->SetDoublePrecision(precision.doublePrecision, LOCAL);
00164         return *this;
00165     }
00166 
00167         // GotoNextPreAtomicState
00168         // . Runs the state machine, emitting if necessary, and returns 'true' if done (i.e., ready to emit an atom)
00169         bool Emitter::GotoNextPreAtomicState()
00170         {
00171                 if(!good())
00172                         return true;
00173                 
00174                 unsigned curIndent = m_pState->GetCurIndent();
00175                 
00176                 EMITTER_STATE curState = m_pState->GetCurState();
00177                 switch(curState) {
00178                                 // document-level
00179                         case ES_WAITING_FOR_DOC:
00180                                 m_pState->SwitchState(ES_WRITING_DOC);
00181                                 return true;
00182                         case ES_WRITING_DOC:
00183                                 return true;
00184                         case ES_DONE_WITH_DOC:
00185                                 EmitBeginDoc();
00186                                 return false;
00187                                 
00188                                 // block sequence
00189                         case ES_WAITING_FOR_BLOCK_SEQ_ENTRY:
00190                                 m_stream << IndentTo(curIndent) << "-";
00191                                 m_pState->RequireSoftSeparation();
00192                                 m_pState->SwitchState(ES_WRITING_BLOCK_SEQ_ENTRY);
00193                                 return true;
00194                         case ES_WRITING_BLOCK_SEQ_ENTRY:
00195                                 return true;
00196                         case ES_DONE_WITH_BLOCK_SEQ_ENTRY:
00197                                 m_stream << '\n';
00198                                 m_pState->SwitchState(ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
00199                                 return false;
00200                                 
00201                                 // flow sequence
00202                         case ES_WAITING_FOR_FLOW_SEQ_ENTRY:
00203                                 m_pState->SwitchState(ES_WRITING_FLOW_SEQ_ENTRY);
00204                                 return true;
00205                         case ES_WRITING_FLOW_SEQ_ENTRY:
00206                                 return true;
00207                         case ES_DONE_WITH_FLOW_SEQ_ENTRY:
00208                                 EmitSeparationIfNecessary();
00209                                 m_stream << ',';
00210                                 m_pState->RequireSoftSeparation();
00211                                 m_pState->SwitchState(ES_WAITING_FOR_FLOW_SEQ_ENTRY);
00212                                 return false;
00213                                 
00214                                 // block map
00215                         case ES_WAITING_FOR_BLOCK_MAP_ENTRY:
00216                                 m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
00217                                 return true;
00218                         case ES_WAITING_FOR_BLOCK_MAP_KEY:
00219                                 if(m_pState->CurrentlyInLongKey()) {
00220                                         m_stream << IndentTo(curIndent) << '?';
00221                                         m_pState->RequireSoftSeparation();
00222                                 }
00223                                 m_pState->SwitchState(ES_WRITING_BLOCK_MAP_KEY);
00224                                 return true;
00225                         case ES_WRITING_BLOCK_MAP_KEY:
00226                                 return true;
00227                         case ES_DONE_WITH_BLOCK_MAP_KEY:
00228                                 m_pState->SetError(ErrorMsg::EXPECTED_VALUE_TOKEN);
00229                                 return true;
00230                         case ES_WAITING_FOR_BLOCK_MAP_VALUE:
00231                                 m_pState->SwitchState(ES_WRITING_BLOCK_MAP_VALUE);
00232                                 return true;
00233                         case ES_WRITING_BLOCK_MAP_VALUE:
00234                                 return true;
00235                         case ES_DONE_WITH_BLOCK_MAP_VALUE:
00236                                 m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
00237                                 return true;
00238                                 
00239                                 // flow map
00240                         case ES_WAITING_FOR_FLOW_MAP_ENTRY:
00241                                 m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
00242                                 return true;
00243                         case ES_WAITING_FOR_FLOW_MAP_KEY:
00244                                 EmitSeparationIfNecessary();
00245                                 m_pState->SwitchState(ES_WRITING_FLOW_MAP_KEY);
00246                                 if(m_pState->CurrentlyInLongKey()) {
00247                                         m_stream << '?';
00248                                         m_pState->RequireSoftSeparation();
00249                                 }
00250                                 return true;
00251                         case ES_WRITING_FLOW_MAP_KEY:
00252                                 return true;
00253                         case ES_DONE_WITH_FLOW_MAP_KEY:
00254                                 m_pState->SetError(ErrorMsg::EXPECTED_VALUE_TOKEN);
00255                                 return true;
00256                         case ES_WAITING_FOR_FLOW_MAP_VALUE:
00257                                 EmitSeparationIfNecessary();
00258                                 m_stream << ':';
00259                                 m_pState->RequireSoftSeparation();
00260                                 m_pState->SwitchState(ES_WRITING_FLOW_MAP_VALUE);
00261                                 return true;
00262                         case ES_WRITING_FLOW_MAP_VALUE:
00263                                 return true;
00264                         case ES_DONE_WITH_FLOW_MAP_VALUE:
00265                                 m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
00266                                 return true;
00267                         default:
00268                                 assert(false);
00269                 }
00270 
00271                 assert(false);
00272                 return true;
00273         }
00274         
00275         // PreAtomicWrite
00276         // . Depending on the emitter state, write to the stream to get it
00277         //   in position to do an atomic write (e.g., scalar, sequence, or map)
00278         void Emitter::PreAtomicWrite()
00279         {
00280                 if(!good())
00281                         return;
00282                 
00283                 while(!GotoNextPreAtomicState())
00284                         ;
00285         }
00286         
00287         // PostAtomicWrite
00288         // . Clean up
00289         void Emitter::PostAtomicWrite()
00290         {
00291                 if(!good())
00292                         return;
00293                 
00294                 EMITTER_STATE curState = m_pState->GetCurState();
00295                 switch(curState) {
00296                                 // document-level
00297                         case ES_WRITING_DOC:
00298                                 m_pState->SwitchState(ES_DONE_WITH_DOC);
00299                                 break;
00300 
00301                                 // block seq
00302                         case ES_WRITING_BLOCK_SEQ_ENTRY:
00303                                 m_pState->SwitchState(ES_DONE_WITH_BLOCK_SEQ_ENTRY);
00304                                 break;
00305                                 
00306                                 // flow seq
00307                         case ES_WRITING_FLOW_SEQ_ENTRY:
00308                                 m_pState->SwitchState(ES_DONE_WITH_FLOW_SEQ_ENTRY);
00309                                 break;
00310                                 
00311                                 // block map
00312                         case ES_WRITING_BLOCK_MAP_KEY:
00313                                 if(!m_pState->CurrentlyInLongKey()) {
00314                                         m_stream << ':';
00315                                         m_pState->RequireSoftSeparation();
00316                                 }
00317                                 m_pState->SwitchState(ES_DONE_WITH_BLOCK_MAP_KEY);
00318                                 break;
00319                         case ES_WRITING_BLOCK_MAP_VALUE:
00320                                 m_pState->SwitchState(ES_DONE_WITH_BLOCK_MAP_VALUE);
00321                                 break;
00322                                 
00323                                 // flow map
00324                         case ES_WRITING_FLOW_MAP_KEY:
00325                                 m_pState->SwitchState(ES_DONE_WITH_FLOW_MAP_KEY);
00326                                 break;
00327                         case ES_WRITING_FLOW_MAP_VALUE:
00328                                 m_pState->SwitchState(ES_DONE_WITH_FLOW_MAP_VALUE);
00329                                 break;
00330                         default:
00331                                 assert(false);
00332                 };
00333                                 
00334                 m_pState->ClearModifiedSettings();
00335         }
00336         
00337         // EmitSeparationIfNecessary
00338         void Emitter::EmitSeparationIfNecessary()
00339         {
00340                 if(!good())
00341                         return;
00342                 
00343                 if(m_pState->RequiresSoftSeparation())
00344                         m_stream << ' ';
00345                 else if(m_pState->RequiresHardSeparation())
00346                         m_stream << '\n';
00347                 m_pState->UnsetSeparation();
00348         }
00349         
00350         // EmitBeginDoc
00351         void Emitter::EmitBeginDoc()
00352         {
00353                 if(!good())
00354                         return;
00355                 
00356                 EMITTER_STATE curState = m_pState->GetCurState();
00357                 if(curState != ES_WAITING_FOR_DOC && curState != ES_WRITING_DOC && curState != ES_DONE_WITH_DOC) {
00358                         m_pState->SetError("Unexpected begin document");
00359                         return;
00360                 }
00361                 
00362                 if(curState == ES_WRITING_DOC || curState == ES_DONE_WITH_DOC)
00363                         m_stream << '\n';               
00364                 m_stream << "---\n";
00365 
00366                 m_pState->UnsetSeparation();
00367                 m_pState->SwitchState(ES_WAITING_FOR_DOC);
00368         }
00369         
00370         // EmitEndDoc
00371         void Emitter::EmitEndDoc()
00372         {
00373                 if(!good())
00374                         return;
00375 
00376                 
00377                 EMITTER_STATE curState = m_pState->GetCurState();
00378                 if(curState != ES_WAITING_FOR_DOC && curState != ES_WRITING_DOC && curState != ES_DONE_WITH_DOC) {
00379                         m_pState->SetError("Unexpected end document");
00380                         return;
00381                 }
00382                 
00383                 if(curState == ES_WRITING_DOC || curState == ES_DONE_WITH_DOC)
00384                         m_stream << '\n';               
00385                 m_stream << "...\n";
00386                 
00387                 m_pState->UnsetSeparation();
00388                 m_pState->SwitchState(ES_WAITING_FOR_DOC);
00389         }
00390 
00391         // EmitBeginSeq
00392         void Emitter::EmitBeginSeq()
00393         {
00394                 if(!good())
00395                         return;
00396                 
00397                 // must have a long key if we're emitting a sequence
00398                 m_pState->StartLongKey();
00399                 
00400                 PreAtomicWrite();
00401                 
00402                 EMITTER_STATE curState = m_pState->GetCurState();
00403                 EMITTER_MANIP flowType = m_pState->GetFlowType(GT_SEQ);
00404                 if(flowType == Block) {
00405                         if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
00406                            curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
00407                            curState == ES_WRITING_DOC
00408                         ) {
00409                                 if(m_pState->RequiresHardSeparation() || curState != ES_WRITING_DOC) {
00410                                         m_stream << "\n";
00411                                         m_pState->UnsetSeparation();
00412                                 }
00413                         }
00414                         m_pState->PushState(ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
00415                 } else if(flowType == Flow) {
00416                         EmitSeparationIfNecessary();
00417                         m_stream << "[";
00418                         m_pState->PushState(ES_WAITING_FOR_FLOW_SEQ_ENTRY);
00419                 } else
00420                         assert(false);
00421 
00422                 m_pState->BeginGroup(GT_SEQ);
00423         }
00424         
00425         // EmitEndSeq
00426         void Emitter::EmitEndSeq()
00427         {
00428                 if(!good())
00429                         return;
00430                 
00431                 if(m_pState->GetCurGroupType() != GT_SEQ)
00432                         return m_pState->SetError(ErrorMsg::UNEXPECTED_END_SEQ);
00433                 
00434                 EMITTER_STATE curState = m_pState->GetCurState();
00435                 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
00436                 if(flowType == FT_BLOCK) {
00437                         // Note: block sequences are *not* allowed to be empty, but we convert it
00438                         //       to a flow sequence if it is
00439                         assert(curState == ES_DONE_WITH_BLOCK_SEQ_ENTRY || curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
00440                         if(curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY) {
00441                                 // Note: only one of these will actually output anything for a given situation
00442                                 EmitSeparationIfNecessary();
00443                                 unsigned curIndent = m_pState->GetCurIndent();
00444                                 m_stream << IndentTo(curIndent);
00445 
00446                                 m_stream << "[]";
00447                         }
00448                 } else if(flowType == FT_FLOW) {
00449                         // Note: flow sequences are allowed to be empty
00450                         assert(curState == ES_DONE_WITH_FLOW_SEQ_ENTRY || curState == ES_WAITING_FOR_FLOW_SEQ_ENTRY);
00451                         m_stream << "]";
00452                 } else
00453                         assert(false);
00454                 
00455                 m_pState->PopState();
00456                 m_pState->EndGroup(GT_SEQ);
00457 
00458                 PostAtomicWrite();
00459         }
00460         
00461         // EmitBeginMap
00462         void Emitter::EmitBeginMap()
00463         {
00464                 if(!good())
00465                         return;
00466                 
00467                 // must have a long key if we're emitting a map
00468                 m_pState->StartLongKey();
00469 
00470                 PreAtomicWrite();
00471 
00472                 EMITTER_STATE curState = m_pState->GetCurState();
00473                 EMITTER_MANIP flowType = m_pState->GetFlowType(GT_MAP);
00474                 if(flowType == Block) {
00475                         if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
00476                            curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
00477                            curState == ES_WRITING_DOC
00478                         ) {
00479                                 if(m_pState->RequiresHardSeparation() || (curState != ES_WRITING_DOC && curState != ES_WRITING_BLOCK_SEQ_ENTRY)) {
00480                                         m_stream << "\n";
00481                                         m_pState->UnsetSeparation();
00482                                 }
00483                         }
00484                         m_pState->PushState(ES_WAITING_FOR_BLOCK_MAP_ENTRY);
00485                 } else if(flowType == Flow) {
00486                         EmitSeparationIfNecessary();
00487                         m_stream << "{";
00488                         m_pState->PushState(ES_WAITING_FOR_FLOW_MAP_ENTRY);
00489                 } else
00490                         assert(false);
00491                 
00492                 m_pState->BeginGroup(GT_MAP);
00493         }
00494         
00495         // EmitEndMap
00496         void Emitter::EmitEndMap()
00497         {
00498                 if(!good())
00499                         return;
00500                 
00501                 if(m_pState->GetCurGroupType() != GT_MAP)
00502                         return m_pState->SetError(ErrorMsg::UNEXPECTED_END_MAP);
00503 
00504                 EMITTER_STATE curState = m_pState->GetCurState();
00505                 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
00506                 if(flowType == FT_BLOCK) {
00507                         // Note: block sequences are *not* allowed to be empty, but we convert it
00508                         //       to a flow sequence if it is
00509                         assert(curState == ES_DONE_WITH_BLOCK_MAP_VALUE || curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY);
00510                         if(curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY) {
00511                                 // Note: only one of these will actually output anything for a given situation
00512                                 EmitSeparationIfNecessary();
00513                                 unsigned curIndent = m_pState->GetCurIndent();
00514                                 m_stream << IndentTo(curIndent);
00515                                 m_stream << "{}";
00516                         }
00517                 } else if(flowType == FT_FLOW) {
00518                         // Note: flow maps are allowed to be empty
00519                         assert(curState == ES_DONE_WITH_FLOW_MAP_VALUE || curState == ES_WAITING_FOR_FLOW_MAP_ENTRY);
00520                         EmitSeparationIfNecessary();
00521                         m_stream << "}";
00522                 } else
00523                         assert(false);
00524                 
00525                 m_pState->PopState();
00526                 m_pState->EndGroup(GT_MAP);
00527                 
00528                 PostAtomicWrite();
00529         }
00530         
00531         // EmitKey
00532         void Emitter::EmitKey()
00533         {
00534                 if(!good())
00535                         return;
00536                 
00537                 EMITTER_STATE curState = m_pState->GetCurState();
00538                 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
00539                 if(curState != ES_WAITING_FOR_BLOCK_MAP_ENTRY && curState != ES_DONE_WITH_BLOCK_MAP_VALUE
00540                    && curState != ES_WAITING_FOR_FLOW_MAP_ENTRY && curState != ES_DONE_WITH_FLOW_MAP_VALUE)
00541                         return m_pState->SetError(ErrorMsg::UNEXPECTED_KEY_TOKEN);
00542 
00543                 if(flowType == FT_BLOCK) {
00544                         if(curState == ES_DONE_WITH_BLOCK_MAP_VALUE)
00545                                 m_stream << '\n';
00546                         unsigned curIndent = m_pState->GetCurIndent();
00547                         m_stream << IndentTo(curIndent);
00548                         m_pState->UnsetSeparation();
00549                         m_pState->SwitchState(ES_WAITING_FOR_BLOCK_MAP_KEY);
00550                 } else if(flowType == FT_FLOW) {
00551                         EmitSeparationIfNecessary();
00552                         if(curState == ES_DONE_WITH_FLOW_MAP_VALUE) {
00553                                 m_stream << ',';
00554                                 m_pState->RequireSoftSeparation();
00555                         }
00556                         m_pState->SwitchState(ES_WAITING_FOR_FLOW_MAP_KEY);
00557                 } else
00558                         assert(false);
00559                 
00560                 if(m_pState->GetMapKeyFormat() == LongKey)
00561                         m_pState->StartLongKey();
00562                 else if(m_pState->GetMapKeyFormat() == Auto)
00563                         m_pState->StartSimpleKey();
00564                 else
00565                         assert(false);
00566         }
00567         
00568         // EmitValue
00569         void Emitter::EmitValue()
00570         {
00571                 if(!good())
00572                         return;
00573 
00574                 EMITTER_STATE curState = m_pState->GetCurState();
00575                 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
00576                 if(curState != ES_DONE_WITH_BLOCK_MAP_KEY && curState != ES_DONE_WITH_FLOW_MAP_KEY)
00577                         return m_pState->SetError(ErrorMsg::UNEXPECTED_VALUE_TOKEN);
00578 
00579                 if(flowType == FT_BLOCK) {
00580                         if(m_pState->CurrentlyInLongKey()) {
00581                                 m_stream << '\n';
00582                                 m_stream << IndentTo(m_pState->GetCurIndent());
00583                                 m_stream << ':';
00584                                 m_pState->RequireSoftSeparation();
00585                         }
00586                         m_pState->SwitchState(ES_WAITING_FOR_BLOCK_MAP_VALUE);
00587                 } else if(flowType == FT_FLOW) {
00588                         m_pState->SwitchState(ES_WAITING_FOR_FLOW_MAP_VALUE);
00589                 } else
00590                         assert(false);
00591         }
00592 
00593         // EmitNewline
00594         void Emitter::EmitNewline()
00595         {
00596                 if(!good())
00597                         return;
00598 
00599                 if(CanEmitNewline()) {
00600                         m_stream << '\n';
00601                         m_pState->UnsetSeparation();
00602                 }
00603         }
00604 
00605         bool Emitter::CanEmitNewline() const
00606         {
00607                 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
00608                 if(flowType == FT_BLOCK && m_pState->CurrentlyInLongKey())
00609                         return true;
00610 
00611                 EMITTER_STATE curState = m_pState->GetCurState();
00612                 return curState != ES_DONE_WITH_BLOCK_MAP_KEY && curState != ES_WAITING_FOR_BLOCK_MAP_VALUE && curState != ES_WRITING_BLOCK_MAP_VALUE;
00613         }
00614 
00615         // *******************************************************************************************
00616         // overloads of Write
00617         
00618         Emitter& Emitter::Write(const std::string& str)
00619         {
00620                 if(!good())
00621                         return *this;
00622                 
00623                 // literal scalars must use long keys
00624                 if(m_pState->GetStringFormat() == Literal && m_pState->GetCurGroupFlowType() != FT_FLOW)
00625                         m_pState->StartLongKey();
00626                 
00627                 PreAtomicWrite();
00628                 EmitSeparationIfNecessary();
00629                 
00630                 bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
00631                 EMITTER_MANIP strFmt = m_pState->GetStringFormat();
00632                 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
00633                 unsigned curIndent = m_pState->GetCurIndent();
00634 
00635                 switch(strFmt) {
00636                         case Auto:
00637                                 Utils::WriteString(m_stream, str, flowType == FT_FLOW, escapeNonAscii);
00638                                 break;
00639                         case SingleQuoted:
00640                                 if(!Utils::WriteSingleQuotedString(m_stream, str)) {
00641                                         m_pState->SetError(ErrorMsg::SINGLE_QUOTED_CHAR);
00642                                         return *this;
00643                                 }
00644                                 break;
00645                         case DoubleQuoted:
00646                                 Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
00647                                 break;
00648                         case Literal:
00649                                 if(flowType == FT_FLOW)
00650                                         Utils::WriteString(m_stream, str, flowType == FT_FLOW, escapeNonAscii);
00651                                 else
00652                                         Utils::WriteLiteralString(m_stream, str, curIndent + m_pState->GetIndent());
00653                                 break;
00654                         default:
00655                                 assert(false);
00656                 }
00657                 
00658                 PostAtomicWrite();
00659                 return *this;
00660         }
00661 
00662         void Emitter::PreWriteIntegralType(std::stringstream& str)
00663         {
00664                 PreAtomicWrite();
00665                 EmitSeparationIfNecessary();
00666                 
00667                 EMITTER_MANIP intFmt = m_pState->GetIntFormat();
00668                 switch(intFmt) {
00669                         case Dec:
00670                                 str << std::dec;
00671                                 break;
00672                         case Hex:
00673                 str << "0x";
00674                                 str << std::hex;
00675                                 break;
00676                         case Oct:
00677                 str << "0";
00678                                 str << std::oct;
00679                                 break;
00680                         default:
00681                                 assert(false);
00682                 }
00683         }
00684 
00685         void Emitter::PreWriteStreamable(std::stringstream&)
00686         {
00687                 PreAtomicWrite();
00688                 EmitSeparationIfNecessary();
00689         }
00690 
00691     unsigned Emitter::GetFloatPrecision() const
00692     {
00693         return m_pState->GetFloatPrecision();
00694     }
00695     
00696     unsigned Emitter::GetDoublePrecision() const
00697     {
00698         return m_pState->GetDoublePrecision();
00699     }
00700 
00701         void Emitter::PostWriteIntegralType(const std::stringstream& str)
00702         {
00703                 m_stream << str.str();
00704                 PostAtomicWrite();
00705         }
00706 
00707         void Emitter::PostWriteStreamable(const std::stringstream& str)
00708         {
00709                 m_stream << str.str();
00710                 PostAtomicWrite();
00711         }
00712 
00713         const char *Emitter::ComputeFullBoolName(bool b) const
00714         {
00715                 const EMITTER_MANIP mainFmt = (m_pState->GetBoolLengthFormat() == ShortBool ? YesNoBool : m_pState->GetBoolFormat());
00716                 const EMITTER_MANIP caseFmt = m_pState->GetBoolCaseFormat();
00717                 switch(mainFmt) {
00718                         case YesNoBool:
00719                                 switch(caseFmt) {
00720                                         case UpperCase: return b ? "YES" : "NO";
00721                                         case CamelCase: return b ? "Yes" : "No";
00722                                         case LowerCase: return b ? "yes" : "no";
00723                                         default: break;
00724                                 }
00725                                 break;
00726                         case OnOffBool:
00727                                 switch(caseFmt) {
00728                                         case UpperCase: return b ? "ON" : "OFF";
00729                                         case CamelCase: return b ? "On" : "Off";
00730                                         case LowerCase: return b ? "on" : "off";
00731                                         default: break;
00732                                 }
00733                                 break;
00734                         case TrueFalseBool:
00735                                 switch(caseFmt) {
00736                                         case UpperCase: return b ? "TRUE" : "FALSE";
00737                                         case CamelCase: return b ? "True" : "False";
00738                                         case LowerCase: return b ? "true" : "false";
00739                                         default: break;
00740                                 }
00741                                 break;
00742                         default:
00743                                 break;
00744                 }
00745                 return b ? "y" : "n"; // should never get here, but it can't hurt to give these answers
00746         }
00747 
00748         Emitter& Emitter::Write(bool b)
00749         {
00750                 if(!good())
00751                         return *this;
00752                 
00753                 PreAtomicWrite();
00754                 EmitSeparationIfNecessary();
00755         
00756                 const char *name = ComputeFullBoolName(b);
00757                 if(m_pState->GetBoolLengthFormat() == ShortBool)
00758                         m_stream << name[0];
00759                 else
00760                         m_stream << name;
00761 
00762                 PostAtomicWrite();
00763                 return *this;
00764         }
00765 
00766         Emitter& Emitter::Write(char ch)
00767         {
00768                 if(!good())
00769                         return *this;
00770                 
00771                 PreAtomicWrite();
00772                 EmitSeparationIfNecessary();
00773                 
00774                 Utils::WriteChar(m_stream, ch);
00775                 
00776                 PostAtomicWrite();
00777                 return *this;
00778         }
00779 
00780         Emitter& Emitter::Write(const _Alias& alias)
00781         {
00782                 if(!good())
00783                         return *this;
00784                 
00785                 PreAtomicWrite();
00786                 EmitSeparationIfNecessary();
00787                 if(!Utils::WriteAlias(m_stream, alias.content)) {
00788                         m_pState->SetError(ErrorMsg::INVALID_ALIAS);
00789                         return *this;
00790                 }
00791                 PostAtomicWrite();
00792                 return *this;
00793         }
00794         
00795         Emitter& Emitter::Write(const _Anchor& anchor)
00796         {
00797                 if(!good())
00798                         return *this;
00799                 
00800                 PreAtomicWrite();
00801                 EmitSeparationIfNecessary();
00802                 if(!Utils::WriteAnchor(m_stream, anchor.content)) {
00803                         m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
00804                         return *this;
00805                 }
00806                 m_pState->RequireHardSeparation();
00807                 // Note: no PostAtomicWrite() because we need another value for this node
00808                 return *this;
00809         }
00810         
00811         Emitter& Emitter::Write(const _Tag& tag)
00812         {
00813                 if(!good())
00814                         return *this;
00815 
00816                 PreAtomicWrite();
00817                 EmitSeparationIfNecessary();
00818                 
00819                 bool success = false;
00820                 if(tag.type == _Tag::Type::Verbatim)
00821                         success = Utils::WriteTag(m_stream, tag.content, true);
00822                 else if(tag.type == _Tag::Type::PrimaryHandle)
00823                         success = Utils::WriteTag(m_stream, tag.content, false);
00824                 else
00825                         success = Utils::WriteTagWithPrefix(m_stream, tag.prefix, tag.content);
00826                 
00827                 if(!success) {
00828                         m_pState->SetError(ErrorMsg::INVALID_TAG);
00829                         return *this;
00830                 }
00831                 
00832                 m_pState->RequireHardSeparation();
00833                 // Note: no PostAtomicWrite() because we need another value for this node
00834                 return *this;
00835         }
00836 
00837         void Emitter::EmitKindTag()
00838         {
00839                 Write(LocalTag(""));
00840         }
00841 
00842         Emitter& Emitter::Write(const _Comment& comment)
00843         {
00844                 if(!good())
00845                         return *this;
00846                 
00847                 if(m_stream.col() > 0)
00848                         m_stream << Indentation(m_pState->GetPreCommentIndent());
00849                 Utils::WriteComment(m_stream, comment.content, m_pState->GetPostCommentIndent());
00850                 m_pState->RequireHardSeparation();
00851                 m_pState->ForceHardSeparation();
00852                 
00853                 return *this;
00854         }
00855 
00856         Emitter& Emitter::Write(const _Null& /*null*/)
00857         {
00858                 if(!good())
00859                         return *this;
00860                 
00861                 PreAtomicWrite();
00862                 EmitSeparationIfNecessary();
00863                 m_stream << "~";
00864                 PostAtomicWrite();
00865                 return *this;
00866         }
00867 
00868         Emitter& Emitter::Write(const Binary& binary)
00869         {
00870                 Write(SecondaryTag("binary"));
00871 
00872                 if(!good())
00873                         return *this;
00874                 
00875                 PreAtomicWrite();
00876                 EmitSeparationIfNecessary();
00877                 Utils::WriteBinary(m_stream, binary);
00878                 PostAtomicWrite();
00879                 return *this;
00880         }
00881 }
00882 


libpointmatcher
Author(s):
autogenerated on Thu Jun 20 2019 19:51:29