emitter.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. #include <sstream>
  2. #include "emitterutils.h"
  3. #include "indentation.h" // IWYU pragma: keep
  4. #include "yaml-cpp/emitter.h"
  5. #include "yaml-cpp/emitterdef.h"
  6. #include "yaml-cpp/emittermanip.h"
  7. #include "yaml-cpp/exceptions.h" // IWYU pragma: keep
  8. namespace YAML {
  9. class Binary;
  10. struct _Null;
  11. Emitter::Emitter() : m_pState(new EmitterState), m_stream{} {}
  12. Emitter::Emitter(std::ostream& stream)
  13. : m_pState(new EmitterState), m_stream(stream) {}
  14. Emitter::~Emitter() = default;
  15. const char* Emitter::c_str() const { return m_stream.str(); }
  16. std::size_t Emitter::size() const { return m_stream.pos(); }
  17. // state checking
  18. bool Emitter::good() const { return m_pState->good(); }
  19. const std::string Emitter::GetLastError() const {
  20. return m_pState->GetLastError();
  21. }
  22. // global setters
  23. bool Emitter::SetOutputCharset(EMITTER_MANIP value) {
  24. return m_pState->SetOutputCharset(value, FmtScope::Global);
  25. }
  26. bool Emitter::SetStringFormat(EMITTER_MANIP value) {
  27. return m_pState->SetStringFormat(value, FmtScope::Global);
  28. }
  29. bool Emitter::SetBoolFormat(EMITTER_MANIP value) {
  30. bool ok = false;
  31. if (m_pState->SetBoolFormat(value, FmtScope::Global))
  32. ok = true;
  33. if (m_pState->SetBoolCaseFormat(value, FmtScope::Global))
  34. ok = true;
  35. if (m_pState->SetBoolLengthFormat(value, FmtScope::Global))
  36. ok = true;
  37. return ok;
  38. }
  39. bool Emitter::SetNullFormat(EMITTER_MANIP value) {
  40. return m_pState->SetNullFormat(value, FmtScope::Global);
  41. }
  42. bool Emitter::SetIntBase(EMITTER_MANIP value) {
  43. return m_pState->SetIntFormat(value, FmtScope::Global);
  44. }
  45. bool Emitter::SetSeqFormat(EMITTER_MANIP value) {
  46. return m_pState->SetFlowType(GroupType::Seq, value, FmtScope::Global);
  47. }
  48. bool Emitter::SetMapFormat(EMITTER_MANIP value) {
  49. bool ok = false;
  50. if (m_pState->SetFlowType(GroupType::Map, value, FmtScope::Global))
  51. ok = true;
  52. if (m_pState->SetMapKeyFormat(value, FmtScope::Global))
  53. ok = true;
  54. return ok;
  55. }
  56. bool Emitter::SetIndent(std::size_t n) {
  57. return m_pState->SetIndent(n, FmtScope::Global);
  58. }
  59. bool Emitter::SetPreCommentIndent(std::size_t n) {
  60. return m_pState->SetPreCommentIndent(n, FmtScope::Global);
  61. }
  62. bool Emitter::SetPostCommentIndent(std::size_t n) {
  63. return m_pState->SetPostCommentIndent(n, FmtScope::Global);
  64. }
  65. bool Emitter::SetFloatPrecision(std::size_t n) {
  66. return m_pState->SetFloatPrecision(n, FmtScope::Global);
  67. }
  68. bool Emitter::SetDoublePrecision(std::size_t n) {
  69. return m_pState->SetDoublePrecision(n, FmtScope::Global);
  70. }
  71. void Emitter::RestoreGlobalModifiedSettings() {
  72. m_pState->RestoreGlobalModifiedSettings();
  73. }
  74. // SetLocalValue
  75. // . Either start/end a group, or set a modifier locally
  76. Emitter& Emitter::SetLocalValue(EMITTER_MANIP value) {
  77. if (!good())
  78. return *this;
  79. switch (value) {
  80. case BeginDoc:
  81. EmitBeginDoc();
  82. break;
  83. case EndDoc:
  84. EmitEndDoc();
  85. break;
  86. case BeginSeq:
  87. EmitBeginSeq();
  88. break;
  89. case EndSeq:
  90. EmitEndSeq();
  91. break;
  92. case BeginMap:
  93. EmitBeginMap();
  94. break;
  95. case EndMap:
  96. EmitEndMap();
  97. break;
  98. case Key:
  99. case Value:
  100. // deprecated (these can be deduced by the parity of nodes in a map)
  101. break;
  102. case TagByKind:
  103. EmitKindTag();
  104. break;
  105. case Newline:
  106. EmitNewline();
  107. break;
  108. default:
  109. m_pState->SetLocalValue(value);
  110. break;
  111. }
  112. return *this;
  113. }
  114. Emitter& Emitter::SetLocalIndent(const _Indent& indent) {
  115. m_pState->SetIndent(indent.value, FmtScope::Local);
  116. return *this;
  117. }
  118. Emitter& Emitter::SetLocalPrecision(const _Precision& precision) {
  119. if (precision.floatPrecision >= 0)
  120. m_pState->SetFloatPrecision(precision.floatPrecision, FmtScope::Local);
  121. if (precision.doublePrecision >= 0)
  122. m_pState->SetDoublePrecision(precision.doublePrecision, FmtScope::Local);
  123. return *this;
  124. }
  125. // EmitBeginDoc
  126. void Emitter::EmitBeginDoc() {
  127. if (!good())
  128. return;
  129. if (m_pState->CurGroupType() != GroupType::NoType) {
  130. m_pState->SetError("Unexpected begin document");
  131. return;
  132. }
  133. if (m_pState->HasAnchor() || m_pState->HasTag()) {
  134. m_pState->SetError("Unexpected begin document");
  135. return;
  136. }
  137. if (m_stream.col() > 0)
  138. m_stream << "\n";
  139. m_stream << "---\n";
  140. m_pState->StartedDoc();
  141. }
  142. // EmitEndDoc
  143. void Emitter::EmitEndDoc() {
  144. if (!good())
  145. return;
  146. if (m_pState->CurGroupType() != GroupType::NoType) {
  147. m_pState->SetError("Unexpected begin document");
  148. return;
  149. }
  150. if (m_pState->HasAnchor() || m_pState->HasTag()) {
  151. m_pState->SetError("Unexpected begin document");
  152. return;
  153. }
  154. if (m_stream.col() > 0)
  155. m_stream << "\n";
  156. m_stream << "...\n";
  157. }
  158. // EmitBeginSeq
  159. void Emitter::EmitBeginSeq() {
  160. if (!good())
  161. return;
  162. PrepareNode(m_pState->NextGroupType(GroupType::Seq));
  163. m_pState->StartedGroup(GroupType::Seq);
  164. }
  165. // EmitEndSeq
  166. void Emitter::EmitEndSeq() {
  167. if (!good())
  168. return;
  169. FlowType::value originalType = m_pState->CurGroupFlowType();
  170. if (m_pState->CurGroupChildCount() == 0)
  171. m_pState->ForceFlow();
  172. if (m_pState->CurGroupFlowType() == FlowType::Flow) {
  173. if (m_stream.comment())
  174. m_stream << "\n";
  175. m_stream << IndentTo(m_pState->CurIndent());
  176. if (originalType == FlowType::Block) {
  177. m_stream << "[";
  178. } else {
  179. if (m_pState->CurGroupChildCount() == 0 && !m_pState->HasBegunNode())
  180. m_stream << "[";
  181. }
  182. m_stream << "]";
  183. }
  184. m_pState->EndedGroup(GroupType::Seq);
  185. }
  186. // EmitBeginMap
  187. void Emitter::EmitBeginMap() {
  188. if (!good())
  189. return;
  190. PrepareNode(m_pState->NextGroupType(GroupType::Map));
  191. m_pState->StartedGroup(GroupType::Map);
  192. }
  193. // EmitEndMap
  194. void Emitter::EmitEndMap() {
  195. if (!good())
  196. return;
  197. FlowType::value originalType = m_pState->CurGroupFlowType();
  198. if (m_pState->CurGroupChildCount() == 0)
  199. m_pState->ForceFlow();
  200. if (m_pState->CurGroupFlowType() == FlowType::Flow) {
  201. if (m_stream.comment())
  202. m_stream << "\n";
  203. m_stream << IndentTo(m_pState->CurIndent());
  204. if (originalType == FlowType::Block) {
  205. m_stream << "{";
  206. } else {
  207. if (m_pState->CurGroupChildCount() == 0 && !m_pState->HasBegunNode())
  208. m_stream << "{";
  209. }
  210. m_stream << "}";
  211. }
  212. m_pState->EndedGroup(GroupType::Map);
  213. }
  214. // EmitNewline
  215. void Emitter::EmitNewline() {
  216. if (!good())
  217. return;
  218. PrepareNode(EmitterNodeType::NoType);
  219. m_stream << "\n";
  220. m_pState->SetNonContent();
  221. }
  222. bool Emitter::CanEmitNewline() const { return true; }
  223. // Put the stream in a state so we can simply write the next node
  224. // E.g., if we're in a sequence, write the "- "
  225. void Emitter::PrepareNode(EmitterNodeType::value child) {
  226. switch (m_pState->CurGroupNodeType()) {
  227. case EmitterNodeType::NoType:
  228. PrepareTopNode(child);
  229. break;
  230. case EmitterNodeType::FlowSeq:
  231. FlowSeqPrepareNode(child);
  232. break;
  233. case EmitterNodeType::BlockSeq:
  234. BlockSeqPrepareNode(child);
  235. break;
  236. case EmitterNodeType::FlowMap:
  237. FlowMapPrepareNode(child);
  238. break;
  239. case EmitterNodeType::BlockMap:
  240. BlockMapPrepareNode(child);
  241. break;
  242. case EmitterNodeType::Property:
  243. case EmitterNodeType::Scalar:
  244. assert(false);
  245. break;
  246. }
  247. }
  248. void Emitter::PrepareTopNode(EmitterNodeType::value child) {
  249. if (child == EmitterNodeType::NoType)
  250. return;
  251. if (m_pState->CurGroupChildCount() > 0 && m_stream.col() > 0)
  252. EmitBeginDoc();
  253. switch (child) {
  254. case EmitterNodeType::NoType:
  255. break;
  256. case EmitterNodeType::Property:
  257. case EmitterNodeType::Scalar:
  258. case EmitterNodeType::FlowSeq:
  259. case EmitterNodeType::FlowMap:
  260. // TODO: if we were writing null, and
  261. // we wanted it blank, we wouldn't want a space
  262. SpaceOrIndentTo(m_pState->HasBegunContent(), 0);
  263. break;
  264. case EmitterNodeType::BlockSeq:
  265. case EmitterNodeType::BlockMap:
  266. if (m_pState->HasBegunNode())
  267. m_stream << "\n";
  268. break;
  269. }
  270. }
  271. void Emitter::FlowSeqPrepareNode(EmitterNodeType::value child) {
  272. const std::size_t lastIndent = m_pState->LastIndent();
  273. if (!m_pState->HasBegunNode()) {
  274. if (m_stream.comment())
  275. m_stream << "\n";
  276. m_stream << IndentTo(lastIndent);
  277. if (m_pState->CurGroupChildCount() == 0)
  278. m_stream << "[";
  279. else
  280. m_stream << ",";
  281. }
  282. switch (child) {
  283. case EmitterNodeType::NoType:
  284. break;
  285. case EmitterNodeType::Property:
  286. case EmitterNodeType::Scalar:
  287. case EmitterNodeType::FlowSeq:
  288. case EmitterNodeType::FlowMap:
  289. SpaceOrIndentTo(
  290. m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
  291. lastIndent);
  292. break;
  293. case EmitterNodeType::BlockSeq:
  294. case EmitterNodeType::BlockMap:
  295. assert(false);
  296. break;
  297. }
  298. }
  299. void Emitter::BlockSeqPrepareNode(EmitterNodeType::value child) {
  300. const std::size_t curIndent = m_pState->CurIndent();
  301. const std::size_t nextIndent = curIndent + m_pState->CurGroupIndent();
  302. if (child == EmitterNodeType::NoType)
  303. return;
  304. if (!m_pState->HasBegunContent()) {
  305. if (m_pState->CurGroupChildCount() > 0 || m_stream.comment()) {
  306. m_stream << "\n";
  307. }
  308. m_stream << IndentTo(curIndent);
  309. m_stream << "-";
  310. }
  311. switch (child) {
  312. case EmitterNodeType::NoType:
  313. break;
  314. case EmitterNodeType::Property:
  315. case EmitterNodeType::Scalar:
  316. case EmitterNodeType::FlowSeq:
  317. case EmitterNodeType::FlowMap:
  318. SpaceOrIndentTo(m_pState->HasBegunContent(), nextIndent);
  319. break;
  320. case EmitterNodeType::BlockSeq:
  321. m_stream << "\n";
  322. break;
  323. case EmitterNodeType::BlockMap:
  324. if (m_pState->HasBegunContent() || m_stream.comment())
  325. m_stream << "\n";
  326. break;
  327. }
  328. }
  329. void Emitter::FlowMapPrepareNode(EmitterNodeType::value child) {
  330. if (m_pState->CurGroupChildCount() % 2 == 0) {
  331. if (m_pState->GetMapKeyFormat() == LongKey)
  332. m_pState->SetLongKey();
  333. if (m_pState->CurGroupLongKey())
  334. FlowMapPrepareLongKey(child);
  335. else
  336. FlowMapPrepareSimpleKey(child);
  337. } else {
  338. if (m_pState->CurGroupLongKey())
  339. FlowMapPrepareLongKeyValue(child);
  340. else
  341. FlowMapPrepareSimpleKeyValue(child);
  342. }
  343. }
  344. void Emitter::FlowMapPrepareLongKey(EmitterNodeType::value child) {
  345. const std::size_t lastIndent = m_pState->LastIndent();
  346. if (!m_pState->HasBegunNode()) {
  347. if (m_stream.comment())
  348. m_stream << "\n";
  349. m_stream << IndentTo(lastIndent);
  350. if (m_pState->CurGroupChildCount() == 0)
  351. m_stream << "{ ?";
  352. else
  353. m_stream << ", ?";
  354. }
  355. switch (child) {
  356. case EmitterNodeType::NoType:
  357. break;
  358. case EmitterNodeType::Property:
  359. case EmitterNodeType::Scalar:
  360. case EmitterNodeType::FlowSeq:
  361. case EmitterNodeType::FlowMap:
  362. SpaceOrIndentTo(
  363. m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
  364. lastIndent);
  365. break;
  366. case EmitterNodeType::BlockSeq:
  367. case EmitterNodeType::BlockMap:
  368. assert(false);
  369. break;
  370. }
  371. }
  372. void Emitter::FlowMapPrepareLongKeyValue(EmitterNodeType::value child) {
  373. const std::size_t lastIndent = m_pState->LastIndent();
  374. if (!m_pState->HasBegunNode()) {
  375. if (m_stream.comment())
  376. m_stream << "\n";
  377. m_stream << IndentTo(lastIndent);
  378. m_stream << ":";
  379. }
  380. switch (child) {
  381. case EmitterNodeType::NoType:
  382. break;
  383. case EmitterNodeType::Property:
  384. case EmitterNodeType::Scalar:
  385. case EmitterNodeType::FlowSeq:
  386. case EmitterNodeType::FlowMap:
  387. SpaceOrIndentTo(
  388. m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
  389. lastIndent);
  390. break;
  391. case EmitterNodeType::BlockSeq:
  392. case EmitterNodeType::BlockMap:
  393. assert(false);
  394. break;
  395. }
  396. }
  397. void Emitter::FlowMapPrepareSimpleKey(EmitterNodeType::value child) {
  398. const std::size_t lastIndent = m_pState->LastIndent();
  399. if (!m_pState->HasBegunNode()) {
  400. if (m_stream.comment())
  401. m_stream << "\n";
  402. m_stream << IndentTo(lastIndent);
  403. if (m_pState->CurGroupChildCount() == 0)
  404. m_stream << "{";
  405. else
  406. m_stream << ",";
  407. }
  408. switch (child) {
  409. case EmitterNodeType::NoType:
  410. break;
  411. case EmitterNodeType::Property:
  412. case EmitterNodeType::Scalar:
  413. case EmitterNodeType::FlowSeq:
  414. case EmitterNodeType::FlowMap:
  415. SpaceOrIndentTo(
  416. m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
  417. lastIndent);
  418. break;
  419. case EmitterNodeType::BlockSeq:
  420. case EmitterNodeType::BlockMap:
  421. assert(false);
  422. break;
  423. }
  424. }
  425. void Emitter::FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
  426. const std::size_t lastIndent = m_pState->LastIndent();
  427. if (!m_pState->HasBegunNode()) {
  428. if (m_stream.comment())
  429. m_stream << "\n";
  430. m_stream << IndentTo(lastIndent);
  431. if (m_pState->HasAlias()) {
  432. m_stream << " ";
  433. }
  434. m_stream << ":";
  435. }
  436. switch (child) {
  437. case EmitterNodeType::NoType:
  438. break;
  439. case EmitterNodeType::Property:
  440. case EmitterNodeType::Scalar:
  441. case EmitterNodeType::FlowSeq:
  442. case EmitterNodeType::FlowMap:
  443. SpaceOrIndentTo(
  444. m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
  445. lastIndent);
  446. break;
  447. case EmitterNodeType::BlockSeq:
  448. case EmitterNodeType::BlockMap:
  449. assert(false);
  450. break;
  451. }
  452. }
  453. void Emitter::BlockMapPrepareNode(EmitterNodeType::value child) {
  454. if (m_pState->CurGroupChildCount() % 2 == 0) {
  455. if (m_pState->GetMapKeyFormat() == LongKey)
  456. m_pState->SetLongKey();
  457. if (child == EmitterNodeType::BlockSeq ||
  458. child == EmitterNodeType::BlockMap ||
  459. child == EmitterNodeType::Property)
  460. m_pState->SetLongKey();
  461. if (m_pState->CurGroupLongKey())
  462. BlockMapPrepareLongKey(child);
  463. else
  464. BlockMapPrepareSimpleKey(child);
  465. } else {
  466. if (m_pState->CurGroupLongKey())
  467. BlockMapPrepareLongKeyValue(child);
  468. else
  469. BlockMapPrepareSimpleKeyValue(child);
  470. }
  471. }
  472. void Emitter::BlockMapPrepareLongKey(EmitterNodeType::value child) {
  473. const std::size_t curIndent = m_pState->CurIndent();
  474. const std::size_t childCount = m_pState->CurGroupChildCount();
  475. if (child == EmitterNodeType::NoType)
  476. return;
  477. if (!m_pState->HasBegunContent()) {
  478. if (childCount > 0) {
  479. m_stream << "\n";
  480. }
  481. if (m_stream.comment()) {
  482. m_stream << "\n";
  483. }
  484. m_stream << IndentTo(curIndent);
  485. m_stream << "?";
  486. }
  487. switch (child) {
  488. case EmitterNodeType::NoType:
  489. break;
  490. case EmitterNodeType::Property:
  491. case EmitterNodeType::Scalar:
  492. case EmitterNodeType::FlowSeq:
  493. case EmitterNodeType::FlowMap:
  494. SpaceOrIndentTo(true, curIndent + 1);
  495. break;
  496. case EmitterNodeType::BlockSeq:
  497. case EmitterNodeType::BlockMap:
  498. if (m_pState->HasBegunContent())
  499. m_stream << "\n";
  500. break;
  501. }
  502. }
  503. void Emitter::BlockMapPrepareLongKeyValue(EmitterNodeType::value child) {
  504. const std::size_t curIndent = m_pState->CurIndent();
  505. if (child == EmitterNodeType::NoType)
  506. return;
  507. if (!m_pState->HasBegunContent()) {
  508. m_stream << "\n";
  509. m_stream << IndentTo(curIndent);
  510. m_stream << ":";
  511. }
  512. switch (child) {
  513. case EmitterNodeType::NoType:
  514. break;
  515. case EmitterNodeType::Property:
  516. case EmitterNodeType::Scalar:
  517. case EmitterNodeType::FlowSeq:
  518. case EmitterNodeType::FlowMap:
  519. SpaceOrIndentTo(true, curIndent + 1);
  520. break;
  521. case EmitterNodeType::BlockSeq:
  522. case EmitterNodeType::BlockMap:
  523. if (m_pState->HasBegunContent())
  524. m_stream << "\n";
  525. SpaceOrIndentTo(true, curIndent + 1);
  526. break;
  527. }
  528. }
  529. void Emitter::BlockMapPrepareSimpleKey(EmitterNodeType::value child) {
  530. const std::size_t curIndent = m_pState->CurIndent();
  531. const std::size_t childCount = m_pState->CurGroupChildCount();
  532. if (child == EmitterNodeType::NoType)
  533. return;
  534. if (!m_pState->HasBegunNode()) {
  535. if (childCount > 0) {
  536. m_stream << "\n";
  537. }
  538. }
  539. switch (child) {
  540. case EmitterNodeType::NoType:
  541. break;
  542. case EmitterNodeType::Property:
  543. case EmitterNodeType::Scalar:
  544. case EmitterNodeType::FlowSeq:
  545. case EmitterNodeType::FlowMap:
  546. SpaceOrIndentTo(m_pState->HasBegunContent(), curIndent);
  547. break;
  548. case EmitterNodeType::BlockSeq:
  549. case EmitterNodeType::BlockMap:
  550. break;
  551. }
  552. }
  553. void Emitter::BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
  554. const std::size_t curIndent = m_pState->CurIndent();
  555. const std::size_t nextIndent = curIndent + m_pState->CurGroupIndent();
  556. if (!m_pState->HasBegunNode()) {
  557. if (m_pState->HasAlias()) {
  558. m_stream << " ";
  559. }
  560. m_stream << ":";
  561. }
  562. switch (child) {
  563. case EmitterNodeType::NoType:
  564. break;
  565. case EmitterNodeType::Property:
  566. case EmitterNodeType::Scalar:
  567. case EmitterNodeType::FlowSeq:
  568. case EmitterNodeType::FlowMap:
  569. SpaceOrIndentTo(true, nextIndent);
  570. break;
  571. case EmitterNodeType::BlockSeq:
  572. case EmitterNodeType::BlockMap:
  573. m_stream << "\n";
  574. break;
  575. }
  576. }
  577. // SpaceOrIndentTo
  578. // . Prepares for some more content by proper spacing
  579. void Emitter::SpaceOrIndentTo(bool requireSpace, std::size_t indent) {
  580. if (m_stream.comment())
  581. m_stream << "\n";
  582. if (m_stream.col() > 0 && requireSpace)
  583. m_stream << " ";
  584. m_stream << IndentTo(indent);
  585. }
  586. void Emitter::PrepareIntegralStream(std::stringstream& stream) const {
  587. switch (m_pState->GetIntFormat()) {
  588. case Dec:
  589. stream << std::dec;
  590. break;
  591. case Hex:
  592. stream << "0x";
  593. stream << std::hex;
  594. break;
  595. case Oct:
  596. stream << "0";
  597. stream << std::oct;
  598. break;
  599. default:
  600. assert(false);
  601. }
  602. }
  603. void Emitter::StartedScalar() { m_pState->StartedScalar(); }
  604. // *******************************************************************************************
  605. // overloads of Write
  606. StringEscaping::value GetStringEscapingStyle(const EMITTER_MANIP emitterManip) {
  607. switch (emitterManip) {
  608. case EscapeNonAscii:
  609. return StringEscaping::NonAscii;
  610. case EscapeAsJson:
  611. return StringEscaping::JSON;
  612. default:
  613. return StringEscaping::None;
  614. break;
  615. }
  616. }
  617. Emitter& Emitter::Write(const std::string& str) {
  618. if (!good())
  619. return *this;
  620. StringEscaping::value stringEscaping = GetStringEscapingStyle(m_pState->GetOutputCharset());
  621. const StringFormat::value strFormat =
  622. Utils::ComputeStringFormat(str, m_pState->GetStringFormat(),
  623. m_pState->CurGroupFlowType(), stringEscaping == StringEscaping::NonAscii);
  624. if (strFormat == StringFormat::Literal || str.size() > 1024)
  625. m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
  626. PrepareNode(EmitterNodeType::Scalar);
  627. switch (strFormat) {
  628. case StringFormat::Plain:
  629. m_stream << str;
  630. break;
  631. case StringFormat::SingleQuoted:
  632. Utils::WriteSingleQuotedString(m_stream, str);
  633. break;
  634. case StringFormat::DoubleQuoted:
  635. Utils::WriteDoubleQuotedString(m_stream, str, stringEscaping);
  636. break;
  637. case StringFormat::Literal:
  638. Utils::WriteLiteralString(m_stream, str,
  639. m_pState->CurIndent() + m_pState->GetIndent());
  640. break;
  641. }
  642. StartedScalar();
  643. return *this;
  644. }
  645. std::size_t Emitter::GetFloatPrecision() const {
  646. return m_pState->GetFloatPrecision();
  647. }
  648. std::size_t Emitter::GetDoublePrecision() const {
  649. return m_pState->GetDoublePrecision();
  650. }
  651. const char* Emitter::ComputeFullBoolName(bool b) const {
  652. const EMITTER_MANIP mainFmt = (m_pState->GetBoolLengthFormat() == ShortBool
  653. ? YesNoBool
  654. : m_pState->GetBoolFormat());
  655. const EMITTER_MANIP caseFmt = m_pState->GetBoolCaseFormat();
  656. switch (mainFmt) {
  657. case YesNoBool:
  658. switch (caseFmt) {
  659. case UpperCase:
  660. return b ? "YES" : "NO";
  661. case CamelCase:
  662. return b ? "Yes" : "No";
  663. case LowerCase:
  664. return b ? "yes" : "no";
  665. default:
  666. break;
  667. }
  668. break;
  669. case OnOffBool:
  670. switch (caseFmt) {
  671. case UpperCase:
  672. return b ? "ON" : "OFF";
  673. case CamelCase:
  674. return b ? "On" : "Off";
  675. case LowerCase:
  676. return b ? "on" : "off";
  677. default:
  678. break;
  679. }
  680. break;
  681. case TrueFalseBool:
  682. switch (caseFmt) {
  683. case UpperCase:
  684. return b ? "TRUE" : "FALSE";
  685. case CamelCase:
  686. return b ? "True" : "False";
  687. case LowerCase:
  688. return b ? "true" : "false";
  689. default:
  690. break;
  691. }
  692. break;
  693. default:
  694. break;
  695. }
  696. return b ? "y" : "n"; // should never get here, but it can't hurt to give
  697. // these answers
  698. }
  699. const char* Emitter::ComputeNullName() const {
  700. switch (m_pState->GetNullFormat()) {
  701. case LowerNull:
  702. return "null";
  703. case UpperNull:
  704. return "NULL";
  705. case CamelNull:
  706. return "Null";
  707. case TildeNull:
  708. // fallthrough
  709. default:
  710. return "~";
  711. }
  712. }
  713. Emitter& Emitter::Write(bool b) {
  714. if (!good())
  715. return *this;
  716. PrepareNode(EmitterNodeType::Scalar);
  717. const char* name = ComputeFullBoolName(b);
  718. if (m_pState->GetBoolLengthFormat() == ShortBool)
  719. m_stream << name[0];
  720. else
  721. m_stream << name;
  722. StartedScalar();
  723. return *this;
  724. }
  725. Emitter& Emitter::Write(char ch) {
  726. if (!good())
  727. return *this;
  728. PrepareNode(EmitterNodeType::Scalar);
  729. Utils::WriteChar(m_stream, ch, GetStringEscapingStyle(m_pState->GetOutputCharset()));
  730. StartedScalar();
  731. return *this;
  732. }
  733. Emitter& Emitter::Write(const _Alias& alias) {
  734. if (!good())
  735. return *this;
  736. if (m_pState->HasAnchor() || m_pState->HasTag()) {
  737. m_pState->SetError(ErrorMsg::INVALID_ALIAS);
  738. return *this;
  739. }
  740. PrepareNode(EmitterNodeType::Scalar);
  741. if (!Utils::WriteAlias(m_stream, alias.content)) {
  742. m_pState->SetError(ErrorMsg::INVALID_ALIAS);
  743. return *this;
  744. }
  745. StartedScalar();
  746. m_pState->SetAlias();
  747. return *this;
  748. }
  749. Emitter& Emitter::Write(const _Anchor& anchor) {
  750. if (!good())
  751. return *this;
  752. if (m_pState->HasAnchor()) {
  753. m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
  754. return *this;
  755. }
  756. PrepareNode(EmitterNodeType::Property);
  757. if (!Utils::WriteAnchor(m_stream, anchor.content)) {
  758. m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
  759. return *this;
  760. }
  761. m_pState->SetAnchor();
  762. return *this;
  763. }
  764. Emitter& Emitter::Write(const _Tag& tag) {
  765. if (!good())
  766. return *this;
  767. if (m_pState->HasTag()) {
  768. m_pState->SetError(ErrorMsg::INVALID_TAG);
  769. return *this;
  770. }
  771. PrepareNode(EmitterNodeType::Property);
  772. bool success = false;
  773. if (tag.type == _Tag::Type::Verbatim)
  774. success = Utils::WriteTag(m_stream, tag.content, true);
  775. else if (tag.type == _Tag::Type::PrimaryHandle)
  776. success = Utils::WriteTag(m_stream, tag.content, false);
  777. else
  778. success = Utils::WriteTagWithPrefix(m_stream, tag.prefix, tag.content);
  779. if (!success) {
  780. m_pState->SetError(ErrorMsg::INVALID_TAG);
  781. return *this;
  782. }
  783. m_pState->SetTag();
  784. return *this;
  785. }
  786. void Emitter::EmitKindTag() { Write(LocalTag("")); }
  787. Emitter& Emitter::Write(const _Comment& comment) {
  788. if (!good())
  789. return *this;
  790. PrepareNode(EmitterNodeType::NoType);
  791. if (m_stream.col() > 0)
  792. m_stream << Indentation(m_pState->GetPreCommentIndent());
  793. Utils::WriteComment(m_stream, comment.content,
  794. m_pState->GetPostCommentIndent());
  795. m_pState->SetNonContent();
  796. return *this;
  797. }
  798. Emitter& Emitter::Write(const _Null& /*null*/) {
  799. if (!good())
  800. return *this;
  801. PrepareNode(EmitterNodeType::Scalar);
  802. m_stream << ComputeNullName();
  803. StartedScalar();
  804. return *this;
  805. }
  806. Emitter& Emitter::Write(const Binary& binary) {
  807. Write(SecondaryTag("binary"));
  808. if (!good())
  809. return *this;
  810. PrepareNode(EmitterNodeType::Scalar);
  811. Utils::WriteBinary(m_stream, binary);
  812. StartedScalar();
  813. return *this;
  814. }
  815. } // namespace YAML