This outlines the basic methods for emitting a YAML document.
Featured Contents
Basic EmittingThe 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: #include "yaml.h" int main() { YAML::Emitter out; out << "Hello, World!"; std::cout << "Here's the output YAML:\n" << out.c_str(); // prints "Hello, World!" return 0; } Simple Lists and MapsA YAML::Emitter object acts as a state machine, and we use manipulators to move it between states. Here's a simple sequence: YAML::Emitter out; out << YAML::BeginSeq; out << "eggs"; out << "bread"; out << "milk"; out << YAML::EndSeq; produces - eggs - bread - milk A simple map: YAML::Emitter out; out << YAML::BeginMap; out << YAML::Key << "name"; out << YAML::Value << "Ryan Braun"; out << YAML::Key << "position"; out << YAML::Value << "LF"; out << YAML::EndMap; produces name: Ryan Braun position: LF These elements can, of course, be nested: YAML::Emitter out; out << YAML::BeginMap; out << YAML::Key << "name"; out << YAML::Value << "Barack Obama"; out << YAML::Key << "children"; out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq; out << YAML::EndMap; produces name: Barack Obama children: - Sasha - Malia Using ManipulatorsTo deviate from standard formatting, you can use manipulators to modify the output format. For example, YAML::Emitter out; out << YAML::Literal << "A\n B\n C"; produces | A B C and YAML::Emitter out; out << YAML::Flow; out << YAML::BeginSeq << 2 << 3 << 5 << 7 << 11 < YAML::EndSeq; produces [2, 3, 5, 7, 11] Comments act like manipulators: YAML::Emitter out; out << YAML::BeginMap; out << YAML::Key << "method"; out << YAML::Value << "least squares"; out << YAML::Comment("should we change this method?"); out << YAML::EndMap; produces method: least squares # should we change this method? And so do aliases/anchors: YAML::Emitter out; out << YAML::BeginSeq; out << YAML::Anchor("fred"); out << YAML::BeginMap; out << YAML::Key << "name" << YAML::Value << "Fred"; out << YAML::Key << "age" << YAML::Value << "42"; out << YAML::EndMap; out << YAML::Alias("fred"); out << YAML::EndSeq; produces - &fred name: Fred age: 42 - *fred STL Containers, and Other OverloadsWe overload operator << for std::vector, std::list, and std::map, so you can write stuff like: std::vector <int> squares; squares.push_back(1); squares.push_back(4); squares.push_back(9); squares.push_back(16); std::map <std::string, int> ages; ages["Daniel"] = 26; ages["Jesse"] = 24; YAML::Emitter out; out << YAML::BeginSeq; out << YAML::Flow << squares; out << ages; out << YAML::EndSeq; to produce - [1, 4, 9, 16] - Daniel: 26 Jesse: 24 Of course, you can overload operator << for your own types: struct Vec3 { int x; int y; int z; }; YAML::Emitter& operator << (YAML::Emitter& out, const Vec3& v) { out << YAML::Flow; out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq; return out; } and it'll play nicely with everything else. Using Existing NodesWe also overload operator << for YAML::Nodes, so you can output already-parsed nodes. Unfortunately, yaml-cpp does not yet provide a good way of modifying existing nodes, so currently the best way to do this is to use the Emitter and pick-and-choose from your node's children. For example: YAML::Node node; // suppose this is a parsed map of scalars to scalars // and we want to replace the value of the key "foo" with "bar" YAML::Emitter emitter; emitter << YAML::BeginMap; for(YAML::Iterator it=node.begin();it!=node.end();++it) { emitter << YAML::Key << it.first(); emitter << YAML::Value; if(it.first().to<std::string>() == "foo") emitter << "bar"; else emitter << it.second(); } emitter << YAML::EndMap; It can get a bit unwieldy for more complex nodes, but it does the trick. Remember, though, that nodes retain no formatting (they represent data), so you may have to drill down to add what you want. Output EncodingThe 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: emitter.SetOutputCharset(YAML::EscapeNonAscii); Lifetime of ManipulatorsManipulators 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.) If you want to permanently change a setting, there are global setters corresponding to each manipulator, e.g.: YAML::Emitter out; out.SetIndent(4); out.SetMapStyle(YAML::Flow); When Something Goes WrongIf 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: YAML::Emitter out; assert(out.good()); out << YAML::Key; assert(!out.good()); std::cout << "Emitter error: " << out.GetLastError() << "\n"; |
HowToEmitYAML
最新推荐文章于 2024-03-20 21:34:16 发布
In the following example:
You need to remove the 1st "out << ages;" for it to make sense with the output.