How-To-Emit-YAML.md (4826B)
1 ## Contents ## 2 3 4 5 # Basic Emitting # 6 7 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: 8 9 ```cpp 10 #include "yaml-cpp/yaml.h" 11 12 int main() 13 { 14 YAML::Emitter out; 15 out << "Hello, World!"; 16 17 std::cout << "Here's the output YAML:\n" << out.c_str(); // prints "Hello, World!" 18 return 0; 19 } 20 ``` 21 22 # Simple Lists and Maps # 23 24 A `YAML::Emitter` object acts as a state machine, and we use manipulators to move it between states. Here's a simple sequence: 25 26 ```cpp 27 YAML::Emitter out; 28 out << YAML::BeginSeq; 29 out << "eggs"; 30 out << "bread"; 31 out << "milk"; 32 out << YAML::EndSeq; 33 ``` 34 35 produces 36 37 ```yaml 38 - eggs 39 - bread 40 - milk 41 ``` 42 43 A simple map: 44 45 ```cpp 46 YAML::Emitter out; 47 out << YAML::BeginMap; 48 out << YAML::Key << "name"; 49 out << YAML::Value << "Ryan Braun"; 50 out << YAML::Key << "position"; 51 out << YAML::Value << "LF"; 52 out << YAML::EndMap; 53 ``` 54 55 produces 56 57 ```yaml 58 name: Ryan Braun 59 position: LF 60 ``` 61 62 These elements can, of course, be nested: 63 64 ```cpp 65 YAML::Emitter out; 66 out << YAML::BeginMap; 67 out << YAML::Key << "name"; 68 out << YAML::Value << "Barack Obama"; 69 out << YAML::Key << "children"; 70 out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq; 71 out << YAML::EndMap; 72 ``` 73 74 produces 75 76 ```yaml 77 name: Barack Obama 78 children: 79 - Sasha 80 - Malia 81 ``` 82 83 # Using Manipulators # 84 85 To deviate from standard formatting, you can use manipulators to modify the output format. For example, 86 87 ```cpp 88 YAML::Emitter out; 89 out << YAML::Literal << "A\n B\n C"; 90 ``` 91 92 produces 93 94 ```yaml 95 | 96 A 97 B 98 C 99 ``` 100 and 101 102 ```cpp 103 YAML::Emitter out; 104 out << YAML::Flow; 105 out << YAML::BeginSeq << 2 << 3 << 5 << 7 << 11 << YAML::EndSeq; 106 ``` 107 108 produces 109 110 ```yaml 111 [2, 3, 5, 7, 11] 112 ``` 113 114 Comments act like manipulators: 115 116 ```cpp 117 YAML::Emitter out; 118 out << YAML::BeginMap; 119 out << YAML::Key << "method"; 120 out << YAML::Value << "least squares"; 121 out << YAML::Comment("should we change this method?"); 122 out << YAML::EndMap; 123 ``` 124 125 produces 126 127 ```yaml 128 method: least squares # should we change this method? 129 ``` 130 131 And so do aliases/anchors: 132 133 ```cpp 134 YAML::Emitter out; 135 out << YAML::BeginSeq; 136 out << YAML::Anchor("fred"); 137 out << YAML::BeginMap; 138 out << YAML::Key << "name" << YAML::Value << "Fred"; 139 out << YAML::Key << "age" << YAML::Value << "42"; 140 out << YAML::EndMap; 141 out << YAML::Alias("fred"); 142 out << YAML::EndSeq; 143 ``` 144 145 produces 146 147 ```yaml 148 - &fred 149 name: Fred 150 age: 42 151 - *fred 152 ``` 153 154 # STL Containers, and Other Overloads # 155 We overload `operator <<` for `std::vector`, `std::list`, and `std::map`, so you can write stuff like: 156 157 ```cpp 158 std::vector <int> squares; 159 squares.push_back(1); 160 squares.push_back(4); 161 squares.push_back(9); 162 squares.push_back(16); 163 164 std::map <std::string, int> ages; 165 ages["Daniel"] = 26; 166 ages["Jesse"] = 24; 167 168 YAML::Emitter out; 169 out << YAML::BeginSeq; 170 out << YAML::Flow << squares; 171 out << ages; 172 out << YAML::EndSeq; 173 ``` 174 175 produces 176 177 ```yaml 178 - [1, 4, 9, 16] 179 - 180 Daniel: 26 181 Jesse: 24 182 ``` 183 184 Of course, you can overload `operator <<` for your own types: 185 186 ```cpp 187 struct Vec3 { int x; int y; int z; }; 188 YAML::Emitter& operator << (YAML::Emitter& out, const Vec3& v) { 189 out << YAML::Flow; 190 out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq; 191 return out; 192 } 193 ``` 194 and it'll play nicely with everything else. 195 196 # Using Existing Nodes # 197 198 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! 199 200 # Output Encoding # 201 202 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`: 203 204 ```cpp 205 emitter.SetOutputCharset(YAML::EscapeNonAscii); 206 ``` 207 208 # Lifetime of Manipulators # 209 210 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.) 211 212 If you want to permanently change a setting, there are global setters corresponding to each manipulator, e.g.: 213 214 ```cpp 215 YAML::Emitter out; 216 out.SetIndent(4); 217 out.SetMapStyle(YAML::Flow); 218 ``` 219 220 # When Something Goes Wrong # 221 222 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: 223 224 ```cpp 225 YAML::Emitter out; 226 assert(out.good()); 227 out << YAML::Key; 228 assert(!out.good()); 229 std::cout << "Emitter error: " << out.GetLastError() << "\n"; 230 ```