serializing values

TOMLファイルを出力する #

toml::format を使うと、 toml::value を文字列にすることができます。

#include <toml.hpp>
#include <cassert>

int main()
{
    const toml::value v(toml::table{
        {"a", 42},
        {"b", "foo"},
    });
    const std::string s = toml::format(v);

    const toml::value u = toml::parse_str(s);

    assert(u.at("a").as_integer() == 42);
    assert(u.at("b").as_string()  == "foo");

    return 0;
}

table_type を格納している toml::value が渡されると、それがファイルのルートテーブルとして解釈されます。

もし table_type 以外を格納している toml::value が渡されると、その値だけがフォーマットされます。

一部のフォーマット指定では、キーが渡されていないとフォーマットできないことがあります。 例えば、 toml::array_format::array_of_tables[[array.of.tables]] の形でフォーマットするので、 キーへのアクセスを要求します。

キーを要求するフォーマット指定の値がキーなしで渡された場合、 toml::serialization_error が送出されます。

他にも、フォーマット指定と矛盾する値が含まれる場合には、 toml::serialization_error が送出されます。 例えば、 integer_format::hex が指定された整数が負の値を持っている場合や、 string_format::literal が指定された文字列が改行を含んでいる場合などです。

フォーマットの指定方法は後述します。

キーを渡して出力する #

toml::format には std::string としてキーを渡すことが可能です。

その場合、ルートテーブルの下にそのキーがあり、渡した値はそのキーに対応すると解釈されます。

キーが複数段になる場合、 std::vector<std::string> を渡すことができます。

#include <toml.hpp>
#include <cassert>

int main()
{
    const toml::value v(toml::table{
        {"a", 42},
        {"b", "foo"},
    });
    const std::string s = toml::format("bar", v);

    const toml::value u = toml::parse_str(s);

    assert(u.at("bar").at("a").as_integer() == 42);
    assert(u.at("bar").at("b").as_string()  == "foo");

    return 0;
}

フォーマットを指定する #

toml::value のそれぞれの型には、対応するフォーマット情報型があります。

toml::value::integer_type には toml::integer_format_info が、 toml::value::table_type には toml::table_format_info があります。

これらは、パースした際に設定され、型が変わらない限り値を変更しても引き継がれます。

また、 as_integer_fmt()as_table_fmt() といったメンバ関数によってアクセスすることができ、 直接編集することが可能です。

以下ではいくつかの例を挙げて使い方を説明します。

フォーマットへのアクセス方法は toml::valueのリファレンスを、 フォーマット情報クラスの完全なリストと詳細は formatのリファレンスを 参照してください。

整数のフォーマットを指定する #

整数は、基数と幅、そして _ の位置を指定することができます。

hex, oct, bin のとき、指定された幅に達するまでゼロで埋められます。 dec の場合は幅指定はスペースを追加しますが、これはパースされません。

#include <toml.hpp>

int main()
{
    toml::value v(0x00C0'FFEE);
    v.as_integer_fmt().fmt    = toml::integer_format::hex;
    v.as_integer_fmt().width  = 8;
    v.as_integer_fmt().spacer = 4;

    const std::stirng s = toml::format(v);
    assert(s == "0x00C0_FFEE");

    return 0;
}

詳細は、reference を参照してください。

配列を単一行・複数行にする #

配列には、 toml::array_format::onelinetoml::array_format::multiline を指定できます。

# oneline
a = [1, 2, 3, 4, 5]
# multiline
a = [
  1,
  2,
  3,
  4, 
  5
]

multiline のときは、インデントを指定できます。 各要素は body_indent の分だけインデントされ、閉じ括弧 ]closing_indent の分だけインデントされます。

文字種は indent_type で指定され、 toml::indent_char::space または toml::indent_char::tab が選択できます。

インデントに使用する文字種は統一してください。

一つのファイル内でインデントに異なる文字種が指定された場合、結果は未規定になります。 何らかのインデントがされますが、全ての箇所で文字種やインデントの深さは不定となります。

また、 array の要素が全て table_type を持つ場合、 toml::array_format::array_of_tables が指定できます。

array_of_tables を指定せずに multiline にした場合、テーブルはインラインテーブルになります。

# multiline
a = [
  {foo = 42},
  {bar = "hoge"},
]

# array_of_tables
[[a]]
foo = 42

[[a]]
bar = "hoge"

デフォルトでは、 toml::array_format::default_format が指定されます。 これは適したフォーマットを自動的に選択します。

例えば、 default_format で全要素が table_type だった場合、 array_of_tables が選択されます。 また、十分短い配列は oneline に、長い配列またはネストされた配列などの複雑な配列は multiline になります。

詳細は、reference を参照してください。

テーブルをインラインテーブルにする #

テーブルをインラインテーブルにする際は toml::table_format::oneline を指定します。 通常のテーブルにする際は、 toml::table_format::multiline を指定します。

oneline = {a = 42, b = "foo"}

[multiline]
a = 42
b = "foo"

TOML v1.1.0ではインラインテーブル内での改行が許可されますが、その場合は toml::table_format::multiline_oneline とします。 これは、後述するTOMLバージョン指定で対応する機能フラグがtrueになっていない限り無視されます。

multiline_oneline = {
    a = 42,
    b = "foo"
}

詳細は、reference を参照してください。

TOML言語バージョンを指定して出力する #

TOML v1.1.0で許可されたインラインテーブル内の改行や\xエスケープシーケンスのように、 TOMLバージョンによって使用できない言語機能があります。

toml::format は最後の引数に toml::spec を取ることができます。

これにより、シリアライズ時に使用するTOMLのバージョンを指定することができます。

特に、 toml::parsetoml::spec を使用して新機能を使用した場合は、 パースした値がそのバージョンでしか使えないフォーマット情報を持つ場合があるので、 toml::format にも同じ toml::spec を渡すことを忘れないようにしてください。

#include <toml.hpp>
#include <iostream>

int main()
{
    const auto spec = toml::spec::v(1, 1, 0)

    const toml::value v = toml::parse("input.toml", spec);

    std::cout << toml::format(v, spec);

    return 0;
}