emitter.cpp 22 KB

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