You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

224 lines
4.6 KiB

2 months ago
  1. ## Contents ##
  2. # Basic Emitting #
  3. The model for emitting YAML is `std::ostream` manipulators. A `YAML::Emitter` objects acts as an output stream, and its output can be retrieved through the `c_str()` function (as in `std::string`). For a simple example:
  4. ```cpp
  5. #include "yaml-cpp/yaml.h"
  6. int main()
  7. {
  8. YAML::Emitter out;
  9. out << "Hello, World!";
  10. std::cout << "Here's the output YAML:\n" << out.c_str(); // prints "Hello, World!"
  11. return 0;
  12. }
  13. ```
  14. # Simple Lists and Maps #
  15. A `YAML::Emitter` object acts as a state machine, and we use manipulators to move it between states. Here's a simple sequence:
  16. ```cpp
  17. YAML::Emitter out;
  18. out << YAML::BeginSeq;
  19. out << "eggs";
  20. out << "bread";
  21. out << "milk";
  22. out << YAML::EndSeq;
  23. ```
  24. produces
  25. ```yaml
  26. - eggs
  27. - bread
  28. - milk
  29. ```
  30. A simple map:
  31. ```cpp
  32. YAML::Emitter out;
  33. out << YAML::BeginMap;
  34. out << YAML::Key << "name";
  35. out << YAML::Value << "Ryan Braun";
  36. out << YAML::Key << "position";
  37. out << YAML::Value << "LF";
  38. out << YAML::EndMap;
  39. ```
  40. produces
  41. ```yaml
  42. name: Ryan Braun
  43. position: LF
  44. ```
  45. These elements can, of course, be nested:
  46. ```cpp
  47. YAML::Emitter out;
  48. out << YAML::BeginMap;
  49. out << YAML::Key << "name";
  50. out << YAML::Value << "Barack Obama";
  51. out << YAML::Key << "children";
  52. out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq;
  53. out << YAML::EndMap;
  54. ```
  55. produces
  56. ```yaml
  57. name: Barack Obama
  58. children:
  59. - Sasha
  60. - Malia
  61. ```
  62. # Using Manipulators #
  63. To deviate from standard formatting, you can use manipulators to modify the output format. For example,
  64. ```cpp
  65. YAML::Emitter out;
  66. out << YAML::Literal << "A\n B\n C";
  67. ```
  68. produces
  69. ```yaml
  70. |
  71. A
  72. B
  73. C
  74. ```
  75. and
  76. ```cpp
  77. YAML::Emitter out;
  78. out << YAML::Flow;
  79. out << YAML::BeginSeq << 2 << 3 << 5 << 7 << 11 << YAML::EndSeq;
  80. ```
  81. produces
  82. ```yaml
  83. [2, 3, 5, 7, 11]
  84. ```
  85. Comments act like manipulators:
  86. ```cpp
  87. YAML::Emitter out;
  88. out << YAML::BeginMap;
  89. out << YAML::Key << "method";
  90. out << YAML::Value << "least squares";
  91. out << YAML::Comment("should we change this method?");
  92. out << YAML::EndMap;
  93. ```
  94. produces
  95. ```yaml
  96. method: least squares # should we change this method?
  97. ```
  98. And so do aliases/anchors:
  99. ```cpp
  100. YAML::Emitter out;
  101. out << YAML::BeginSeq;
  102. out << YAML::Anchor("fred");
  103. out << YAML::BeginMap;
  104. out << YAML::Key << "name" << YAML::Value << "Fred";
  105. out << YAML::Key << "age" << YAML::Value << "42";
  106. out << YAML::EndMap;
  107. out << YAML::Alias("fred");
  108. out << YAML::EndSeq;
  109. ```
  110. produces
  111. ```yaml
  112. - &fred
  113. name: Fred
  114. age: 42
  115. - *fred
  116. ```
  117. # STL Containers, and Other Overloads #
  118. We overload `operator <<` for `std::vector`, `std::list`, and `std::map`, so you can write stuff like:
  119. ```cpp
  120. std::vector <int> squares = {1, 4, 9, 16};
  121. std::map <std::string, int> ages = {{"Daniel", 26}, {"Jesse", 24}};
  122. YAML::Emitter out;
  123. out << YAML::BeginSeq;
  124. out << YAML::Flow << squares;
  125. out << ages;
  126. out << YAML::EndSeq;
  127. ```
  128. produces
  129. ```yaml
  130. - [1, 4, 9, 16]
  131. -
  132. Daniel: 26
  133. Jesse: 24
  134. ```
  135. Of course, you can overload `operator <<` for your own types:
  136. ```cpp
  137. struct Vec3 { int x; int y; int z; };
  138. YAML::Emitter& operator << (YAML::Emitter& out, const Vec3& v) {
  139. out << YAML::Flow;
  140. out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq;
  141. return out;
  142. }
  143. ```
  144. and it'll play nicely with everything else.
  145. # Using Existing Nodes #
  146. We also overload `operator << ` for `YAML::Node`s in both APIs, so you can output existing Nodes. Of course, Nodes in the old API are read-only, so it's tricky to emit them if you want to modify them. So use the new API!
  147. # Output Encoding #
  148. The output is always UTF-8. By default, yaml-cpp will output as much as it can without escaping any characters. If you want to restrict the output to ASCII, use the manipulator `YAML::EscapeNonAscii`:
  149. ```cpp
  150. emitter.SetOutputCharset(YAML::EscapeNonAscii);
  151. ```
  152. # Lifetime of Manipulators #
  153. Manipulators affect the **next** output item in the stream. If that item is a `BeginSeq` or `BeginMap`, the manipulator lasts until the corresponding `EndSeq` or `EndMap`. (However, within that sequence or map, you can override the manipulator locally, etc.; in effect, there's a "manipulator stack" behind the scenes.)
  154. If you want to permanently change a setting, there are global setters corresponding to each manipulator, e.g.:
  155. ```cpp
  156. YAML::Emitter out;
  157. out.SetIndent(4);
  158. out.SetMapStyle(YAML::Flow);
  159. ```
  160. # When Something Goes Wrong #
  161. If something goes wrong when you're emitting a document, it must be something like forgetting a `YAML::EndSeq`, or a misplaced `YAML::Key`. In this case, emitting silently fails (no more output is emitted) and an error flag is set. For example:
  162. ```cpp
  163. YAML::Emitter out;
  164. assert(out.good());
  165. out << YAML::Key;
  166. assert(!out.good());
  167. std::cout << "Emitter error: " << out.GetLastError() << "\n";
  168. ```