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:
|
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"
|
#include "yaml-cpp/yaml.h"
|
||||||
|
|
||||||
int main()
|
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:
|
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;
|
YAML::Emitter out;
|
||||||
out << YAML::BeginSeq;
|
out << YAML::BeginSeq;
|
||||||
out << "eggs";
|
out << "eggs";
|
||||||
@ -31,15 +31,18 @@ out << "bread";
|
|||||||
out << "milk";
|
out << "milk";
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
```
|
```
|
||||||
|
|
||||||
produces
|
produces
|
||||||
```
|
|
||||||
|
```yaml
|
||||||
- eggs
|
- eggs
|
||||||
- bread
|
- bread
|
||||||
- milk
|
- milk
|
||||||
```
|
```
|
||||||
|
|
||||||
A simple map:
|
A simple map:
|
||||||
```
|
|
||||||
|
```cpp
|
||||||
YAML::Emitter out;
|
YAML::Emitter out;
|
||||||
out << YAML::BeginMap;
|
out << YAML::BeginMap;
|
||||||
out << YAML::Key << "name";
|
out << YAML::Key << "name";
|
||||||
@ -48,14 +51,17 @@ out << YAML::Key << "position";
|
|||||||
out << YAML::Value << "LF";
|
out << YAML::Value << "LF";
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
```
|
```
|
||||||
|
|
||||||
produces
|
produces
|
||||||
```
|
|
||||||
|
```yaml
|
||||||
name: Ryan Braun
|
name: Ryan Braun
|
||||||
position: LF
|
position: LF
|
||||||
```
|
```
|
||||||
|
|
||||||
These elements can, of course, be nested:
|
These elements can, of course, be nested:
|
||||||
```
|
|
||||||
|
```cpp
|
||||||
YAML::Emitter out;
|
YAML::Emitter out;
|
||||||
out << YAML::BeginMap;
|
out << YAML::BeginMap;
|
||||||
out << YAML::Key << "name";
|
out << YAML::Key << "name";
|
||||||
@ -64,8 +70,10 @@ out << YAML::Key << "children";
|
|||||||
out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq;
|
out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq;
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
```
|
```
|
||||||
|
|
||||||
produces
|
produces
|
||||||
```
|
|
||||||
|
```yaml
|
||||||
name: Barack Obama
|
name: Barack Obama
|
||||||
children:
|
children:
|
||||||
- Sasha
|
- Sasha
|
||||||
@ -75,30 +83,37 @@ children:
|
|||||||
# Using Manipulators #
|
# Using Manipulators #
|
||||||
|
|
||||||
To deviate from standard formatting, you can use manipulators to modify the output format. For example,
|
To deviate from standard formatting, you can use manipulators to modify the output format. For example,
|
||||||
```
|
|
||||||
|
```cpp
|
||||||
YAML::Emitter out;
|
YAML::Emitter out;
|
||||||
out << YAML::Literal << "A\n B\n C";
|
out << YAML::Literal << "A\n B\n C";
|
||||||
```
|
```
|
||||||
|
|
||||||
produces
|
produces
|
||||||
```
|
|
||||||
|
```yaml
|
||||||
|
|
|
|
||||||
A
|
A
|
||||||
B
|
B
|
||||||
C
|
C
|
||||||
```
|
```
|
||||||
and
|
and
|
||||||
```
|
|
||||||
|
```cpp
|
||||||
YAML::Emitter out;
|
YAML::Emitter out;
|
||||||
out << YAML::Flow;
|
out << YAML::Flow;
|
||||||
out << YAML::BeginSeq << 2 << 3 << 5 << 7 << 11 << YAML::EndSeq;
|
out << YAML::BeginSeq << 2 << 3 << 5 << 7 << 11 << YAML::EndSeq;
|
||||||
```
|
```
|
||||||
|
|
||||||
produces
|
produces
|
||||||
```
|
|
||||||
|
```yaml
|
||||||
[2, 3, 5, 7, 11]
|
[2, 3, 5, 7, 11]
|
||||||
```
|
```
|
||||||
|
|
||||||
Comments act like manipulators:
|
Comments act like manipulators:
|
||||||
```
|
|
||||||
|
```cpp
|
||||||
YAML::Emitter out;
|
YAML::Emitter out;
|
||||||
out << YAML::BeginMap;
|
out << YAML::BeginMap;
|
||||||
out << YAML::Key << "method";
|
out << YAML::Key << "method";
|
||||||
@ -106,13 +121,16 @@ out << YAML::Value << "least squares";
|
|||||||
out << YAML::Comment("should we change this method?");
|
out << YAML::Comment("should we change this method?");
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
```
|
```
|
||||||
|
|
||||||
produces
|
produces
|
||||||
```
|
|
||||||
|
```yaml
|
||||||
method: least squares # should we change this method?
|
method: least squares # should we change this method?
|
||||||
```
|
```
|
||||||
|
|
||||||
And so do aliases/anchors:
|
And so do aliases/anchors:
|
||||||
```
|
|
||||||
|
```cpp
|
||||||
YAML::Emitter out;
|
YAML::Emitter out;
|
||||||
out << YAML::BeginSeq;
|
out << YAML::BeginSeq;
|
||||||
out << YAML::Anchor("fred");
|
out << YAML::Anchor("fred");
|
||||||
@ -123,8 +141,10 @@ out << YAML::EndMap;
|
|||||||
out << YAML::Alias("fred");
|
out << YAML::Alias("fred");
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
```
|
```
|
||||||
|
|
||||||
produces
|
produces
|
||||||
```
|
|
||||||
|
```yaml
|
||||||
- &fred
|
- &fred
|
||||||
name: Fred
|
name: Fred
|
||||||
age: 42
|
age: 42
|
||||||
@ -133,7 +153,8 @@ produces
|
|||||||
|
|
||||||
# STL Containers, and Other Overloads #
|
# STL Containers, and Other Overloads #
|
||||||
We overload `operator <<` for `std::vector`, `std::list`, and `std::map`, so you can write stuff like:
|
We overload `operator <<` for `std::vector`, `std::list`, and `std::map`, so you can write stuff like:
|
||||||
```
|
|
||||||
|
```cpp
|
||||||
std::vector <int> squares;
|
std::vector <int> squares;
|
||||||
squares.push_back(1);
|
squares.push_back(1);
|
||||||
squares.push_back(4);
|
squares.push_back(4);
|
||||||
@ -150,8 +171,10 @@ out << YAML::Flow << squares;
|
|||||||
out << ages;
|
out << ages;
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
```
|
```
|
||||||
to produce
|
|
||||||
```
|
produces
|
||||||
|
|
||||||
|
```yaml
|
||||||
- [1, 4, 9, 16]
|
- [1, 4, 9, 16]
|
||||||
-
|
-
|
||||||
Daniel: 26
|
Daniel: 26
|
||||||
@ -159,7 +182,8 @@ to produce
|
|||||||
```
|
```
|
||||||
|
|
||||||
Of course, you can overload `operator <<` for your own types:
|
Of course, you can overload `operator <<` for your own types:
|
||||||
```
|
|
||||||
|
```cpp
|
||||||
struct Vec3 { int x; int y; int z; };
|
struct Vec3 { int x; int y; int z; };
|
||||||
YAML::Emitter& operator << (YAML::Emitter& out, const Vec3& v) {
|
YAML::Emitter& operator << (YAML::Emitter& out, const Vec3& v) {
|
||||||
out << YAML::Flow;
|
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`:
|
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);
|
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.)
|
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.:
|
If you want to permanently change a setting, there are global setters corresponding to each manipulator, e.g.:
|
||||||
```
|
|
||||||
|
```cpp
|
||||||
YAML::Emitter out;
|
YAML::Emitter out;
|
||||||
out.SetIndent(4);
|
out.SetIndent(4);
|
||||||
out.SetMapStyle(YAML::Flow);
|
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:
|
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:
|
||||||
|
|
||||||
```
|
```cpp
|
||||||
YAML::Emitter out;
|
YAML::Emitter out;
|
||||||
assert(out.good());
|
assert(out.good());
|
||||||
out << YAML::Key;
|
out << YAML::Key;
|
||||||
assert(!out.good());
|
assert(!out.good());
|
||||||
std::cout << "Emitter error: " << out.GetLastError() << "\n";
|
std::cout << "Emitter error: " << out.GetLastError() << "\n";
|
||||||
```
|
```
|
||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
A typical example, loading a configuration file, might look like this:
|
A typical example, loading a configuration file, might look like this:
|
||||||
|
|
||||||
```
|
```cpp
|
||||||
YAML::Node config = YAML::LoadFile("config.yaml");
|
YAML::Node config = YAML::LoadFile("config.yaml");
|
||||||
|
|
||||||
if (config["lastLogin"]) {
|
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:
|
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]");
|
YAML::Node node = YAML::Load("[1, 2, 3]");
|
||||||
assert(node.Type() == YAML::NodeType::Sequence);
|
assert(node.Type() == YAML::NodeType::Sequence);
|
||||||
assert(node.IsSequence()); // a shortcut!
|
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:
|
Collection nodes (sequences and maps) act somewhat like STL vectors and maps:
|
||||||
|
|
||||||
```
|
```cpp
|
||||||
YAML::Node primes = YAML::Load("[2, 3, 5, 7, 11]");
|
YAML::Node primes = YAML::Load("[2, 3, 5, 7, 11]");
|
||||||
for (std::size_t i=0;i<primes.size();i++) {
|
for (std::size_t i=0;i<primes.size();i++) {
|
||||||
std::cout << primes[i].as<int>() << "\n";
|
std::cout << primes[i].as<int>() << "\n";
|
||||||
@ -46,7 +46,7 @@ assert(primes.size() == 6);
|
|||||||
|
|
||||||
and
|
and
|
||||||
|
|
||||||
```
|
```cpp
|
||||||
YAML::Node lineup = YAML::Load("{1B: Prince Fielder, 2B: Rickie Weeks, LF: Ryan Braun}");
|
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) {
|
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";
|
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)
|
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}");
|
YAML::Node node = YAML::Load("{name: Brewers, city: Milwaukee}");
|
||||||
if (node["name"]) {
|
if (node["name"]) {
|
||||||
std::cout << node["name"].as<std::string>() << "\n";
|
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:
|
If you're not sure what kind of data you're getting, you can query the type of a node:
|
||||||
|
|
||||||
```
|
```cpp
|
||||||
switch (node.Type()) {
|
switch (node.Type()) {
|
||||||
case Null: // ...
|
case Null: // ...
|
||||||
case Scalar: // ...
|
case Scalar: // ...
|
||||||
@ -84,7 +84,7 @@ switch (node.Type()) {
|
|||||||
|
|
||||||
or ask directly whether it's a particular type, e.g.:
|
or ask directly whether it's a particular type, e.g.:
|
||||||
|
|
||||||
```
|
```cpp
|
||||||
if (node.IsSequence()) {
|
if (node.IsSequence()) {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@ if (node.IsSequence()) {
|
|||||||
|
|
||||||
You can build `YAML::Node` from scratch:
|
You can build `YAML::Node` from scratch:
|
||||||
|
|
||||||
```
|
```cpp
|
||||||
YAML::Node node; // starts out as null
|
YAML::Node node; // starts out as null
|
||||||
node["key"] = "value"; // it now is a map node
|
node["key"] = "value"; // it now is a map node
|
||||||
node["seq"].push_back("first element"); // node["seq"] automatically becomes a sequence
|
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:
|
The above node is now:
|
||||||
|
|
||||||
```
|
```yaml
|
||||||
&1
|
&1
|
||||||
key: value
|
key: value
|
||||||
&2 seq: [&3 "element #1", second element]
|
&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,
|
Sequences can be turned into maps by asking for non-integer keys. For example,
|
||||||
|
|
||||||
```
|
```cpp
|
||||||
YAML::Node node = YAML::Load("[1, 2, 3]");
|
YAML::Node node = YAML::Load("[1, 2, 3]");
|
||||||
node[1] = 5; // still a sequence, [1, 5, 3]
|
node[1] = 5; // still a sequence, [1, 5, 3]
|
||||||
node.push_back(-3) // still a sequence, [1, 5, 3, -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,
|
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]");
|
YAML::Node node = YAML::Load("[1, 2, 3]");
|
||||||
node[3] = 4; // still a sequence, [1, 2, 3, 4]
|
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}
|
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:
|
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}");
|
YAML::Node node = YAML::Load("{pi: 3.14159, [0, 1]: integers}");
|
||||||
|
|
||||||
// this needs the conversion from Node to double
|
// 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:
|
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== */ };
|
struct Vec3 { double x, y, z; /* etc - make sure you have overloaded operator== */ };
|
||||||
```
|
```
|
||||||
|
|
||||||
You could write
|
You could write
|
||||||
|
|
||||||
```
|
```cpp
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
template<>
|
template<>
|
||||||
struct convert<Vec3> {
|
struct convert<Vec3> {
|
||||||
@ -194,7 +194,7 @@ struct convert<Vec3> {
|
|||||||
|
|
||||||
Then you could use `Vec3` wherever you could use any other type:
|
Then you could use `Vec3` wherever you could use any other type:
|
||||||
|
|
||||||
```
|
```cpp
|
||||||
YAML::Node node = YAML::Load("start: [1, 3, 0]");
|
YAML::Node node = YAML::Load("start: [1, 3, 0]");
|
||||||
Vec3 v = node["start"].as<Vec3>();
|
Vec3 v = node["start"].as<Vec3>();
|
||||||
node["end"] = Vec3(2, -1, 0);
|
node["end"] = Vec3(2, -1, 0);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user