Improve markdown and add colored code syntax
This commit is contained in:
parent
f082897a23
commit
c38ad5bdfb
@ -6,7 +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:
|
||||
|
||||
```
|
||||
```cpp
|
||||
#include "yaml-cpp/yaml.h"
|
||||
|
||||
int main()
|
||||
@ -23,7 +23,7 @@ int main()
|
||||
|
||||
A `YAML::Emitter` object acts as a state machine, and we use manipulators to move it between states. Here's a simple sequence:
|
||||
|
||||
```
|
||||
```cpp
|
||||
YAML::Emitter out;
|
||||
out << YAML::BeginSeq;
|
||||
out << "eggs";
|
||||
@ -31,15 +31,18 @@ out << "bread";
|
||||
out << "milk";
|
||||
out << YAML::EndSeq;
|
||||
```
|
||||
|
||||
produces
|
||||
```
|
||||
|
||||
```yaml
|
||||
- eggs
|
||||
- bread
|
||||
- milk
|
||||
```
|
||||
|
||||
A simple map:
|
||||
```
|
||||
|
||||
```cpp
|
||||
YAML::Emitter out;
|
||||
out << YAML::BeginMap;
|
||||
out << YAML::Key << "name";
|
||||
@ -48,14 +51,17 @@ out << YAML::Key << "position";
|
||||
out << YAML::Value << "LF";
|
||||
out << YAML::EndMap;
|
||||
```
|
||||
|
||||
produces
|
||||
```
|
||||
|
||||
```yaml
|
||||
name: Ryan Braun
|
||||
position: LF
|
||||
```
|
||||
|
||||
These elements can, of course, be nested:
|
||||
```
|
||||
|
||||
```cpp
|
||||
YAML::Emitter out;
|
||||
out << YAML::BeginMap;
|
||||
out << YAML::Key << "name";
|
||||
@ -64,8 +70,10 @@ out << YAML::Key << "children";
|
||||
out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq;
|
||||
out << YAML::EndMap;
|
||||
```
|
||||
|
||||
produces
|
||||
```
|
||||
|
||||
```yaml
|
||||
name: Barack Obama
|
||||
children:
|
||||
- Sasha
|
||||
@ -75,30 +83,37 @@ children:
|
||||
# Using Manipulators #
|
||||
|
||||
To deviate from standard formatting, you can use manipulators to modify the output format. For example,
|
||||
```
|
||||
|
||||
```cpp
|
||||
YAML::Emitter out;
|
||||
out << YAML::Literal << "A\n B\n C";
|
||||
```
|
||||
|
||||
produces
|
||||
```
|
||||
|
||||
```yaml
|
||||
|
|
||||
A
|
||||
B
|
||||
C
|
||||
```
|
||||
and
|
||||
```
|
||||
|
||||
```cpp
|
||||
YAML::Emitter out;
|
||||
out << YAML::Flow;
|
||||
out << YAML::BeginSeq << 2 << 3 << 5 << 7 << 11 << YAML::EndSeq;
|
||||
```
|
||||
|
||||
produces
|
||||
```
|
||||
|
||||
```yaml
|
||||
[2, 3, 5, 7, 11]
|
||||
```
|
||||
|
||||
Comments act like manipulators:
|
||||
```
|
||||
|
||||
```cpp
|
||||
YAML::Emitter out;
|
||||
out << YAML::BeginMap;
|
||||
out << YAML::Key << "method";
|
||||
@ -106,13 +121,16 @@ out << YAML::Value << "least squares";
|
||||
out << YAML::Comment("should we change this method?");
|
||||
out << YAML::EndMap;
|
||||
```
|
||||
|
||||
produces
|
||||
```
|
||||
|
||||
```yaml
|
||||
method: least squares # should we change this method?
|
||||
```
|
||||
|
||||
And so do aliases/anchors:
|
||||
```
|
||||
|
||||
```cpp
|
||||
YAML::Emitter out;
|
||||
out << YAML::BeginSeq;
|
||||
out << YAML::Anchor("fred");
|
||||
@ -123,8 +141,10 @@ out << YAML::EndMap;
|
||||
out << YAML::Alias("fred");
|
||||
out << YAML::EndSeq;
|
||||
```
|
||||
|
||||
produces
|
||||
```
|
||||
|
||||
```yaml
|
||||
- &fred
|
||||
name: Fred
|
||||
age: 42
|
||||
@ -133,7 +153,8 @@ produces
|
||||
|
||||
# STL Containers, and Other Overloads #
|
||||
We overload `operator <<` for `std::vector`, `std::list`, and `std::map`, so you can write stuff like:
|
||||
```
|
||||
|
||||
```cpp
|
||||
std::vector <int> squares;
|
||||
squares.push_back(1);
|
||||
squares.push_back(4);
|
||||
@ -150,8 +171,10 @@ out << YAML::Flow << squares;
|
||||
out << ages;
|
||||
out << YAML::EndSeq;
|
||||
```
|
||||
to produce
|
||||
```
|
||||
|
||||
produces
|
||||
|
||||
```yaml
|
||||
- [1, 4, 9, 16]
|
||||
-
|
||||
Daniel: 26
|
||||
@ -159,7 +182,8 @@ to produce
|
||||
```
|
||||
|
||||
Of course, you can overload `operator <<` for your own types:
|
||||
```
|
||||
|
||||
```cpp
|
||||
struct Vec3 { int x; int y; int z; };
|
||||
YAML::Emitter& operator << (YAML::Emitter& out, const Vec3& v) {
|
||||
out << YAML::Flow;
|
||||
@ -177,7 +201,7 @@ We also overload `operator << ` for `YAML::Node`s in both APIs, so you can outpu
|
||||
|
||||
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`:
|
||||
|
||||
```
|
||||
```cpp
|
||||
emitter.SetOutputCharset(YAML::EscapeNonAscii);
|
||||
```
|
||||
|
||||
@ -186,7 +210,8 @@ emitter.SetOutputCharset(YAML::EscapeNonAscii);
|
||||
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.)
|
||||
|
||||
If you want to permanently change a setting, there are global setters corresponding to each manipulator, e.g.:
|
||||
```
|
||||
|
||||
```cpp
|
||||
YAML::Emitter out;
|
||||
out.SetIndent(4);
|
||||
out.SetMapStyle(YAML::Flow);
|
||||
@ -196,10 +221,10 @@ out.SetMapStyle(YAML::Flow);
|
||||
|
||||
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:
|
||||
|
||||
```
|
||||
YAML::Emitter out;
|
||||
assert(out.good());
|
||||
out << YAML::Key;
|
||||
assert(!out.good());
|
||||
std::cout << "Emitter error: " << out.GetLastError() << "\n";
|
||||
```cpp
|
||||
YAML::Emitter out;
|
||||
assert(out.good());
|
||||
out << YAML::Key;
|
||||
assert(!out.good());
|
||||
std::cout << "Emitter error: " << out.GetLastError() << "\n";
|
||||
```
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
A typical example, loading a configuration file, might look like this:
|
||||
|
||||
```
|
||||
```cpp
|
||||
YAML::Node config = YAML::LoadFile("config.yaml");
|
||||
|
||||
if (config["lastLogin"]) {
|
||||
@ -22,7 +22,7 @@ fout << config;
|
||||
|
||||
All nodes in a YAML document (including the root) are represented by `YAML::Node`. You can check what kind it is:
|
||||
|
||||
```
|
||||
```cpp
|
||||
YAML::Node node = YAML::Load("[1, 2, 3]");
|
||||
assert(node.Type() == YAML::NodeType::Sequence);
|
||||
assert(node.IsSequence()); // a shortcut!
|
||||
@ -30,7 +30,7 @@ assert(node.IsSequence()); // a shortcut!
|
||||
|
||||
Collection nodes (sequences and maps) act somewhat like STL vectors and maps:
|
||||
|
||||
```
|
||||
```cpp
|
||||
YAML::Node primes = YAML::Load("[2, 3, 5, 7, 11]");
|
||||
for (std::size_t i=0;i<primes.size();i++) {
|
||||
std::cout << primes[i].as<int>() << "\n";
|
||||
@ -46,7 +46,7 @@ assert(primes.size() == 6);
|
||||
|
||||
and
|
||||
|
||||
```
|
||||
```cpp
|
||||
YAML::Node lineup = YAML::Load("{1B: Prince Fielder, 2B: Rickie Weeks, LF: Ryan Braun}");
|
||||
for(YAML::const_iterator it=lineup.begin();it!=lineup.end();++it) {
|
||||
std::cout << "Playing at " << it->first.as<std::string>() << " is " << it->second.as<std::string>() << "\n";
|
||||
@ -59,7 +59,7 @@ assert(lineup.size() == 5);
|
||||
|
||||
Querying for keys does **not** create them automatically (this makes handling optional map entries very easy)
|
||||
|
||||
```
|
||||
```cpp
|
||||
YAML::Node node = YAML::Load("{name: Brewers, city: Milwaukee}");
|
||||
if (node["name"]) {
|
||||
std::cout << node["name"].as<std::string>() << "\n";
|
||||
@ -72,7 +72,7 @@ assert(node.size() == 2); // the previous call didn't create a node
|
||||
|
||||
If you're not sure what kind of data you're getting, you can query the type of a node:
|
||||
|
||||
```
|
||||
```cpp
|
||||
switch (node.Type()) {
|
||||
case Null: // ...
|
||||
case Scalar: // ...
|
||||
@ -84,7 +84,7 @@ switch (node.Type()) {
|
||||
|
||||
or ask directly whether it's a particular type, e.g.:
|
||||
|
||||
```
|
||||
```cpp
|
||||
if (node.IsSequence()) {
|
||||
// ...
|
||||
}
|
||||
@ -94,7 +94,7 @@ if (node.IsSequence()) {
|
||||
|
||||
You can build `YAML::Node` from scratch:
|
||||
|
||||
```
|
||||
```cpp
|
||||
YAML::Node node; // starts out as null
|
||||
node["key"] = "value"; // it now is a map node
|
||||
node["seq"].push_back("first element"); // node["seq"] automatically becomes a sequence
|
||||
@ -110,7 +110,7 @@ node[node["mirror"]] = node["seq"]; // and strange loops :)
|
||||
|
||||
The above node is now:
|
||||
|
||||
```
|
||||
```yaml
|
||||
&1
|
||||
key: value
|
||||
&2 seq: [&3 "element #1", second element]
|
||||
@ -123,7 +123,7 @@ self: *1
|
||||
|
||||
Sequences can be turned into maps by asking for non-integer keys. For example,
|
||||
|
||||
```
|
||||
```cpp
|
||||
YAML::Node node = YAML::Load("[1, 2, 3]");
|
||||
node[1] = 5; // still a sequence, [1, 5, 3]
|
||||
node.push_back(-3) // still a sequence, [1, 5, 3, -3]
|
||||
@ -132,7 +132,7 @@ node["key"] = "value"; // now it's a map! {0: 1, 1: 5, 2: 3, 3: -3, key: value}
|
||||
|
||||
Indexing a sequence node by an index that's not in its range will _usually_ turn it into a map, but if the index is one past the end of the sequence, then the sequence will grow by one to accommodate it. (That's the **only** exception to this rule.) For example,
|
||||
|
||||
```
|
||||
```cpp
|
||||
YAML::Node node = YAML::Load("[1, 2, 3]");
|
||||
node[3] = 4; // still a sequence, [1, 2, 3, 4]
|
||||
node[10] = 10; // now it's a map! {0: 1, 1: 2, 2: 3, 3: 4, 10: 10}
|
||||
@ -142,7 +142,7 @@ node[10] = 10; // now it's a map! {0: 1, 1: 2, 2: 3, 3: 4, 10: 10}
|
||||
|
||||
Yaml-cpp has built-in conversion to and from most built-in data types, as well as `std::vector`, `std::list`, and `std::map`. The following examples demonstrate when those conversions are used:
|
||||
|
||||
```
|
||||
```cpp
|
||||
YAML::Node node = YAML::Load("{pi: 3.14159, [0, 1]: integers}");
|
||||
|
||||
// this needs the conversion from Node to double
|
||||
@ -160,13 +160,13 @@ std::string str = node[v].as<std::string>();
|
||||
|
||||
To use yaml-cpp with your own data types, you need to specialize the YAML::convert<> template class. For example, suppose you had a simple `Vec3` class:
|
||||
|
||||
```
|
||||
```cpp
|
||||
struct Vec3 { double x, y, z; /* etc - make sure you have overloaded operator== */ };
|
||||
```
|
||||
|
||||
You could write
|
||||
|
||||
```
|
||||
```cpp
|
||||
namespace YAML {
|
||||
template<>
|
||||
struct convert<Vec3> {
|
||||
@ -194,7 +194,7 @@ struct convert<Vec3> {
|
||||
|
||||
Then you could use `Vec3` wherever you could use any other type:
|
||||
|
||||
```
|
||||
```cpp
|
||||
YAML::Node node = YAML::Load("start: [1, 3, 0]");
|
||||
Vec3 v = node["start"].as<Vec3>();
|
||||
node["end"] = Vec3(2, -1, 0);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user