HowToEmitYAML

This outlines the basic methods for emitting a YAML document.
Featured
Updated Sep 13, 2011 by jbe...@gmail.com

Contents

Basic Emitting

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:

#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 Maps

A 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 Manipulators

To 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 Overloads

We 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 Nodes

We 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 Encoding

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:

emitter.SetOutputCharset(YAML::EscapeNonAscii);

Lifetime of Manipulators

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.:

YAML::Emitter out;
out.SetIndent(4);
out.SetMapStyle(YAML::Flow);

When Something Goes Wrong

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";
Comment by philippe...@gmail.com, Jun 18, 2009

In the following example:

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;
out << ages;

YAML::Emitter out;
out << YAML::BeginSeq;
out << YAML::Flow << squares;
out << ages;
out << YAML::EndSeq;

You need to remove the 1st "out << ages;" for it to make sense with the output.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值