changelog

Change Log #

v4.2.0 #

Added #

  • TOML11_DEFINE_CONVERSION_NON_INTRUSIVEstd::optional なメンバをサポート (by Ken Matsui @ken-matsui)
  • thread_localだったcolor_modeをデフォルトでグローバルにし、thread_localにするオプションを追加 (by Ken Matsui @ken-matsui)
  • CPMでの使い方をREADMEに追加
  • READMEordered_mapへの言及を追加し、ドキュメントでの説明を追加

Fixed #

  • ファイルサイズのstd::streamsizeへの変換で警告が出ることがある問題を修正 (by Pino Toscano @pinotree)
  • table_formatに不正な値が与えられた際の出力のtypoを修正
  • arrayのフォーマットがarray_of_tablesと指定されていてかつ空の場合の出力を修正
  • 特定の環境でincludeが足りずにコンパイルできない問題を修正
  • ドキュメントに含まれる文法エラーを修正 (by Jack W)
  • toml::find_or を深くネストされたテーブルに使用した際にコンパイルが失敗する問題を修正

v4.1.0 #

Added #

  • std::get<std::u8string>をサポート
  • toml::value(std::u8string)をサポート
  • string_type = std::u8stringをサポート
  • operator<<(std::ostream&, toml::value)をサポート
  • toml::integer_formatに、16進数表示で大文字を使うことを指定するbool uppercaseを追加
  • templateを使って実装された into_toml() をサポート (by 萧迩珀)

Fixed #

  • Windowsで\r\nが改行に使われた際、出力時に\rが重複する問題を修正 (by Andreas Keller)

Changed #

  • CIで複数コアを使うことでビルドを高速化

v4.0.3 #

Fixed #

  • toml_fwd.hppを使用した際にデフォルト引数が重複する問題を修正
  • toml::valueを複数渡した際にtoml::make_error_infoが使えない問題を修正
  • std::reference_wrapperを持つtoml::resultをコピー・ムーブする際の問題を修正
  • hugoの最新版でドキュメントがビルドできない問題を修正
  • コンパイラによる軽微な警告を多数修正
  • CMakeの互換性に関する警告を抑制

Changed #

  • CIビルドで-Werror, /WXを追加
  • CIビルドでMSVCのwarningレベルを/W3から/W4に変更
  • READMEでより多くの機能を紹介するよう更新

v4.0.2 #

Fixed #

  • parse(FILE*) 内の fread の結果をチェック
  • toml11/version.hppのマクロを修正
  • コンパイルオプションに関するドキュメントの更新
  • ファイルオープンモードに関するドキュメントの更新

Changed #

  • CMakeLists.txt内のバージョン番号をversion.hppから取得するように変更

v4.0.1 #

Fixed #

  • sematic_version::{major, minor}<sys/sysmacro.h> 内で定義されるマクロの衝突を解消
  • discard_commentsoperator<< の定義を修正 (by Egor Pugin)
  • format_locationを使用した際に最初の空行が出ない問題を解決
  • 改行文字のみを含む行を指すsource_locationでエラーメッセージを生成した際に、同じ行が二回表示される問題を解決
  • README.md内のリンクを修正
  • example/unicodeのREADMEのタイトルを修正

Added #

  • mainに変更があったとき、single_include/toml.hppを自動生成するようCIを設定

v3からv4への変化 #

破壊的変更 #

toml::basic_valuetemplate引数を変更 #

toml11 v3では、toml::basic_valueはコメントコンテナ、テーブル型コンテナ、配列型コンテナをそれぞれ取っていました。

template<typename Comment,
         template<typename ...> class Table = std::unordered_map,
         template<typename ...> class Array = std::vector>
class basic_value;

ですが、integer_typeなどを変更したいという場合にはこれでは対応できません。

toml11 v4では、toml::basic_valueは単一のTypeConfigを受け取り、より多くの型を変更可能にします。

template<typename TypeConfig>
class basic_value;

デフォルトではtoml::valueが格納する型は変わりません。

型を変更する際は、 type_config を参照してください。

toml::basic_valuestd::initializer_listサポートを削除 #

toml11 v3では、 toml::valuestd::initializer_list を取るオーバーロードが用意されていました。

これにより、 toml::value を配列やテーブルで初期化する際により直観的な書き方が可能でした。

// toml11 v3
toml::value v{1,2,3,4,5};
toml::value v{ {"a", 42}, {"b", "foo"} };

しかし、これは同時に以下のような問題を引き起こしました。

一つ目は、1要素の配列と通常の値の区別がつかず、常に配列になってしまうことです。

// toml11 v3
toml::value v{1}; // 1 ではなく [1,] になってしまう

統一初期化記法が普及した現在、これは非常に不便です。

二つ目は、値が全て文字列のテーブルと、ネストされた配列の区別がつかないことです。

// toml11 v3
toml::value v{ {"a", "foo"}, {"b", "bar"} };
// {a = "foo", b = "bar"}
// [["a", "foo"], ["b", "bar"]]
// のどちらでもあり得る

これらの問題は言語仕様上解決が困難です。

toml11 v4では、混乱を避けるため、std::initializer_listサポートを削除しました。

toml::value を配列で初期化する際はexplicitに toml::array を、 テーブルで初期化する際はexplicitに toml::table を指定する必要があります。

// toml11 v4
toml::value v(toml::array{1,2,3,4,5});
toml::value v(toml::table{ {"a", 42}, {"b", "foo"} });

toml::value v{toml::array{1}}; // [1,]
toml::value v{1}               // 1

toml::value v{toml::table{{"a", "foo"}, {"b", "bar"}}};
toml::value v{toml::array{toml::array{"a", "foo"}, toml::array{"b", "bar"}}};

これにより toml::value をテーブルや配列で初期化する際に少し不便になりますが、 explicitに型情報を記述することにより予測不能な値になることは避けることができます。

toml::basic_value::is_uninitialized()is_empty() に変更 #

toml11 v3では、初期化されていない basic_value かどうかを判定する関数は is_uninitialized でした。

しかし、toml11 v4では言語拡張で null をサポートするため、意図的に空にされた値が構築される可能性があります。 なので命名を変更し、 is_empty としました。

toml::string を廃止、フォーマット情報を陽に格納 #

toml11 v3では、文字列が basicliteral かの情報を保持するため、 格納する文字列型に toml::string という std::string の薄いラッパーを使用していました。

// toml11 v3
namespace toml
{
enum class string_t : std::uint8_t
{
    basic   = 0,
    literal = 1,
};

struct string
{
    string_t    kind;
    std::string str;
};
} // toml

toml11 v4では、数値型の基数や配列を複数行にするかどうかなどのより多くのフォーマット情報を持たせるため、 全ての型に xxx_format 型を用意し、値とペアで格納することにしました。

// toml11 v4
enum class string_format : std::uint8_t
{
    basic             = 0,
    literal           = 1,
    multiline_basic   = 2,
    multiline_literal = 3
};

struct string_format_info
{
    string_format fmt = string_format::basic;
    bool start_with_newline    = false;
};

これにより、より細かいフォーマット情報を保持することができるようになり、 特に数値型や配列、テーブル型のフォーマット情報がパース後も維持できるようになりました。

toml::formatの引数を変更 #

toml11 v3では、 toml::format が数値型の精度や幅などの値を受け取っていました。

しかし、これでは細かなフォーマット指定ができず、予想したようなファイルにシリアライズできませんでした。

toml11 v4では、各 toml::value にそれぞれのフォーマット情報を格納したため、 より細かいフォーマット情報を toml::value 自体が持ち運べるようになりました。

これにより、 toml::format 自体はフォーマット指定を受け取らず、 フォーマット時に使用できる言語機能フラグを持つ toml::spec のみを取るようになりました。

toml::source_locationのメンバ関数を変更 #

toml11 v3では、 toml::source_location のメンバ型は一行分だけを意識したものでした。

toml11 v4では、 toml::source_location のメンバ型は複数行が前提になります。

toml::format_underlinetoml::format_locationに変更 #

toml11 v3では、 toml::source_location を使用して位置情報を文字列化するとき、 toml::format_underline を使用していました。

しかしこれは名称としてわかりにくいため、 toml::format_location に変更しました。

format_errorの引数を変更 #

toml11 v3ではエラー情報を表すクラスがなかったため、toml::format_errorの引数が複雑になっていました。

template<typename C, template<typename ...> class T, template<typename ...> class A>
std::string format_error(const std::string& err_msg,
        const basic_value<C, T, A>& v, const std::string& comment,
        std::vector<std::string> hints = {},
        const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED);

template<typename C, template<typename ...> class T, template<typename ...> class A>
inline std::string format_error(const std::string& err_msg,
        const toml::basic_value<C, T, A>& v1, const std::string& comment1,
        const toml::basic_value<C, T, A>& v2, const std::string& comment2,
        std::vector<std::string> hints = {},
        const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED);

template<typename C, template<typename ...> class T, template<typename ...> class A>
inline std::string format_error(const std::string& err_msg,
        const toml::basic_value<C, T, A>& v1, const std::string& comment1,
        const toml::basic_value<C, T, A>& v2, const std::string& comment2,
        const toml::basic_value<C, T, A>& v3, const std::string& comment3,
        std::vector<std::string> hints = {},
        const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED);

toml11 v4では、class error_infomake_error_infoを導入し、format_errorの引数を簡略化しました。

std::string format_error(const error_info& err);
std::string format_error(const std::string& errkind, const error_info& err);

template<typename ... Ts>
std::string format_error(std::string title,
        source_location loc, std::string msg, Ts&& ... tail);

template<typename TC, typename ... Ts>
std::string format_error(std::string title,
        const basic_value<TC>& v, std::string msg, Ts&& ... tail);

toml::color の制御を変更 #

toml11 v3では、出力に色を付けるかどうかに toml::colorize というマニピュレータを、 toml::color::enable/disable と並列で使用していました。

マニピュレータはストリームごとに色を付けるかどうかを決定できるものでしたが、 v4でストリームを使用する頻度が下がったことと、内部で使用する std::ios_base::xalloc がC++11ではスレッドセーフではないことなどから、 toml::color::enable/disable のみを使用するようにし、 toml::colorize を削除しました。

破壊的でない変更 #

parse_strの追加 #

toml11 v3では、文字列そのものを取るtoml::parse関数はありませんでした。 なので文字列をパースする際にはstd::istringstreamを使う必要がありました。

これは不便なので、toml::parse_strを追加し、文字列を直接パース出来るようにしました。

try_parseの追加 #

toml11 v3では、パーサはエラーを発見した際にはtoml::syntax_errorを送出していました。

しかし、例外を投げられない環境や、パフォーマンスの都合や記法の都合によって例外を投げたくない場合があります。

toml11 v4では toml::result を使用して、例外を投げずにパース失敗を伝える toml::try_parse を実装しました。

これも必ず例外を投げないというわけではなく、使用している標準ライブラリの内部でのエラー、 例えばメモリ不足によるアロケーション失敗での std::bad_alloc などは送出される可能性があります。

バイト列のパースをサポート #

ファイルなど以外の方法で得られたTOMLコンテンツをパース出来るようにするため、 std::vector<unsigned char> を受け取る toml::parse, toml::try_parse を追加しました。

toml::specの追加 #

toml11 v3では、TOML言語側の新機能は全て取り込み、またTOML言語の新バージョンに導入されることが決定した機能も マクロ TOML11_USE_UNRELEASED_TOML_FEATURES によって制御していました。

これは、toml11 v3を開発していた時点では TOML言語は0.4.0から0.5.0で、1.0.0に到達していなかったためです。

最新のTOML言語仕様に全てのユーザーが詳しいわけではないため、 古い言語使用に基づいたエラーメッセージを表示すると、コミュニティ全体を混乱させてしまいます。 よって、v1.0.0に達するまでは、できる限り素早く新しい言語仕様を提供し、かつユーザーにもアップデートを促す必要がありました。

しかし、現在のTOML言語仕様はv1.0.0です。 そのため、TOML v1.1.0がリリースされた後でもv1.0.0を使用する、という選択肢に気を配る必要が生じました。

よって、より柔軟にTOML言語仕様を選択できるよう、toml::specを導入して、TOML言語バージョンを実行時に変更できるようにしました。

また、toml::specでは言語機能ごとにフラグを設定し、特定の言語機能のみを試すこともできるようにしました。

これは、toml11 v4特有の言語拡張でも使用します。

フォーマット情報の追加 #

toml11 v3では、文字列を除いてフォーマット情報が保存されず、シリアライズ時に考慮できるのは幅と精度だけでした。

しかし、これでは16進数整数がシリアライズ時に10進数になってしまったり、確実にinline tableにする方法がありませんでした。

toml11 v4では、全てのTOML型にフォーマット情報(integer_format etc)を追加し、 パース時とシリアライズ時に考慮するようにしました。

これによって、16進数整数や、インラインテーブル等のフォーマット情報をより細かく、値ごとに設定できるようになりました。

デフォルトでコメントを維持するよう変更 #

toml11 v3では、デフォルトではコメントがパースされず、シリアライズもされませんでした。

これは、コメントが後期に導入された機能で、特別なハックによって読み込まれていたためです。

toml11 v4では、デフォルトでコメントをパースし、保存し、シリアライズするようになりました。

また、パーサの実装も大幅に変更され、コメントが他の要素と同様にパースされるようになりました。

single_include/toml.hpp の追加 #

toml11は多機能なライブラリなので、開発効率のために機能ごとに異なるヘッダファイルを持っています。 ですが、これはインストールにある程度の手間が必要ということでもあります。

そこで、toml11 v4から全てのヘッダファイルを適切な順序で結合した single_include/toml.hpp ファイルを追加し、 単一のファイルで完結するライブラリをコピーするだけで導入できるようにしました。

コンパイル済みライブラリを選択可能に #

toml11は template を多用しているため、コンパイル時間が長くなります。

toml11 v4では、できるだけコンパイル可能な関数を増やし、それらを先にライブラリとしてコンパイルできるようにしました。

これにより、大規模な開発で使用する際にコンパイル時間を短くできると期待できます。

リファレンス・ドキュメントの追加 #

これまでは、READMEにすべてのfeatureを記載しており、関数の詳細な定義を示すリファレンスや、また日本語での資料などがありませんでした。

toml11 v4では、リファレンスを追加したドキュメントを同梱し、また日本語・英語両方で同一の内容を記載します。

ただし、ライブラリ作者は日本語母語話者であるため、日本語の内容を第一とし、英語の内容がそれと異なっていた場合は日本語の内容が正しいものとします。