15 KiB
+++ title = "changelog" type = "docs" weight = 4 +++
Change Log
v4.0.1
Fixed
sematic_version::{major, minor}と<sys/sysmacro.h>内で定義されるマクロの衝突を解消discard_commentsのoperator<<の定義を修正format_locationを使用した際に最初の空行が出ない問題を解決- 改行文字のみを含む行を指す
source_locationでエラーメッセージを生成した際に、同じ行が二回表示される問題を解決 README.md内のリンクを修正example/unicodeのREADMEのタイトルを修正
Added
mainに変更があったとき、single_include/toml.hppを自動生成するようCIを設定
v3からv4への変化
破壊的変更
toml::basic_valueのtemplate引数を変更
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]({{< ref "/docs/reference/types.md">}})
を参照してください。
toml::basic_valueのstd::initializer_listサポートを削除
toml11 v3では、 toml::value に std::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では、文字列が basic か literal かの情報を保持するため、
格納する文字列型に 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_underlineをtoml::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_infoとmake_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では、リファレンスを追加したドキュメントを同梱し、また日本語・英語両方で同一の内容を記載します。
ただし、ライブラリ作者は日本語母語話者であるため、日本語の内容を第一とし、英語の内容がそれと異なっていた場合は日本語の内容が正しいものとします。