doc: add reference manual

This commit is contained in:
ToruNiina
2024-06-15 19:27:42 +09:00
parent 7210e708a6
commit 64197caa05
77 changed files with 18139 additions and 0 deletions

View File

@@ -0,0 +1,313 @@
+++
title = "changelog"
type = "docs"
weight = 4
+++
# Change Log
# v3からの変化
## 破壊的変更
### `toml::basic_value`の`template`引数を変更
toml11 v3では、`toml::basic_value`はコメントコンテナ、テーブル型コンテナ、配列型コンテナをそれぞれ取っていました。
```cpp
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`を受け取り、より多くの型を変更可能にします。
```cpp
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` を配列やテーブルで初期化する際により直観的な書き方が可能でした。
```cpp
// toml11 v3
toml::value v{1,2,3,4,5};
toml::value v{ {"a", 42}, {"b", "foo"} };
```
しかし、これは同時に以下のような問題を引き起こしました。
一つ目は、1要素の配列と通常の値の区別がつかず、常に配列になってしまうことです。
```cpp
// toml11 v3
toml::value v{1}; // 1 ではなく [1,] になってしまう
```
統一初期化記法が普及した現在、これは非常に不便です。
二つ目は、値が全て文字列のテーブルと、ネストされた配列の区別がつかないことです。
```cpp
// 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` を指定する必要があります。
```cpp
// 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` の薄いラッパーを使用していました。
```cpp
// 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` 型を用意し、値とペアで格納することにしました。
```cpp
// 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`の引数が複雑になっていました。
```cpp
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`の引数を簡略化しました。
```cpp
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では、リファレンスを追加したドキュメントを同梱し、また日本語・英語両方で同一の内容を記載します。
ただし、ライブラリ作者は日本語母語話者であるため、日本語の内容を第一とし、英語の内容がそれと異なっていた場合は日本語の内容が正しいものとします。

View File

@@ -0,0 +1,101 @@
+++
title = "features"
type = "docs"
weight = 2
bookCollapseSection = true
+++
# features
ここでは、toml11が提供する主な機能について、例を挙げながら説明します。
## [ファイル・文字列をパースする](parsing_files)
ファイルや文字列をパースする関数と、それが出力するエラーの扱い方について説明します。
以下の内容を含みます。
- ファイルをパースする
- 文字列をパースする
- バイト列をパースする
- 例外を投げずにファイルをパースする
- 例外を投げずに文字列をパースする
- 例外を投げずにバイト列をパースする
## [`toml::value`から値を取り出す](value)
`toml::value`が持つデータの型を調べ、取り出す方法、型変換を行う方法について説明します。
以下の内容を含みます。
- メンバ関数を使って値の型を調べる
- メンバ関数を使って値にアクセスする
- コメントにアクセスする
- インラインテーブル・ドットキーの取り扱い
- 日付情報の取り扱い
- `toml::get<T>`を使って変換する
- `toml::get_or`を使って失敗時の値を指定する
- `toml::find<T>`を使って検索と変換を行う
- `toml::find_or`を使って失敗時の値を指定する
- ユーザー定義型との変換を定義する
- `toml::visit`で関数を適用する
- `toml::value`を構築する
## [エラーメッセージを作る](error_message)
`toml::value`の値を使って、TOMLファイル中の位置情報つきのエラーメッセージを生成する方法について説明します。
以下の内容を含みます。
- `toml::value` の位置情報を取り出す
- エラーメッセージを構築する
- 出力に色を付ける
## [TOMLファイルを出力する](serialize)
`toml::value`の値をフォーマットする方法と、可能なフォーマット指定について説明します。
以下の内容を含みます。
- `toml::value`の値ごとにフォーマットを指定する
- `toml::value`をフォーマットして文字列化する
## [`toml::value`の型を変更する](configure_types)
`toml::value`が格納する型(`integer_type``table_type`をカスタマイズする方法について説明します。
以下の内容を含みます。
- `type_config`の定義
- `ordered_type_config`を使用する
- コメントを保存しないようにする
- `std::deque`などの異なるコンテナを使用する
- `boost::multiprecision`などの異なる数値型を使用する
## [TOMLリテラル](literal)
C++内にTOMLファイルを埋め込むための`_toml`リテラルについて説明します。
以下の内容を含みます。
- TOMLリテラルを使用する
## [TOML言語バージョン](toml_spec)
toml11がサポートするTOML言語のバージョン、主にTOML-v1.1.0で追加された言語機能を制御する方法について説明します。
以下の内容を含みます。
- TOML言語の1.1.0を使用する
- TOML言語の1.1.0の一部の機能のみ使用する
## [TOML言語拡張](extension)
toml11独自のTOML言語拡張について説明します。
以下の内容を含みます。
- `null` をサポートする
- 浮動小数点数の16進数フォーマットをサポートする
- 数値に単位を付けられるようにする

View File

@@ -0,0 +1,213 @@
+++
title = "configuring types"
type = "docs"
weight = 50
+++
# 型をカスタマイズする
`toml::value``integer_type` として `std::int64_t` を、
`table_type` として `std::unordered_map<key_type, value_type>` を使用します。
しかし、場合によっては `boost::multiprecision::int128_t` や、 `std::map` を使用したい場合もあります。
そのため、 `toml::value``template` 引数を取って格納する型を変えられるように実装されています。
`std::string` が実際には `std::basic_string<char, std::char_traits<char>, std::allocator<char>>`
エイリアスであるように、 `toml::value` は実際には `toml::basic_value<toml::type_config>` のエイリアスです。
ここでは、 `toml::type_config` が持つ型と、異なる `config` 型を定義する方法を説明します。
## `type_config`
`type_config` は、以下のメンバ型と`static`メンバ関数を持つクラスです。
```cpp
namespace toml
{
struct type_config
{
using comment_type = preserve_comments;
using boolean_type = bool;
using integer_type = std::int64_t;
using floating_type = double;
using string_type = std::string;
template<typename T>
using array_type = std::vector<T>;
template<typename K, typename T>
using table_type = std::unordered_map<K, T>;
static result<integer_type, error_info>
parse_int(const std::string& str, const source_location src, const std::uint8_t base);
static result<floating_type, error_info>
parse_float(const std::string& str, const source_location src, const bool is_hex);
};
}
```
`toml::basic_value<TypeConfig>` は、格納する `boolean_type``TypeConfig::boolean_type`
格納する `integer_type``TypeConfig::integer_type` 、のようにして定義しています。
また、 `array_type``TypeConfig::array_type<toml::basic_value<TypeConfig>>`
`table_type``TypeConfig::table_type<key_type, toml::basic_value<TypeConfig>>`
定義されます。
これらのメンバ型とメンバ関数を定義したクラスを `toml::basic_value`
渡すことで、その `toml::basic_value` が持つ型を変更できます。
`parse_int``parse_float` は、数値型を独自実装のものに変更した際にパース方法を提供するための関数です。
これらの関数には `0x` などのprefixと桁区切りの `_` が取り除かれた文字列、
例えば `123456``DEADBEEF` が渡されます。
`base` には `10`, `16`, `8`, `2` のいずれかが渡されます。
これらを使って `integer_type``floating_type` をパース出来るような関数を渡してください。
デフォルト実装として、`toml::read_int``toml::read_float` が提供されています。
```cpp
static result<integer_type, error_info>
parse_int(const std::string& str, const source_location src, const std::uint8_t base)
{
return toml::read_int<integer_type>(str, src, base);
}
static result<floating_type, error_info>
parse_float(const std::string& str, const source_location src, const bool is_hex)
{
return toml::read_float<floating_type>(str, src, is_hex);
}
```
`read_int``istream` を使用し、16進と8進の場合は `std::hex`
`std::oct` を使用します。2進の場合は掛け算と足し算で実装されています。
これらをサポートしている型であれば、 `read_int` をそのまま使用できます。
`read_float``istream` を使用します。
16進浮動小数点数は `double``float` の場合しかサポートされておらず、
それ以外の型のときに呼ばれると常にパースエラーを返す実装になっているので、
もし浮動小数点数型をこれら以外の型にし、かつ `hexfloat` を使用する場合は、
それを実装してください。 `hexfloat` を使用しないのであれば、実装する必要はありません。
## テーブル内の値の順序を維持する
デフォルトの `toml::type_config` の他に、 `toml::ordered_type_config` が提供されています。
これは、 `table_type` を [ordered_map]({{< ref "docs/reference/ordered_map" >}}) に変更したものです。
これを使用したものを `toml::ordered_value` 、その配列型とテーブル型のエイリアスを
`toml::ordered_array``toml::ordered_table` と定義しています。
`toml::parse(...)``toml::parse<toml::ordered_type_config>(...)` として呼び出すことで、
`toml::ordered_value` を使用することができます。
## コメントを保存しない
`type_config``comment_type` でコメントを保存するコンテナを定義しています。
コメントに特に情報がなく、パースせずに捨ててしまっていい場合は、 `comment_type`
`toml::discard_comments` を指定してください。
```cpp
struct wo_comment_config
{
using comment_type = toml::discard_comments; // XXX
using boolean_type = bool;
using integer_type = std::int64_t;
using floating_type = double;
using string_type = std::string;
template<typename T>
using array_type = std::vector<T>;
template<typename K, typename T>
using table_type = std::unordered_map<K, T>;
static result<integer_type, error_info>
parse_int(const std::string& str, const source_location src, const std::uint8_t base)
{
return toml::read_int<integer_type>(str, src, base);
}
static result<floating_type, error_info>
parse_float(const std::string& str, const source_location src, const bool is_hex)
{
return toml::read_float<floating_type>(str, src, is_hex);
}
};
```
## 配列に`std::vector`以外のコンテナを使用する
TOML配列の実装に`vector`以外のコンテナ(例:`std::deque`)を使用するには、
`array_type` を以下のように変更してください。
また、テーブル型のコンテナに `unordered_map` 以外のコンテナ(例:`std::map`)を使用するには、
`table_type` を以下のように変更してください。
```cpp
struct deque_map_config
{
using comment_type = toml::preserve_comments;
using boolean_type = bool;
using integer_type = std::int64_t;
using floating_type = double;
using string_type = std::string;
template<typename T>
using array_type = std::deque<T>; // XXX
template<typename K, typename T>
using table_type = std::map<K, T>; // XXX
static result<integer_type, error_info>
parse_int(const std::string& str, const source_location src, const std::uint8_t base)
{
return toml::read_int<integer_type>(str, src, base);
}
static result<floating_type, error_info>
parse_float(const std::string& str, const source_location src, const bool is_hex)
{
return toml::read_float<floating_type>(str, src, is_hex);
}
};
```
## 数値型に `boost::multiprecision` を使用する
`boost::multiprecision::cpp_int``boost::multiprecision::cpp_bin_float_oct`
を使用することで、より幅の広い整数型とより精度の良い浮動小数点数型を使用することができます。
これらの型はストリーム演算子を実装しているため、デフォルト実装の `read_int`
`read_float` をそのまま使用できます。
```cpp
struct large_num_config
{
using comment_type = toml::preserve_comments;
using boolean_type = bool;
using integer_type = boost::multiprecision::cpp_int;
using floating_type = boost::multiprecision::cpp_bin_float_oct;
using string_type = std::string;
template<typename T>
using array_type = std::vector<T>;
template<typename K, typename T>
using table_type = std::unordered_map<K, T>;
static toml::result<integer_type, toml::error_info>
parse_int(const std::string& str, const toml::source_location src, const std::uint8_t base)
{
return toml::read_int<integer_type>(str, src, base);
}
static toml::result<floating_type, toml::error_info>
parse_float(const std::string& str, const toml::source_location src, const bool is_hex)
{
return toml::read_float<floating_type>(str, src, is_hex);
}
};
```

View File

@@ -0,0 +1,237 @@
+++
title = "error message"
type = "docs"
weight = 30
+++
# エラーメッセージを出力する
toml11は `toml::parse``toml::get<T>/find<T>`, `as_integer()` などから
ファイル内の位置情報を含んだエラーメッセージを出力します。
例えば、パース時に整数の文法エラーを発見した場合、
```
[error] bad integer: `_` must be surrounded by digits
--> internal string at line 64 in file main.cpp
|
1 | a = 123__456
| ^-- invalid underscore
Hint: valid : -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755
Hint: invalid: _42, 1__000, 0123
```
あるいは実際に格納されている型と異なる型を要求した場合
```
[error] toml::value::as_string(): bad_cast to string
--> input.toml
|
1 | a = 123_456
| ^^^^^^^-- the actual type is integer
```
toml11は `toml::value` からこのようなエラーメッセージを作成する方法を提供します。
この機能を利用することで、TOMLの文法エラーだけでなく、
例えば正の値でなければならないところに負数が現れた場合などの
アプリケーション固有のエラーメッセージを、TOMLファイル内の位置を指摘しながら
ユーザーに伝えられるということです。
## `toml::value` の位置情報からエラーメッセージを作成する
`toml::value` はそれがパースされた位置の情報を持っています。
その情報は `toml::source_location` にまとめられ、`toml::value::location()` で取得できます。
```cpp
const toml::value& a = input.at("a");
const toml::source_location src = a.location();
```
ファイルを `toml::parse` でパースした場合、そのTOMLファイル名と行数が保存されています。
`toml::parse_str` でパースした場合TOMLファイル名はありませんが、代わりに
`toml::parse_str` を呼び出したC++ソースコードのファイル名と行数がTOMLファイル名として保存されています。
このページの最初の例は `toml::parse_str` から出力された例でした。
ファイル名の部分に注目してください。
詳細は [reference]({{<ref "/docs/reference/source_location">}}) を参照してください。
`toml::source_location` または `toml::value` とそれに付随するエラーメッセージを
`toml::make_error_info` に渡すことで、エラー情報を構築できます。
これを`toml::format_error` に渡すと、エラーメッセージが `std::string` にフォーマットされます。
```cpp
const toml::value& a = input.at("a");
if(a.as_integer() < 0)
{
const toml::error_info err = toml::make_error_info(
"positive integer is required", // エラーのタイトル
a, "but got negative value" // 値の横に書くメッセージ
);
std::cerr << toml::format_error(err) << std::endl;
}
```
これは以下のようになります。
```
[error] positive integer is required
--> input.toml
|
1 | a = -123456
| ^^^^^^^-- but got negative value
```
最後に補足をつけ足すこともできます。これはインデントされません。
```cpp
const toml::value& a = input.at("a");
if(a.as_integer() < 0)
{
const toml::error_info err = toml::make_error_info(
"positive integer is required", // エラーのタイトル
a, "but got negative value", // 値の横に書くメッセージ
"Hint: `a` means length of the data" // 補足
);
std::cerr << toml::format_error(err) << std::endl;
}
```
```
[error] positive integer is required
--> input.toml
|
1 | a = -123456
| ^^^^^^^-- but got negative value
Hint: `a` means length of the data
```
{{<hint info>}}
`toml::value` からファイル内の行を出力できるのは、
パースしたファイルが文字列としてメモリの中に残されているからです。
パースした文字列はその全体が `std::shared_ptr``toml::value` に共有されています。
コピーしてもファイル文字列全体がコピーされることはありません。
また、そのファイルをパースして構築された `toml::value` が全てデストラクトされた時点で、
ファイル情報もメモリ上から解放されます。
ですので、アプリケーションで使用する際には、 `toml::value` を直接保存するのではなく
読み込み中に必要な値を全て取り出して、変換した値を保存した方がよいでしょう。
{{</hint>}}
## 文字列に色を付ける
エラーメッセージにはANSIエスケープコードを使って色を付けることができます。
`TOML11_COLORIZE_ERROR_MESSAGE` をコンパイル時に定義していれば、
toml11の出力するエラーメッセージはデフォルトで色が付くようになります。
そうでない場合は、 `toml::color::enable()` を呼び出すことにより、それ以降で出力される
エラーメッセージには色が付くようになります。
逆に出力先がコンソールではないなどの理由で色をつけたくない場合は、
`toml::color::disable()` を呼び出してください。
その時点で色が付くようになっているかどうかは、
`toml::color::should_color()` の返り値で判定できます。
詳細は [reference]({{<ref "docs/reference/color">}}) を参照してください。
また、エラーのタイトルやエラーメッセージ、補足にはデフォルトで色が付きませんが、
`toml::color` にあるマニピュレータを使って色を付けることも可能です。
```cpp
std::ostringstream oss;
oss << toml::color::red << "but got negative value";
const toml::error_info err = toml::make_error_info(
"positive integer is required", // Error title
a, oss.str(), // Message next to the value
"Hint: `a` means length of the data" // Supplementary message
);
```
こちらも、詳細は [reference]({{<ref "docs/reference/color">}}) を参照してください。
## エラーメッセージのprefixを`[error]`から変更する
エラーには種類があり、デフォルトの `[error]` ではよくない場合もあるでしょう。
`toml::format_error` では、 `toml::error_info` の前に `std::string` を取って、それを
`[error]` の代わりに出力することができます。
例えば、
```cpp
const toml::value& a = input.at("a");
if(a.as_integer() < 0)
{
const toml::error_info err = toml::make_error_info(
"positive integer is required", // エラーのタイトル
a, "but got negative value" // 値の横に書くメッセージ
);
std::ostringstream prefix;
prefix << toml::color::bold << toml::color::yellow << "[warn]";
std::cerr << toml::format_error(prefix.str(), err) << std::endl;
return 0;
}
else
{
return a.as_integer()
}
```
このようにすると、 `[warn]` から始まる警告を出力することができます。
他にも、`toml::format_error` に直接 `error_info` の構成要素を渡すことで、
`[error]` なしのエラーメッセージを作成できます。
```cpp
const toml::value& a = input.at("a");
if(a.as_integer() < 0)
{
std::cerr << toml::format_error(
"[warn] positive integer is required", // エラーのタイトル
a, "but got negative value" // 値の横に書くメッセージ
) << std::endl;
return 0;
}
else
{
return a.as_integer()
}
```
## 複数の `toml::value` を指すエラーメッセージを作成する
アプリケーションの設定では、先に読み込んだ値によって後に読み込んだ値が取れる範囲が変わることがあるでしょう。
そのような場合には、エラーの原因となる別の値を同時に出力したいはずです。
`toml::format_error``toml::make_error_info` は、 `toml::value` とそれに対応するエラーメッセージ `std::string` のペアを任意個取ることができます。
```cpp
std::cerr << toml::format_error(
"[error] invalid range",
a, "minimum value is defined here",
b, "maximum value is defined here",
c, "and it exceeds the range"
) << std::endl;
```
こちらも末尾に補足を追加することができます。
```cpp
std::cerr << toml::format_error(
"[error] invalid range",
a, "minimum value is defined here",
b, "maximum value is defined here",
c, "and it exceeds the range",
"Hint: all the value must be in the range, [a, b)"
) << std::endl;
```
`toml::value` または `toml::source_location` を渡した場合、必ずそれに関する
エラーメッセージが続く必要があります。
そうしない場合、非常にわかりにくいコンパイルエラーになります。

View File

@@ -0,0 +1,136 @@
+++
title = "extension"
type = "docs"
weight = 80
+++
# TOML言語拡張
TOML言語は現在 v1.0.0 が最新版ですが、その後もいくつかの新機能が議論の末マージされ、
v1.1.0に向けて議論が続いています。
そこで議論された機能の中には、有用なケースが少ないと考えられたものや、
提案された際の方向性では導入が難しいもの、導入がされなかったものも多くあります。
toml11では、そのような機能のなかからいくつかを選んで、実験的に実装を行っています。
これらはtoml11ではサポートされていますが、他のパーサではサポートされておらず、また
サポートされる予定もないことに注意してください。
また、これらの機能はデフォルトで使用されない設定になっており、
使用するためには機能フラグをそれぞれ `true` にしなければなりません。
非標準の機能なので、あえて明示的に書かなければ使えないように設計しています。
いくつかの機能は今後TOML言語自体に新機能としてマージされる可能性があります。
もし以下の拡張機能を完全に置き換えられる機能が導入された場合、拡張機能は
本来の機能の実装後にマイナーバージョンアップで削除される可能性があります。
## `null`
TOMLファイル内で値として`null`を使えるようになります。
```
a = null
b = [ 1, 2, 3, null, 5]
```
これを使用するには、 `toml::spec``ext_null_value``true` にします。
パースすると、デフォルト構築した場合と同様の `toml::value_t::empty` となります。
ただし、ファイル内の位置情報は設定されます。
`null` は値の文脈でのみパースされるので、キーに `null` を使用した際はこれまで通り
`"null"` という文字列のキーとして解釈されます。
```cpp
#include <toml.hpp>
int main()
{
toml::spec spec;
spec.ext_null_value = true;
const auto v = toml::parse_str("a = null", spec);
assert(v.at("a").is_empty());
assert(v.at("a").is(toml::value_t::empty));
return 0;
}
```
## 浮動小数点数の16進数フォーマット
TOMLファイル内で浮動小数点数に16進数フォーマットを使用できるようになります。
```
a = 0x1.91eb851eb851fp+1 # 3.14
```
これを使用するには、 `toml::spec``ext_hex_float``true` にします。
フォーマットは `printf``%a/%A` を指定した場合に準拠します。
```cpp
#include <toml.hpp>
int main()
{
toml::spec spec;
spec.ext_hex_float = true;
const auto v = toml::parse_str("a = 0x1.91eb851eb851fp+1", spec);
assert(v.at("a").is_floating());
assert(v.at("a").as_floating() == 3.14);
return 0;
}
```
## 整数・浮動小数点数のsuffix
TOMLファイル内で数値の後ろにsuffixをつけられるようになります。
10進数表記の整数と浮動小数点数で使用できます。
単位を表示するときなどに便利です。
```
a = 86_400_sec
b = 3.1416_rad
c = 10_μm
```
ですが、これらはあくまで単なる `suffix` であり、単位換算は行われません。
単位換算が必要な場合は、ユーザーが `suffix` を参照して実装してください。
これを使用するには、 `toml::spec``ext_num_suffix``true` にします。
数値と接尾辞の間は`_`で区切られている必要があります。
数値部分との区別のため、suffixは数値で始まることはできません。
```
distance = 100_m # valid
distance = 10_0m # invalid
distance = 10_0_m # valid
```
接尾辞は`std::string suffix`としてフォーマット情報に保持されます。
```cpp
#include <toml.hpp>
int main()
{
toml::spec spec;
spec.ext_hex_float = true;
const auto v = toml::parse_str("a = 86_400_sec", spec);
assert(v.at("a").is_integer());
assert(v.at("a").as_integer() == 86400);
assert(v.at("a").as_integer_fmt().suffix == "sec");
return 0;
}
```

View File

@@ -0,0 +1,93 @@
+++
title = "toml literal"
type = "docs"
weight = 60
+++
# `_toml`リテラル
`""_toml`リテラルによって、TOMLファイルをその場でフォーマットできます。
```cpp
#include <toml.hpp>
int main()
{
using namespace toml::literals::toml_literals;
const auto v = "a = 42"_toml;
assert(v.at("a").as_integer() == 42);
return 0;
}
```
改行を含む場合、生文字列リテラルが便利です。
```cpp
#include <toml.hpp>
int main()
{
using namespace toml::literals::toml_literals;
const auto v = R"(
a = 42
b = "foo"
)"_toml;
assert(v.at("a").as_integer() == 42);
assert(v.at("b").as_string() == "foo");
return 0;
}
```
値が単体で書かれていた場合、その値が返されます。
```cpp
#include <toml.hpp>
int main()
{
using namespace toml::literals::toml_literals;
const auto a = "42"_toml;
const auto b = "12:34:56"_toml;
assert(v.at("a").as_integer() == 42);
assert(v.at("b").as_local_time().hour == 12);
assert(v.at("b").as_local_time().minute == 34);
assert(v.at("b").as_local_time().second == 56);
return 0;
}
```
TOMLは数値のみからなるキーを許可しています。
よって、`[1]`はテーブル名として合法です。
`[1]`のようにテーブル定義と配列の区別がつかない場合、テーブル定義が優先されます。
配列として解釈させるには、trailing commaを使用してください。
```cpp
#include <toml.hpp>
int main()
{
using namespace toml::literals::toml_literals;
const auto t = "[1]"_toml; // {1 = {}}
const auto a = "[1,]"_toml; // [1,]
assert(t.is_table());
assert(t.at("1").is_table());
assert(a.is_array());
assert(a.at(0).as_integer() == 1);
return 0;
}
```

View File

@@ -0,0 +1,279 @@
+++
title = "parsing files"
type = "docs"
weight = 10
+++
# ファイル・文字列をパースする
toml11では、`toml::parse``toml::try_parse` を使って、ファイルや文字列、バイト列をパースすることができます。
これらは成功時に `toml::value` を返します。
ファイルは常にテーブルになりますが、返り値が `toml::table` でないことに気を付けてください。
`toml::value` はファイルに関するメタデータを持っており、
`toml::table``std::unordered_map<std::stirng, toml::value>` のエイリアスでしかありません。
メタデータを返すために、 `toml::table` ではなく `toml::value` を返しています。
ファイルのルートに対応する `toml::value` は常に `table_type` を持ちます。
## ファイルをパースする
ファイルをパースする際は、
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}})
または
[`toml::try_parse`]({{< ref "docs/reference/parser#try_parse" >}})
を使います。
### `toml::parse`
#### `std::string`でファイル名を指定する
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}})
は、文字列でファイル名を受け取り、そのファイルを開いてパースします。
以下のサンプルは、`input.toml`というファイルをパースし、`title`という変数を文字列として取り出し、出力するコードです。
```cpp
#include <toml.hpp>
#include <iostream>
int main()
{
const toml::value input = toml::parse("input.toml");
std::cout << input.at("title").as_string() << std::endl;
return 0;
}
```
#### `std::istream`で入力ストリームを指定する
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}})
には、`std::istream`を渡すことも可能です。
その際、ファイル名の情報がなくなるため、エラーメッセージ中では `"unknown file"` となります。
これを避けるため、 `std::istream` を取る場合は第二引数に `std::string` でファイル名を取ることもできます。
`std::ifstream` 以外にも、 `std::istringstream` 等の別の`istream`を受け取ることができます。
ただし、呼び出した時点で内容が全て読み込める必要があります。
```cpp
#include <toml.hpp>
#include <iostream>
int main()
{
std::string filename("input.toml");
std::ifstream ifs(filename);
const toml::value input = toml::parse(ifs, filename);
std::cout << input.at("title").as_string() << std::endl;
return 0;
}
```
#### `std::filesystem::path`でファイルを指定する
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}})
には、`std::filesystem::path`を渡すことも可能です。
当然ですが、`<filesystem>`がサポートされるC++17以降でなければ使用できません。
#### `FILE*`でファイルを指定する
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}})
には、`FILE*`を渡すことも可能です。
この場合も、`std::istream`のときと同様に、第二引数に文字列でファイル名を与える必要があります。
`FILE*`を渡した場合、ファイルの読み込みに失敗した際には`errno`が報告されます。
#### エラー時の挙動
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}})
は、文法エラーを発見した場合
[`toml::syntax_error`]({{<ref "docs/reference/parser#syntax_error">}})
を送出します。
[`toml::syntax_error`]({{<ref "docs/reference/parser#syntax_error">}})
は、
[`toml::exception`]({{<ref "docs/reference/exception">}})
から派生しており、またそれは`std::exception`から派生します。
よって、
[`toml::syntax_error`]({{<ref "docs/reference/parser#syntax_error">}})
からは `what()` メンバ関数を使ってエラーメッセージを取り出すことができます。
また、
[`toml::syntax_error`]({{<ref "docs/reference/parser#syntax_error">}})
[`std::vector<toml::error_info>`]({{<ref "docs/reference/error_info">}})
を持っており、`errors()`メンバ関数を使ってそれにアクセスすることもできます。
`toml::parse` はごく簡単なエラーならスキップして復帰し、複数のエラーを報告しようと努めます。
数値のフォーマットエラー程度なら復帰できることが多いですが、
配列やテーブルの中のエラーは復帰できずに似たようなエラーを複数回報告することもあります。
冗長であると感じた場合は、 `std::vector<toml::error_info>``front()` だけを使用するようにすると、
確実に問題のある個所に関するメッセージを得られます。
```cpp
#include <toml.hpp>
int main()
{
// parse
try {
const toml::value input = toml::parse("input.toml");
std::cout << input.at("title").as_string() << std::endl;
} catch(const toml::syntax_error& err) {
// 全てのエラーを報告
std::cerr << err.what() << std::endl;
// 最初のエラーのみ報告
std::cerr << err.errors().front() << std::endl;
}
}
```
### `toml::try_parse`
`toml::parse` は失敗時に例外を送出しますが、 `toml::try_parse` は失敗時に例外を投げません。
その代わり、返り値が `toml::value` ではなく [`toml::result<toml::value, std::vector<toml::error_info>>`]({{<ref "docs/reference/result#result">}}) になります。
[`result`]({{<ref "docs/reference/result#result">}}) 型は成功値または失敗値のどちらかを持つ型です。
Rustの `Result` やHaskellの `Either` に相当します。
```cpp
#include <toml.hpp>
int main()
{
const auto parse_result = toml::try_parse("input.toml");
if(parse_result.is_ok())
{
std::cout << parse_result.unwrap().at("title").as_string() << std::endl;
}
else
{
std::cerr << parse_result.unwrap_err().at(0) << std::endl;
}
return 0;
}
```
[`result`]({{<ref "docs/reference/result#result">}}) 型がどちらの値を保持しているかは
`is_ok()`, `is_err()` 関数を使って確認できます。
また、 `unwrap()`, `unwrap_err()` によって成功値、失敗値をそれぞれ取り出せます。
`unwrap` が失敗した場合は、 `bad_result_access` 例外が送出されます。
`as_ok()``as_err()` 関数を使用すると、失敗時には例外が送出されず、未定義動作となります。
{{<hint warning>}}
`try_parse``syntax_error``file_io_error` を投げず、同じ `toml::error_info`
`result` の失敗型として返しますが、絶対に例外を投げないわけではありません。
標準ライブラリ内部でエラーが発生した場合、例えばメモリ不足の際に `vector`
`allocate` が失敗した場合などには `std::bad_alloc` が送出されますが、
`toml::try_parse` はこれが送出された場合は `catch` せずに通します。
そのため、それらのような標準ライブラリの内部で発生する例外は送出される恐れがあります。
{{</hint>}}
## 文字列をパースする
### `toml::parse_str`
[`toml::parse_str`]({{<ref "docs/reference/parser#parse_str">}})
は、ファイル名ではなくパースする文字列そのものを受け取ります。
また、エラーメッセージのTOMLファイルの名前に相当する部分には、`std::source_location`
相当のコンパイラ拡張機能が使用できる場合、 `parse_str` を呼び出したC++ファイルの名前と行数が代わりに使用されます。
```cpp
#include <toml.hpp>
#include <iostream>
int main()
{
const toml::value input = toml::parse_str("title = \"parse_str\"");
std::cout << input.at("title").as_string() << std::endl;
return 0;
}
```
### `toml::try_parse_str`
[`toml::try_parse_str`]({{<ref "docs/reference/parser#try_parse_str">}})
は、 `parse_str` と同じくパースする文字列そのものを受け取り、
`try_parse` と同じくエラーの報告に
[`toml::result`]({{<ref "docs/reference/result#result">}})
を使用します。
```cpp
#include <toml.hpp>
#include <iostream>
int main()
{
const auto parse_result = toml::try_parse_str("title = \"parse_str\"");
if(parse_result.is_ok())
{
std::cout << parse_result.unwrap().at("title").as_string() << std::endl;
}
else
{
std::cerr << parse_result.unwrap_err().at(0) << std::endl;
}
return 0;
}
```
## バイト列をパースする
ファイルではなくバイト列をパースすることも可能です。
UTF-8でエンコードされている必要があるため、`unsigned char`を使っています。
### `toml::parse(std::vector<unsigned char>)`
挙動は [`toml::parse`]({{<ref "docs/reference/parser#parse">}}) と同一です。
バイト列をパースする際は、 `filename` を要求します。
```cpp
#include <toml.hpp>
#include <iostream>
int main()
{
std::vector<unsigned char> bytes{/* ... */};
const toml::value input = toml::parse(bytes, "internal bytes");
std::cout << input.at("title").as_string() << std::endl;
return 0;
}
```
### `toml::try_parse(std::vector<unsigned char>)`
挙動は [`toml::try_parse`]({{<ref "docs/reference/parser#try_parse">}}) と同一です。
バイト列をパースする際は、 `filename` を要求します。
```cpp
#include <toml.hpp>
#include <iostream>
int main()
{
std::vector<unsigned char> bytes{/* ... */};
const auto parse_result = toml::try_parse(bytes, "internal bytes");
if(parse_result.is_ok())
{
std::cout << parse_result.unwrap().at("title").as_string() << std::endl;
}
else
{
std::cerr << parse_result.unwrap_err().at(0) << std::endl;
}
return 0;
}
```

View File

@@ -0,0 +1,234 @@
+++
title = "serializing values"
type = "docs"
weight = 40
+++
# TOMLファイルを出力する
`toml::format` を使うと、 `toml::value` を文字列にすることができます。
```cpp
#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>` を渡すことができます。
```cpp
#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`のリファレンス]({{< ref "/docs/reference/value" >}})を、
フォーマット情報クラスの完全なリストと詳細は
[formatのリファレンス]({{< ref "/docs/reference/format" >}})を
参照してください。
### 整数のフォーマットを指定する
整数は、基数と幅、そして `_` の位置を指定することができます。
`hex`, `oct`, `bin` のとき、指定された幅に達するまでゼロで埋められます。
`dec` の場合は幅指定はスペースを追加しますが、これはパースされません。
```cpp
#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]({{< ref "/docs/reference/format#integer_format" >}}) を参照してください。
### 配列を単一行・複数行にする
配列には、 `toml::array_format::oneline``toml::array_format::multiline` を指定できます。
```toml
# 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` が選択できます。
{{<hint warning>}}
インデントに使用する文字種は統一してください。
一つのファイル内でインデントに異なる文字種が指定された場合、結果は未規定になります。
何らかのインデントがされますが、全ての箇所で文字種やインデントの深さは不定となります。
{{</hint>}}
また、 `array` の要素が全て `table_type` を持つ場合、
`toml::array_format::array_of_tables` が指定できます。
`array_of_tables` を指定せずに `multiline` にした場合、テーブルはインラインテーブルになります。
```toml
# 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]({{< ref "/docs/reference/format#array_format" >}}) を参照してください。
### テーブルをインラインテーブルにする
テーブルをインラインテーブルにする際は `toml::table_format::oneline` を指定します。
通常のテーブルにする際は、 `toml::table_format::multiline` を指定します。
```toml
oneline = {a = 42, b = "foo"}
[multiline]
a = 42
b = "foo"
```
TOML v1.1.0ではインラインテーブル内での改行が許可されますが、その場合は
`toml::table_format::multiline_oneline` とします。
これは、後述するTOMLバージョン指定で対応する機能フラグが`true`になっていない限り無視されます。
```toml
multiline_oneline = {
a = 42,
b = "foo"
}
```
詳細は、[reference]({{< ref "/docs/reference/format#table_format" >}}) を参照してください。
## TOML言語バージョンを指定して出力する
TOML v1.1.0で許可されたインラインテーブル内の改行や`\x`エスケープシーケンスのように、
TOMLバージョンによって使用できない言語機能があります。
`toml::format` は最後の引数に `toml::spec` を取ることができます。
これにより、シリアライズ時に使用するTOMLのバージョンを指定することができます。
特に、 `toml::parse``toml::spec` を使用して新機能を使用した場合は、
パースした値がそのバージョンでしか使えないフォーマット情報を持つ場合があるので、
`toml::format` にも同じ `toml::spec` を渡すことを忘れないようにしてください。
```cpp
#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;
}
```

View File

@@ -0,0 +1,116 @@
+++
title = "toml spec"
type = "docs"
weight = 70
+++
# TOML言語バージョン
[`toml::spec`]({{< ref "docs/reference/spec#tomlspec" >}})
によって、 `toml::parse``toml::format` で使用するTOML言語のバージョンや、個別の機能フラグを指定することができます。
## TOMLのバージョンを指定する
[`toml::spec`]({{< ref "docs/reference/spec#tomlspec" >}})
[`toml::semantic_version`]({{< ref "docs/reference/spec#tomlsemantic_version" >}})
から構築できます。
```cpp
#include <toml.hpp>
int main()
{
toml::spec spec(toml::semantic_version(1, 1, 0));
return 0;
}
```
ですがこれは長いので、`toml::spec::v()`関数が用意されています。
```cpp
#include <toml.hpp>
int main()
{
toml::spec spec = toml::spec::v(1, 1, 0);
return 0;
}
```
特に指定しない場合、デフォルトの値で構築する `toml::spec::default_version()` が使用されます。
デフォルトの値はtoml11のバージョンによって変わりますが、その時点でリリースされているTOML言語の最新バージョンに追従します。
v4.0.0現在、TOML v1.1.0はまだリリースされていないため、デフォルトのTOMLバージョンはv1.0.0です。
{{<hint warning>}}
TOML v1.1.0の一部の機能にはかなり長い議論が続いており、まだ差し戻される可能性があります。
実際に差し戻された場合、toml11はマイナーバージョンアップでそれらの機能を削除、もしくは対応するそれ以降のバージョンに移動します。
そのような意味で、将来のバージョンに関する機能は全て不安定なものと考えてください。
{{</hint>}}
### バージョン指定でパースする
[`toml::parse`]({{< ref "docs/reference/parser" >}})
のオーバーロードは、ファイル名に続いて`toml::spec`を受け取ります。
これによって、使用するTOMLバージョンを変更できます。
```cpp
#include <toml.hpp>
int main()
{
toml::value input = toml::parse("input.toml", toml::spec::v(1, 1, 0));
return 0;
}
```
### バージョン指定でシリアライズする
[`toml::format`]({{< ref "docs/reference/serializer" >}})
のオーバーロードは、 `toml::value` に続いて `toml::spec` を受け取ります。
これによって、使用するTOMLバージョンを変更できます。
```cpp
#include <toml.hpp>
int main()
{
toml::value v = toml::parse("input.toml", toml::spec::v(1, 1, 0));
std::cout << toml::format(v, toml::spec::v(1, 1, 0)) << std::endl;
return 0;
}
```
もしフォーマット変数などによって指定されているフォーマットが渡された `toml::spec`
では許可されていないものだった場合、指定は無視されて他のフォーマットにフォールバックされます。
## TOMLに追加された新機能を個別に指定する
TOMLのバージョンアップで追加された機能は複数あり、そのうちの一部だけを有効にすることが可能です。
```cpp
#include <toml.hpp>
int main()
{
toml::spec spec = toml::spec::v(1, 0, 0);
// インラインテーブル内での改行を許可
spec.v1_1_0_allow_newlines_in_inline_tables = true;
toml::value input = toml::parse("input.toml", spec);
return 0;
}
```
全てのフラグのリストは、
[`toml::spec`]({{< ref "docs/reference/spec#tomlspec" >}})
を参照してください。

View File

@@ -0,0 +1,828 @@
+++
title = "getting values"
type = "docs"
weight = 20
+++
# 値を取り出す
ここでは、 `toml::value` が格納している値にアクセスする方法を説明します。
## メンバ関数を使って値にアクセスする
### `is_something` と `as_something`
`toml::value``is_boolean()``is_integer()` などのメンバ関数を持っており、
これらを使うと持っている型を調べることができます。
また、 `as_boolean()`, `as_integer()` などのメンバ関数も持っており、
これらを使ってその型にアクセスすることができます。
完全なリストは [`toml::value` のリファレンス]({{<ref "docs/reference/value#is_xxx">}}) を参照してください。
```cpp
toml::value v = /* ... */;
if(v.is_integer())
{
std::cout << v.as_integer() << std::endl;
}
```
指定された値と異なる型が格納されていた場合、 [`toml::type_error`]({{<ref "docs/reference/value#tomltype_error">}}) が送出されます。
その `what()` は以下のようなメッセージを含みます。
```
[error] toml::value::as_string(): bad_cast to string
--> input.toml
|
1 | a = 123_456
| ^^^^^^^-- the actual type is integer
```
### `toml::value_t`
型情報は [`enum class toml::value_t`]({{<ref "docs/reference/value_t">}}) で識別できます。
[`type()`]({{<ref "docs/reference/value#type">}}) メンバ関数は、現時点で格納している値の型情報を返します。
```cpp
toml::value v = /* ... */;
switch(v.type())
{
case toml:value_t::empty : { /*...*/ break; }
case toml:value_t::boolean : { /*...*/ break; }
case toml:value_t::integer : { /*...*/ break; }
case toml:value_t::floating : { /*...*/ break; }
case toml:value_t::string : { /*...*/ break; }
case toml:value_t::offset_datetime: { /*...*/ break; }
case toml:value_t::local_datetime : { /*...*/ break; }
case toml:value_t::local_date : { /*...*/ break; }
case toml:value_t::local_time : { /*...*/ break; }
case toml:value_t::array : { /*...*/ break; }
case toml:value_t::table : { /*...*/ break; }
default: {break;}
}
```
[`is(toml::value_t)`]({{<ref "docs/reference/value#istomlvalue_t">}}) メンバ関数は、渡された `value_t` と同じ型の値を格納している場合 `true` を、
それ以外の場合 `false` を返します。
```cpp
toml::value v = /* ... */;
if(v.is(toml::value_t::integer))
{
std::cout << v.as_integer() << std::endl;
}
```
### `at`, `[]`, `contains`, `size`, `push_back`, `emplace_back`
標準ライブラリコンテナが持つメンバ関数の一部は、 `toml::value` も提供しています。
これらは、内部で `toml::value` を対応する型に変換し、そのメンバ関数を呼び出します。
#### `at(std::size_t i)`, `operator[](std::size_t i)`
`as_array().at(i)`, `as_array()[i]` と同等です。
`toml::value` はデフォルトで `std::vector<toml::value>``array_type` に使うので、
エラーが発生した際には `at``std::out_of_range` を送出し、`operator[]` は未定義動作となります。
```cpp
toml::value v(toml::array{1,2,3});
std::cout << v.at(1);
```
格納している型が `array_type` ではなかった場合、 `type_error` を送出します。
#### `at(std::string key)`, `operator[](std::string key)`
`as_table().at(key)`, `as_table()[key]` と同等です。
`toml::value` はデフォルトで `std::unordered_map<std::string, toml::value>``table_type` に使うので、
対応する値が存在しない場合は `at``std::out_of_range` を送出し、 `operator[]` は新しく `toml::value` を構築してそれへの参照を返します。
そのため、`operator[]``const` 版はありません。
```cpp
toml::value v(toml::table{});
v["a"] = 42;
```
格納している型が `table_type` ではなかった場合、 `type_error` を送出します。
#### `size()`
長さを返します。
`array_type` または `table_type` の場合は要素数、 `string_type` の場合は文字数を返します。
格納している型がどれでもなかった場合、 `type_error` を送出します。
#### `push_back()`, `emplace_back()`
`as_array().push_back()`, `as_array().emplace_back()` と同一です。
格納している型が `array_type` ではなかった場合、 `type_error` を送出します。
## コメントにアクセスする
toml11では、デフォルトでコメントがパースされ、対応する値に行ごとに保存されます。
対応する値は、連続するコメント行の直後に来る値か、もしくはそのコメントと同じ行に描かれている値です。
直前または直後に値がなければ、そのコメントはどこにも紐づけられず、無視されます。
```toml
# input.toml
# これはaに関するコメントです。
a = 42
b = 3.14 # これはbに関するコメントです。
# このコメントには対応する値がないため無視されます。
# これは1番目のcに関するコメントです。
# これは2番目のcに関するコメントです。
c = "foo" # これは最後のcに関するコメントです。
```
値に対応するコメントには、`toml::value``comments()` メンバ関数を使ってアクセスします。
`comments()``std::vector<std::string>` と同じメンバ関数を持つコンテナを返します。
```cpp
const auto v = toml::parse("input.toml");
const auto& a = v.at("a");
const auto& b = v.at("b");
const auto& c = v.at("c");
assert(a.comments().size() == 1);
assert(a.comments().at(0) == "# これはaに関するコメントです。");
assert(b.comments().size() == 1);
assert(b.comments().at(0) == "# これはbに関するコメントです。");
assert(c.comments().size() == 3);
assert(c.comments().at(0) == "# これは1番目のcに関するコメントです。");
assert(c.comments().at(1) == "# これは2番目のcに関するコメントです。");
assert(c.comments().at(2) == "# これは最後のcに関するコメントです。");
```
ファイル全体に対応するルートテーブルに関するコメントは、ファイルの先頭に書きます。
```toml
# ルートテーブルに関するコメントです。
# これもルートテーブルに関するコメントです。
# これはaに関するコメントです。
a = 42
```
ただし、もしファイルの先頭のコメントの直後に値が来た場合、
そのコメントはその値に関するコメントと解釈され、ルートテーブルのコメントはなくなります。
```toml
# これはaに関するコメントです。
# これもaに関するコメントです。
a = 42
```
## インラインテーブル・ドットキーの取り扱い
インラインテーブルは単にテーブルで、C++コード上で他のテーブルと異なる点はありません。
```toml
a = {b = 42, c = "foo"}
```
ドットキーも単にテーブルで、C++コード上で他のテーブルと異なる点はありません。
```toml
a.b = 42
a.c = "foo"
```
これらは以下のファイルと全く同じ構造を持ちます。
```toml
[a]
b = 42
c = "foo"
```
なので、どの記法でも以下の全く同一のコードで処理できます。
```cpp
const auto input = toml::parse("input.toml");
assert(input.at("a").at("b").as_integer() == 42);
assert(input.at("a").at("c").as_string() == "foo");
```
ただし、フォーマット情報によって区別することは可能です。
```cpp
const auto input = toml::parse("input.toml");
switch(input.at("a").as_table_fmt().fmt)
{
case toml::table_format::oneline:
{
std::cout << "inline table" << std::endl;
break;
}
case toml::table_format::multiline:
{
std::cout << "normal table" << std::endl;
break;
}
case toml::table_format::dotted:
{
std::cout << "dotted keys" << std::endl;
break;
}
}
```
このフォーマット情報は後述するシリアライズの際も考慮されます。
## 日付情報の取り扱い
[`local_date`]({{<ref "docs/reference/datetime#local_date">}}),
[`local_time`]({{<ref "docs/reference/datetime#local_time">}}),
[`local_datetime`]({{<ref "docs/reference/datetime#local_datetime">}}), そして
[`offset_datetime`]({{<ref "docs/reference/datetime#offset_datetime">}}) は、
toml11では対応するメンバ変数を持つ専用の構造体にパースされます。
使用する際は、直接値を取り出す他にも、後述する `toml::get``toml::find` を使用して、
`std::chrono::system_clock::time_point``std::tm` 等の型に変換することができます。
## `toml::get<T>`を使って変換する
`toml::get<T>` は、 `toml::value` の持つ値を変換して取り出す関数です。
`T` に変換先に指定したい型を指定します。
```cpp
const toml::value v = /*...*/;
std::cout << toml::get<int>(v) << std::endl;
```
後述する `toml::find<T>` も、型変換の部分は同一の機能を持ちます。
格納されている型のそれぞれについて、
変換ができない型が指定された場合、 `toml::type_error` が送出されます。
### 単純な変換
#### boolean_type
`boolean_type` から変換が可能なのは、 `bool` のみです。
#### integer_type
`bool` 以外で `std::is_integral<T>``true` になる型は、 `integer_type` から変換できます。
```cpp
toml::value v(42);
const auto u32 = toml::get<std::uint32_t>(v);
const auto i16 = toml::get<short>(v);
```
#### floating_type
`std::is_floating_point<T>``true` になる型は、`floating_type` から変換できます。
```cpp
toml::value v(3.14);
const auto f64 = toml::get<double>(v);
const auto f32 = toml::get<float >(v);
```
#### string_type
`string_type` からは `std::string` へ変換できます。
また、C++17以降では、`std::string_view` へも変換できます。
```cpp
toml::value v("foo");
const auto s = toml::get<std::string>(v);
// C++17以降
const auto sv = toml::get<std::string_view>(v);
```
#### datetime variants
[`local_date`]({{<ref "docs/reference/datetime#local_date">}}),
[`local_datetime`]({{<ref "docs/reference/datetime#local_datetime">}}),
[`offset_datetime`]({{<ref "docs/reference/datetime#offset_datetime">}}) は
ある日付と時刻を指しているため、
`std::chrono::system_clock::time_point` への変換が可能です。
ただし、[`local_time`]({{<ref "docs/reference/datetime#local_time">}}) は
日付の情報がないため、0時0分からの経過時刻として `std::chrono::duration` への
変換をサポートします。
また、 `local_date``local_datetime` は実行中のマシンのタイムゾーンを取得して変換を行います。
```toml
date = 2024-01-23
time = 12:30:00
l_dt = 2024-01-23T12:30:00
o_dt = 2024-01-23T12:30:00+09:00
```
```cpp
const auto input = toml::parse("input.toml");
const auto date = toml::get<std::chrono::system_clock::time_point>(input.at("date"));
const auto l_dt = toml::get<std::chrono::system_clock::time_point>(input.at("l_dt"));
const auto o_dt = toml::get<std::chrono::system_clock::time_point>(input.at("o_dt"));
const auto time = toml::get<std::chrono::minutes>(input.at("time")); // 12 * 60 + 30 min
```
### 参照を取得できる条件
`toml::get<T>` は、 `T``toml::value` が格納する型そのものだった場合、参照を返すことができます。
逆に、変換が必要な場合( `std::int64_t` で格納されている整数を `std::uint32_t` で取り出そうとした場合)は、
変換後の型への参照を返すことは不可能です。
変換が必要ない型の場合、返された参照を経由して値を書き換えることも可能です。
```cpp
toml::value v(42);
toml::get<toml::value::integer_type>(v) = 6 * 9;
assert(v.as_integer() == 54);
```
### 配列をSTLコンテナに
配列の要素型が全て同じ場合、要素型が `T` に変換可能であれば、 `std::vector<T>` に変換可能です。
```toml
a = [1, 2, 3, 4, 5]
```
```cpp
const auto a = toml::get<std::vector<int>>(input.at("a"));
```
他のSTLコンテナにも変換可能です。
```cpp
const auto a1 = toml::get<std::deque<int>>(input.at("a"));
const auto a2 = toml::get<std::list <int>>(input.at("a"));
const auto a3 = toml::get<std::array<int, 5>>(input.at("a"));
```
`std::array` に変換する場合、要素数が一致している必要があります。
もし要素数が一致しなかった場合、 `std::out_of_range` が送出されます。
STL以外のコンテナであっても、デフォルトコンストラクタと `push_back` を持っている場合、
`toml::get` で変換が可能です。
```cpp
const auto a = toml::get<boost::container::small_vector<int, 8>>(input.at("a"));
```
### 配列を `std::pair`, `std::tuple` に
配列の要素型が異なる場合、 `std::pair``std::tuple` に変換が可能です。
```toml
a = [true, 3.14]
b = [42, 2.718, "foo"]
```
```cpp
const auto a = toml::get<std::pair<bool, double>>(input.at("a"));
const auto b = toml::get<std::tuple<int, double, std::string>>(input.at("b"));
```
`std::array` の場合と同様に、配列の長さは `std::pair`, `std::tuple` の要素数と一致している必要があります。
もし要素数が一致しなかった場合、 `std::out_of_range` が送出されます。
また、各要素は対応する要素に変換できる必要があります。
変換できない場合、 `toml::type_error` が送出されます。
### ネストされた配列の変換
ネストされた配列は、ネストされたコンテナに変換可能です。
```toml
a = [ [1, 2, 3], [4, 5, 6] ]
```
```cpp
const auto a = toml::get<std::vector<std::vector<int>>>(input.at("a"));
```
型が異なる場合には、 `std::pair/tuple` が便利です。
```toml
a = [ [1, 2, 3], ["foo", "bar"] ]
```
```cpp
const auto a = toml::get<
std::pair<std::vector<int>, std::vector<std::string>>
>(input.at("a"));
```
### テーブルを `std::map` に変換
テーブルに含まれる値の型が全て同じであれば、 `std::map``std::unordered_map` に変換が可能です。
```toml
t = {a = 1, b = 2}
```
```cpp
const auto t = toml::get<std::map<std::string, int>>(input.at("t"));
```
STL以外のコンテナであっても、デフォルトコンストラクタと `emplace(key, mapped)` を持っている場合、
`toml::get` で変換が可能です。
```cpp
const auto t = toml::get<boost::container::flat_map<std::string, int>>(input.at("t"));
```
要素型の変換に失敗した場合は `toml::type_error` が送出されます。
## `toml::get_or`を使って失敗時の値を指定する
`toml::get` は変換に失敗した際に `toml::type_error` 例外を送出します。
`toml::get_or` を使用することで、変換に失敗した際に例外ではなくデフォルト値を返せるようになります。
`toml::get<T>` とは異なり、 `get_or` は引数から変換先の型を推論するため、 `<T>` の指定は不要です。
```cpp
const auto a = toml::get_or(input.at("a"), 42);
```
変換可能な型は `toml::get` と同様です。
`toml::value::xxx_type`を指定した場合は、参照を取り出すことも可能ですが、その場合は引数も参照である必要があります。
```cpp
toml::value::integer_type a_default = 42;
auto a& = toml::get_or(input.at("a"), a_default);
```
## `toml::find<T>`を使って検索と変換を同時に行う
`toml::find<T>` は、テーブルを持つ `toml::value` から値を検索し、同時に
`toml::get` と同じ型変換を行って取り出す関数です。
```cpp
const auto a = toml::find<int>(input, "a");
// const auto a = toml::get<int>(input.at("a")); と同じ
```
`toml::find<T>` は配列にも使用できます。
```cpp
const auto a = input.at("a");
const auto a2 = toml::find<int>(a, 2);
// const auto a2 = toml::get<int>(input.at("a").at(2)); と同じ
```
型変換の際にエラーが起きた場合、 `toml::get` と同じ `toml::type_error`
送出します。
キーが見つからなかった場合またはインデックスが存在しない場合は、
`std::out_of_range` を送出します。
型を指定しなかった場合、型変換を行わず `toml::value` を取り出します。
```cpp
const auto a = toml::find(input, "a");
// const auto a = input.at("a"); と同じ
```
`toml::find<T>` は再帰的に値にアクセスることもできます。
```toml
a = {b = {c = 42}}
```
```cpp
const auto a_b_c = toml::find<int>(input, "a", "b", "c");
// const auto a = toml::get<int>(input.at("a").at("b").at("c")); と同じ
```
このとき、キーとインデックスを混ぜることができます。
```toml
a = [ {b = 1}, {b = 2}, {b = 3} ]
```
```cpp
const auto a_2_b = toml::find<int>(input, "a", 2, "b");
// const auto a = toml::get<int>(input.at("a").at(2).at("c")); と同じ
```
{{<hint info>}}
TOMLはquoted keyという機能を持っています。
これは、 `""``''` を使うことで通常許可されない文字をキーに使えるというもので、
この中では `.` はテーブルを導入**しません**。
```toml
"127.0.0.1" = "value"
site."google.com" = true
```
このTOMLファイルは以下のようにして読みます。
```cpp
const auto input = toml::parse("input.toml");
assert(input.at("127.0.0.1").as_string() == "value");
assert(input.at("site").at("google.com").as_boolean());
```
このような場合にも違和感なく対応するため、toml11ではキーに `.` が含まれていても
自動で分割はしません。
テーブルの階層構造を陽に指定することが、適切な入力ファイルの構造化に資すると考えているからです。
参考: [toml.io キー](https://toml.io/ja/v1.0.0#%E3%82%AD%E3%83%BC)
{{</hint>}}
## `toml::find_or`を使って失敗時の値を指定する
`toml::find_or` は、 `toml::get_or` と同様に、失敗時のデフォルト値を渡します。
```cpp
const auto a = toml::find_or(input, "a", 42);
```
型変換の失敗だけでなく、キーが見つからなかった場合もデフォルト値を返します。
## ユーザー定義型との変換を定義する
`toml::get``toml::find` では、以下のどれかの方法を使うことで
ユーザー定義型を使用することができます。
### `toml::from` の定義
toml11には `toml::from` という型があり、以下のように特殊化することでユーザー定義型からの
変換をサポートできます。
```cpp
namespace extlib
{
struct foo
{
int a;
std::string b;
};
} // extlib
namespace toml
{
template<>
struct from<extlib::foo>
{
static extlib::foo from_toml(const toml::value& v)
{
return extlib::foo{
toml::find<int>(v, "a"),
toml::find<std::string>(v, "b")
};
}
};
} // toml
```
後述する型設定を変更した `toml::value` もサポートする場合、以下のようにしてください。
```cpp
namespace extlib
{
struct foo
{
int a;
std::string b;
};
} // extlib
namespace toml
{
template<>
struct from<extlib::foo>
{
template<typename <TC>
static extlib::foo from_toml(const toml::basic_value<TC>& v)
{
return extlib::foo{
toml::find<int>(v, "a"),
toml::find<std::string>(v, "b")
};
}
};
} // toml
```
この定義は、 `TOML11_DEFINE_CONVERSION_NON_INTRUSIVE` によって自動的に定義できます。
```cpp
namespace extlib
{
struct foo
{
int a;
std::string b;
};
} // extlib
TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(extlib::foo, a, b)
```
あるいは、リフレクションライブラリを使用することもできます。
`example``boost-ext/reflect` を使用したサンプルも参照してください。
### `from_toml` メンバ関数の定義
`from_toml` メンバ関数を定義することによっても変換を定義することができます。
これを使用する場合、デフォルトコンストラクタが必要です。
```cpp
struct bar
{
int a;
std::string b;
void from_toml(const toml::value& v)
{
this->a = toml::find<int>(v, "a");
this->b = toml::find<std::string>(v, "b");
return ;
}
};
```
両方が定義されていた場合、 `toml::from` が優先されます。
### `toml::value` を受け取るコンストラクタ
`toml::value` を受け取るコンストラクタがあれば、 `toml::get` による変換ができます。
```cpp
struct baz
{
explicit baz(const toml::value& v)
: a(toml::find<int>(v, "a")), b(toml::find<std::string>(v, "b"))
{}
int a;
std::string b;
};
```
両方が定義されていた場合、`toml::from``from_toml` が優先されます。
## `toml::visit`で関数を適用する
`toml::value` が格納する型すべてに適用できる関数オブジェクトがあれば、
`toml::visit` によって型変換を経ずに直接その関数を呼ぶことができます。
```cpp
struct type_name_of
{
std::string operator()(const toml::value::boolean_type &) const {return "boolean";}
std::string operator()(const toml::value::integer_type &) const {return "integer";}
std::string operator()(const toml::value::floating_type &) const {return "floating";}
std::string operator()(const toml::value::string_type &) const {return "string";}
std::string operator()(const toml::value::local_time_type &) const {return "local_time";}
std::string operator()(const toml::value::local_date_type &) const {return "local_date";}
std::string operator()(const toml::value::local_datetime_type &) const {return "local_datetime";}
std::string operator()(const toml::value::offset_datetime_type&) const {return "offset_datetime";}
std::string operator()(const toml::value::array_type &) const {return "array";}
std::string operator()(const toml::value::table_type &) const {return "table";}
};
toml::value v(3.14);
std::cout << toml::visit(type_name_of{}, v) << std::endl; // floating
```
## `toml::value` を構築する
`toml::value` はパーサの内部だけでなく、ユーザーコードで構築することも可能です。
`toml::value` が格納する型と同じか変換可能な型を渡しての構築が可能です。
```cpp
toml::value v1(true);
toml::value v2(42);
toml::value v3(3.14);
```
配列の場合、 `toml::array` を使うか、
```cpp
toml::value v(toml::array{1, 2, 3});
```
配列の場合、 `std::vector` などのコンテナを直接渡すことが可能です。
```cpp
const std::vector<toml::value> a{1,2,3};
toml::value v(a);
```
このコンテナには、 `toml::get` で変換可能なコンテナが使用できます。
テーブルの場合も同様に、 `toml::table` を使うか、
```cpp
toml::value v(toml::table{{"foo", 1}, {"bar", 2}, {"baz", 3}});
```
`std::map` などのコンテナを直接渡します。
```cpp
const std::map<std::string, toml::value> t{
{"foo", 1}, {"bar", 2}, {"baz", 3}
}
toml::value v(t);
```
コンストラクタには、 `format_info` と コメントを渡すことができます。
コメントの型は `std::vector<std::string>` です。
各要素が一行分に相当します。
```cpp
toml::integer_format_info fmt;
fmt.fmt = toml::integer_format::hex;
fmt.spacer = 4;
toml::value v1(0xDEADBEEF, fmt);
toml::value v2(0xC0FFEE, fmt, {"hex value!"});
```
## `toml::value` に変換する
ユーザー定義型から `toml::value` を構築する際に、 `toml::into``into_toml`
定義することで、その挙動をカスタマイズできます。
特に、別のライブラリの型などを変換する際に `toml::into` が便利です。
### `toml::into`を定義する
`toml::into` を特殊化することで `toml::value` への変換が可能になります。
`toml::value` への変換が用意されていない外部ライブラリの型などに対して有効です。
`toml::value` が変換時に `type_config` を渡すため、`basic_value``template` 引数を受け取る必要があります。
```cpp
namespace extlib
{
struct foo
{
int a;
std::string b;
};
} // extlib
template<>
struct into<extlib::foo>
{
template<typename TC>
static toml::basic_value<TC> into_toml(const extlib::foo& f)
{
return toml::basic_value<TC>(typename toml::basic_value<TC>::table_type{{"a", f.a}, {"b", f.b}});
}
};
```
### `into_toml` メンバ関数を定義する
`from_toml` と同様、メンバ関数によっても変換を定義することができます。
`toml::into` が定義されていた場合、そちらが優先されます。
```cpp
struct bar
{
int a;
std::string b;
toml::value into_toml() const
{
return toml::value(toml::table{{"a", this->a}, {"b", this->b}});
}
};
```

View File

@@ -0,0 +1,104 @@
+++
title = "installation"
type = "docs"
weight = 1
+++
# installation
## `single_include`を使用する
`single_include/toml.hpp`は、`toml11`が持つ全ての機能を単一のファイルにまとめたシングルファイル・ヘッダオンリーライブラリです。
これを`INCLUDE_PATH`が通っている箇所にコピーして`#include <toml.hpp>`とするのが最も単純な使用方法です。
MITライセンスの許諾表示はコメントと`toml:license_notice()`関数の両方に含まれます。
ソースコードを公開せずに再頒布する場合は、toml11のライセンスファイルをコピーして同梱するか、この関数を呼び出せるようにしておいてください。
## toml11をクローンし、`cmake`を使って使用する
`toml11``git submodule`などによって自身のレポジトリ下に配置した場合、`cmake`を使用している場合は`add_subdirectory(toml11)`のようにすることで使用可能になります。
```cmake
add_subdirectory(toml11)
add_executable(main main.cpp)
target_link_libraries(main PUBLIC toml11::toml11)
```
`toml11`は自身がルートプロジェクトのときのみ、テストとインストールを行います。
## `cmake`を使用してインストールする
`toml11`をクローンしたのち、`cmake`を使ってインストールすることができます。
```console
$ cmake -B ./build/ -DTOML11_BUILD_TESTS=ON
$ cmake --install ./build/ --prefix=/opt/toml11
```
インストールの前にテストプログラムを実行する際は、最初に`-DTOML11_BUILD_TESTS=ON`を設定してください。
インストールが完了すれば、以下のようにして使用できます。
```cmake
find_package(toml11)
add_executable(main main.cpp)
target_link_libraries(main PRIVATE toml11::toml11)
```
## `cmake`を使用してコンパイルし、静的ライブラリを作成する
`cmake`の実行時に`-DTOML11_PRECOMPILE=ON`を定義することで、`toml11`の関数のうちコンパイルできるものを先にコンパイルして、全体のコンパイル時間を短縮することができます。
```console
$ cmake -B ./build/ -DTOML11_PRECOMPILE=ON
```
ただし、toml11は複数のC++バージョンに対応するため、`__cplusplus`の値などによって型を切り替えることがあります。
そのため、ビルドした際のバージョンと使用時のバージョンが異なる場合、リンクに失敗する可能性があります。
問題が生じた場合は`CMAKE_CXX_STANDARD`によって必要なバージョンを設定してコンパイルしてください。
それが難しい場合は、通常通りヘッダオンリーライブラリとして使用してください。
`find_package(toml11)`によって`TOML11_INCLUDE_DIR`が定義されます。
コンパイル済みライブラリとしてインストールした場合でも、 `TOML11_INCLUDE_DIR`
`include_directories` に追加した上で `target_link_libraries`
使用しないようにすれば、ヘッダオンリーライブラリとして使用可能です。
```cmake
find_package(toml11)
add_executable(main main.cpp)
# インクルードのみ可能にし、リンクを行わない
target_include_directories(main PRIVATE ${TOML11_INCLUDE_DIR})
```
## examplesをコンパイルする
`-DTOML11_BUILD_EXAMPLES=ON`とすることで、`examples/`をコンパイルできます。
```console
$ cmake -B ./build/ -DTOML11_BUILD_EXAMPLES=ON
$ cmake --build ./build/
```
`examples`の実行バイナリは`examples/`に生成されます。
## テストを実行する
テストをビルドするためには、`-DTOML11_BUILD_TESTS=ON`とします。
```console
$ git submodule update --init --recursive
$ cmake -B ./build/ -DTOML11_BUILD_TESTS=ON
$ cmake --build ./build/
$ ctest --test_dir ./build/
```
toml-lang/toml-testsを実行するには、`-DTOML11_BUILD_TOML_TESTS=ON`とします。
すると、`tests/``toml11_decoder``toml11_encoder`がビルドされます。
```console
$ git submodule update --init --recursive
$ cmake -B ./build/ -DTOML11_BUILD_TOML_TESTS=ON
$ cmake --build ./build/
$ ctest --test_dir ./build/
```

View File

@@ -0,0 +1,124 @@
+++
title = "reference"
type = "docs"
weight = 3
bookCollapseSection = true
+++
# Reference
以下では、toml11が公開するクラスと関数の効果を説明します。
## ディレクトリ構造
`toml.hpp``toml_fwd.hpp``${TOML11_INCLUDE_DIR}` にあります。
他のファイルは、`${TOML11_INCLUDE_DIR}/toml11` にあります。
もし各機能のファイルを個別に `#include` したい場合は、 `#include <toml11/color.hpp>` としてください。
全てを一度に `#include` する場合は、 `#include <toml.hpp>` としてください。
## [color.hpp](color)
エラーメッセージの色付けに関する関数を定義します。
## [comments.hpp](comments)
コメントを持つ`preserve_comment`型と`discard_comment`型を定義します。
## [conversion.hpp](conversion)
`toml::value`とユーザー定義クラスを自動的に変換するマクロを定義します。
## [datetime.hpp](datetime)
日時情報を持つクラスを定義します。
## [error_info.hpp](error_info)
エラー情報を持つクラスを定義します。
## [exception.hpp](exception)
toml11で使用される例外の基底クラス、`toml::exception`を定義します。
## [find.hpp](find)
値を探し変換する`toml::find`関数を定義します。
## [format.hpp](format)
値のフォーマット情報を持つクラスを定義します。
## [from.hpp](from)
ユーザー定義型を変換するための`from<T>`型の前方宣言です。
## [get.hpp](get)
`toml::value`の値を取り出し変換する`toml::get<T>`関数を定義します。
## [into.hpp](into)
ユーザー定義型を変換するための`into<T>`型の前方宣言です。
## [literal.hpp](literal)
`operator"" _toml`リテラルを定義します。
## [ordered_map.hpp](ordered_map)
`toml::ordered_map`を定義します。
## [parser.hpp](parser)
ファイルまたは文字列をパースする関数を定義します。
## [result.hpp](result)
他の関数の返り値として使われる、成功値または失敗値を持つ`result<T, E>`型を定義します。
## [serializer.hpp](serializer)
シリアライズに用いる`toml::format`関数と`toml::serializer`を定義します。
## [source_location.hpp](source_location)
エラー情報に用いられる、ファイル内のある領域を指す`source_location`型を定義します。
## [spec.hpp](spec)
TOML言語のバージョン情報と機能フラグを制御する、`toml::semantic_version`型と`toml::spec`型を定義します。
## [toml.hpp](toml)
`toml.hpp`は、他の全てのヘッダを `include` します。
toml11の全機能が使用可能になります。
## [toml_fwd.hpp](toml_fwd)
`toml_fwd.hpp`は、toml11で定義される構造体の前方宣言と、マクロ定義を持ちます。
## [types.hpp](types)
`toml::value`の持つ型を制御するための`toml::type_config`型を定義します。
## [value.hpp](value)
`toml::value`型を定義します。
## [value_t.hpp](value_t)
列挙型`toml::value_t`を定義します。
## [version.hpp](version)
toml11のバージョン情報を定義します。
## [visit.hpp](visit)
`toml::value`の持つ値に関数を適用する`toml::visit`関数を定義します。
## 備考
ここで明記されない関数(主に`namespace toml::detail``namespace toml::cxx`以下に定義されるもの)は、
ソースコードを見ることで利用可能ではあるものの、そのインターフェースは今後のいかなるバージョンアップでも(パッチバージョンアップを含む)維持される保証はありません。

View File

@@ -0,0 +1,141 @@
+++
title = "color.hpp"
type = "docs"
+++
# color.hpp
`color.hpp`では、エラーメッセージの色付けに関する関数が定義されます。
色はANSIエスケープシーケンスによって指定されます。
ANSIエスケープシーケンスをサポートしていないターミナルやその他の出力先では、読みにくくなる可能性があります。
## マクロ
```cpp
TOML11_COLORIZE_ERROR_MESSAGE
```
コンパイル時にこのマクロが定義されていた場合(`-DTOML11_COLORIZE_ERROR_MESASGE`)、
デフォルトでエラーメッセージに色が付きます。
定義されていなかった場合、デフォルトでは色は付きません。以下の `toml::color::enable()`
使用して指定する必要があります。
## 関数
### `enable()`
```cpp
namespace toml {
namespace color {
void enable();
} // color
} // toml
```
ANSIエスケープシーケンスによる色付けを行うよう設定します。
#### 例
```cpp
#include <toml.hpp>
int main()
{
toml::color::enable(); // この後の全てのエラーがカラーになります。
const auto input = toml::parse("input.toml");
return 0;
}
```
### `disable()`
```cpp
namespace toml {
namespace color {
void disable();
} // color
} // toml
```
ANSIエスケープシーケンスによる色付けを行わないよう設定します。
#### 例
```cpp
#include <toml.hpp>
int main()
{
toml::color::enable(); // この後の全てのエラーがカラーになります。
const auto input = toml::parse("input.toml");
return 0;
}
```
### `should_color()`
```cpp
namespace toml {
namespace color {
bool should_color();
} // color
} // toml
```
色付けを行う設定になっている場合`true`が、そうでない場合`false`が返されます。
#### 例
```cpp
#include <toml.hpp>
#include <iomanip>
#include <iostream>
int main()
{
std::cout << "colorized? : " << std::boolalpha << toml::color::should_color() << std::endl;
return 0;
}
```
## マニピュレータ
```cpp
namespace toml {
namespace color {
std::ostream& reset (std::ostream&);
std::ostream& bold (std::ostream&);
std::ostream& grey (std::ostream&);
std::ostream& gray (std::ostream&);
std::ostream& red (std::ostream&);
std::ostream& green (std::ostream&);
std::ostream& yellow (std::ostream&);
std::ostream& blue (std::ostream&);
std::ostream& magenta(std::ostream&);
std::ostream& cyan (std::ostream&);
std::ostream& white (std::ostream&);
} // color
} // toml
```
ANSIエスケープシーケンスによって、`fg`を色付けします。
#### 例
```cpp
#include <toml.hpp>
#include <iostream>
int main()
{
std::cout << toml::color::red << "red!" << std::endl;
return 0;
}
```
# 関連項目
- [error_info.hpp]({{<ref "error_info.md">}})

View File

@@ -0,0 +1,773 @@
+++
title = "comments.hpp"
type = "docs"
+++
# comments.hpp
`color.hpp`では、コメントを保持するクラスが提供されます。
# `toml::preserve_comments`
`preserve_comments`は、コメントを保持するコンテナです。
`std::vector<std::string>`が持つメンバ関数を全て持っています。
コメントは`std::string`として保持されます。
先頭が`#`でない場合、出力時に`#`が補われます。コンテナに要素として追加する段階では補われません。
スペースは補われないため、`#`の直後にスペースを入れたい場合、コメントをスペースから始めるか、`#`を含めたコメントを渡す必要があります。
```cpp
namespace toml
{
class preserve_comments;
bool operator==(const preserve_comments&, const preserve_comments&);
bool operator!=(const preserve_comments&, const preserve_comments&);
bool operator< (const preserve_comments&, const preserve_comments&);
bool operator<=(const preserve_comments&, const preserve_comments&);
bool operator> (const preserve_comments&, const preserve_comments&);
bool operator>=(const preserve_comments&, const preserve_comments&);
void swap(preserve_comments&, preserve_comments&);
void swap(preserve_comments&, std::vector<std::string>&);
void swap(std::vector<std::string>&, preserve_comments&);
std::ostream& operator<<(std::ostream&, const preserve_comments&);
} //toml
```
## メンバ型
```cpp
using container_type = std::vector<std::string>;
using size_type = container_type::size_type;
using difference_type = container_type::difference_type;
using value_type = container_type::value_type;
using reference = container_type::reference;
using const_reference = container_type::const_reference;
using pointer = container_type::pointer;
using const_pointer = container_type::const_pointer;
using iterator = container_type::iterator;
using const_iterator = container_type::const_iterator;
using reverse_iterator = container_type::reverse_iterator;
using const_reverse_iterator = container_type::const_reverse_iterator;
```
## メンバ関数
### デフォルトコンストラクタ
```cpp
preserve_comments() = default;
```
空の`preserve_comments`を構築します。
### コピー・ムーブコンストラクタ
```cpp
preserve_comments(preserve_comments const&) = default;
preserve_comments(preserve_comments &&) = default;
```
`preserve_comments`をコピー・ムーブ構築します。
### コンストラクタ(`std::vector<std::string>`)
```cpp
explicit preserve_comments(const std::vector<std::string>& c);
explicit preserve_comments(std::vector<std::string>&& c);
```
`std::vector<std::string>`の内容を持つ`preserve_comments`を構築します。
### コンストラクタ(`discard_comments`)
```cpp
explicit preserve_comments(const discard_comments&);
```
空の`preserve_comments`を構築します。
### コンストラクタ(`Iterator`)
```cpp
template<typename InputIterator>
preserve_comments(InputIterator first, InputIterator last);
```
`std::string`を指す`InputIterator`が表す範囲から`preserve_comments`を構築します。
### コンストラクタ(`std::initializer_list`)
```cpp
preserve_comments(std::initializer_list<std::string> x);
```
`std::initializer_list<std::string>`が表す範囲から`preserve_comments`を構築します。
### コンストラクタ(サイズ指定)
```cpp
explicit preserve_comments(size_type n);
preserve_comments(size_type n, const std::string& x);
```
`n`個のコメントを持つ`preserve_comments`を構築します。
`std::string`を渡した場合、そのコメントを`n`個に複製します。
### デストラクタ
```cpp
~preserve_comments() = default;
```
`preserve_comments`を破棄します。
### `operator=(preserve_comments)`
```cpp
preserve_comments& operator=(preserve_comments const&) = default;
preserve_comments& operator=(preserve_comments &&) = default;
```
`preserve_comments`をコピー・ムーブ代入します。
### `operator=(std::vector<std::string>)`
```cpp
preserve_comments& operator=(const std::vector<std::string>& c);
preserve_comments& operator=(std::vector<std::string>&& c);
```
`std::vector<std::string>`をコピー・ムーブ代入します。
### `assign`
```cpp
template<typename InputIterator>
void assign(InputIterator first, InputIterator last);
void assign(std::initializer_list<std::string> ini);
void assign(size_type n, const std::string& val);
```
`std::vector<std::string>::assign`と同等の効果を持ちます。
### `insert`
```cpp
iterator insert(const_iterator p, const std::string& x);
iterator insert(const_iterator p, std::string&& x);
iterator insert(const_iterator p, size_type n, const std::string& x);
template<typename InputIterator>
iterator insert(const_iterator p, InputIterator first, InputIterator last);
iterator insert(const_iterator p, std::initializer_list<std::string> ini);
```
`std::vector<std::string>::insert`と同等の効果を持ちます。
### `emplace`
```cpp
template<typename ... Ts>
iterator emplace(const_iterator p, Ts&& ... args);
```
`std::vector<std::string>::insert`と同等の効果を持ちます。
### `erase`
```cpp
iterator erase(const_iterator pos);
iterator erase(const_iterator first, const_iterator last);
```
`std::vector<std::string>::insert`と同等の効果を持ちます。
### `swap`
```cpp
void swap(preserve_comments& other);
```
他の`preserve_comments`と内容を交換します。
### `push_back`
```cpp
void push_back(const std::string& v);
void push_back(std::string&& v);
```
`std::vector<std::string>::push_back`と同等の効果を持ちます。
### `pop_back`
```cpp
void pop_back();
```
`std::vector<std::string>::pop_back`と同等の効果を持ちます。
### `emplace_back`
```cpp
template<typename ... Ts>
void emplace_back(Ts&& ... args);
```
`std::vector<std::string>::emplace_back`と同等の効果を持ちます。
### `clear`
```cpp
void clear();
```
`std::vector<std::string>::clear`と同等の効果を持ちます。
### `size`
```cpp
size_type size() const noexcept;
```
`std::vector<std::string>::size`と同等の効果を持ちます。
### `max_size`
```cpp
size_type max_size() const noexcept;
```
`std::vector<std::string>::max_size`と同等の効果を持ちます。
### `capacity`
```cpp
size_type capacity() const noexcept;
```
`std::vector<std::string>::capacity`と同等の効果を持ちます。
### `empty`
```cpp
bool empty() const noexcept;
```
`std::vector<std::string>::empty`と同等の効果を持ちます。
### `reserve`
```cpp
void reserve(size_type n);
```
`std::vector<std::string>::reserve`と同等の効果を持ちます。
### `resize`
```cpp
void resize(size_type n);
void resize(size_type n, const std::string& c);
```
`std::vector<std::string>::resize`と同等の効果を持ちます。
### `shrink_to_fit`
```cpp
void shrink_to_fit();
```
`std::vector<std::string>::shrink_to_fit`と同等の効果を持ちます。
### `operator[]`
```cpp
reference operator[](const size_type n) noexcept;
const_reference operator[](const size_type n) const noexcept;
```
`std::vector<std::string>::operator[]`と同等の効果を持ちます。
### `at`
```cpp
reference at(const size_type n) ;
const_reference at(const size_type n) const;
```
`std::vector<std::string>::at`と同等の効果を持ちます。
### `front`
```cpp
reference front() noexcept;
const_reference front() const noexcept;
```
`std::vector<std::string>::front`と同等の効果を持ちます。
### `back`
```cpp
reference back() noexcept;
const_reference back() const noexcept;
```
`std::vector<std::string>::back`と同等の効果を持ちます。
### `data`
```cpp
pointer data() noexcept;
const_pointer data() const noexcept;
```
`std::vector<std::string>::data`と同等の効果を持ちます。
### `begin/end`
```cpp
iterator begin() noexcept;
iterator end() noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
```
`std::vector<std::string>::begin/end`と同等の効果を持ちます。
### `rbegin/rend`
```cpp
reverse_iterator rbegin() noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator rend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
```
`std::vector<std::string>::rbegin/rend`と同等の効果を持ちます。
## 非メンバ関数
### 比較演算子
```cpp
bool operator==(const preserve_comments&, const preserve_comments&);
bool operator!=(const preserve_comments&, const preserve_comments&);
bool operator< (const preserve_comments&, const preserve_comments&);
bool operator<=(const preserve_comments&, const preserve_comments&);
bool operator> (const preserve_comments&, const preserve_comments&);
bool operator>=(const preserve_comments&, const preserve_comments&);
```
`std::vector<std::string>`と同様に比較を行います。
### `swap`
```cpp
void swap(preserve_comments&, preserve_comments&);
void swap(preserve_comments&, std::vector<std::string>&);
void swap(std::vector<std::string>&, preserve_comments&);
```
### ストリーム演算子
```cpp
std::ostream& operator<<(std::ostream&, const preserve_comments&);
```
コメントとして出力します。
先頭が`#`でない場合、`#`が補われます。
# `toml::discard_comments`
`discard_comments`は、コメントを破棄するコンテナです。
`std::vector<std::string>`が持つメンバ関数を全て持っていますが、内容を変更する関数を呼び出しても何も効果はなく、常に空になります。
```cpp
namespace toml
{
class discard_comments;
bool operator==(const discard_comments&, const discard_comments&);
bool operator!=(const discard_comments&, const discard_comments&);
bool operator< (const discard_comments&, const discard_comments&);
bool operator<=(const discard_comments&, const discard_comments&);
bool operator> (const discard_comments&, const discard_comments&);
bool operator>=(const discard_comments&, const discard_comments&);
void swap(discard_comments&, discard_comments&);
std::ostream& operator<<(std::ostream&, const discard_comments&);
} //toml
```
## メンバ型
```cpp
// container_type is not defined
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using value_type = std::string;
using reference = std::string&;
using const_reference = std::string const&;
using pointer = std::string*;
using const_pointer = std::string const*;
using iterator = /* internal type: empty-iterator */
using const_iterator = /* internal type: empty-iterator */
using reverse_iterator = /* internal type: empty-iterator */
using const_reverse_iterator = /* internal type: empty-iterator */
```
### デフォルトコンストラクタ
```cpp
discard_comments() = default;
```
空の`discard_comments`を構築します。
### コピー・ムーブコンストラクタ
```cpp
discard_comments(discard_comments const&) = default;
discard_comments(discard_comments &&) = default;
```
`discard_comments`をコピー・ムーブ構築します。
### コンストラクタ(`std::vector<std::string>`)
```cpp
explicit discard_comments(const std::vector<std::string>& c);
explicit discard_comments(std::vector<std::string>&& c);
```
空の`discard_comments`を構築します。引数の内容は無視されます。
### コンストラクタ(`preserve_comments`)
```cpp
explicit discard_comments(const preserve_comments&);
```
空の`discard_comments`を構築します。引数の内容は無視されます。
### コンストラクタ(`Iterator`)
```cpp
template<typename InputIterator>
discard_comments(InputIterator first, InputIterator last);
```
空の`discard_comments`を構築します。引数の内容は無視されます。
### コンストラクタ(`std::initializer_list`)
```cpp
discard_comments(std::initializer_list<std::string> x);
```
空の`discard_comments`を構築します。引数の内容は無視されます。
### コンストラクタ(サイズ指定)
```cpp
explicit discard_comments(size_type n);
discard_comments(size_type n, const std::string& x);
```
空の`discard_comments`を構築します。引数の内容は無視されます。
### デストラクタ
```cpp
~discard_comments() = default;
```
`discard_comments`を破棄します。
### `operator=(discard_comments)`
```cpp
discard_comments& operator=(discard_comments const&) = default;
discard_comments& operator=(discard_comments &&) = default;
```
`discard_comments`をコピー・ムーブ代入します。
### `operator=(std::vector<std::string>)`
```cpp
discard_comments& operator=(const std::vector<std::string>& c);
discard_comments& operator=(std::vector<std::string>&& c);
```
何もしません。引数の内容は無視されます。
### `assign`
```cpp
template<typename InputIterator>
void assign(InputIterator first, InputIterator last);
void assign(std::initializer_list<std::string> ini);
void assign(size_type n, const std::string& val);
```
何もしません。引数の内容は無視されます。
### `insert`
```cpp
iterator insert(const_iterator p, const std::string& x);
iterator insert(const_iterator p, std::string&& x);
iterator insert(const_iterator p, size_type n, const std::string& x);
template<typename InputIterator>
iterator insert(const_iterator p, InputIterator first, InputIterator last);
iterator insert(const_iterator p, std::initializer_list<std::string> ini);
```
何もしません。引数の内容は無視されます。
### `emplace`
```cpp
template<typename ... Ts>
iterator emplace(const_iterator p, Ts&& ... args);
```
何もしません。引数の内容は無視されます。
### `erase`
```cpp
iterator erase(const_iterator pos);
iterator erase(const_iterator first, const_iterator last);
```
何もしません。引数の内容は無視されます。
### `swap`
```cpp
void swap(discard_comments& other);
```
他の`discard_comments`と内容を交換します。
### `push_back`
```cpp
void push_back(const std::string& v);
void push_back(std::string&& v);
```
何もしません。引数の内容は無視されます。
### `pop_back`
```cpp
void pop_back();
```
何もしません。引数の内容は無視されます。
### `emplace_back`
```cpp
template<typename ... Ts>
void emplace_back(Ts&& ... args);
```
何もしません。引数の内容は無視されます。
### `clear`
```cpp
void clear();
```
何もしません。引数の内容は無視されます。
### `size`
```cpp
size_type size() const noexcept;
```
常に`0`を返します。
### `max_size`
```cpp
size_type max_size() const noexcept;
```
常に`0`を返します。
### `capacity`
```cpp
size_type capacity() const noexcept;
```
常に`0`を返します。
### `empty`
```cpp
bool empty() const noexcept;
```
常に`true`を返します。
### `reserve`
```cpp
void reserve(size_type n);
```
何もしません。引数の内容は無視されます。
### `resize`
```cpp
void resize(size_type n);
void resize(size_type n, const std::string& c);
```
何もしません。引数の内容は無視されます。
### `shrink_to_fit`
```cpp
void shrink_to_fit();
```
何もしません。引数の内容は無視されます。
### `operator[]`
```cpp
reference operator[](const size_type n) noexcept;
const_reference operator[](const size_type n) const noexcept;
```
未定義動作です。
### `at`
```cpp
reference at(const size_type n) ;
const_reference at(const size_type n) const;
```
`std::out_of_range`を送出します。
### `front`
```cpp
reference front() noexcept;
const_reference front() const noexcept;
```
未定義動作です。
### `back`
```cpp
reference back() noexcept;
const_reference back() const noexcept;
```
未定義動作です。
### `data`
```cpp
pointer data() noexcept;
const_pointer data() const noexcept;
```
常に`nullptr`を返します。
### `begin/end`
```cpp
iterator begin() noexcept;
iterator end() noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
```
内部で定義された`empty-iterator`を返します。
`empty-iterator`はインクリメントやデクリメントしても同じ値でとどまり、全ての値が同値です。
`empty-iterator`が指す先にアクセスすると常に`std::terminate`が呼び出されます。
### `rbegin/rend`
```cpp
reverse_iterator rbegin() noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator rend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
```
内部で定義された`empty-iterator`を返します。
`empty-iterator`はインクリメントやデクリメントしても同じ値でとどまり、全ての値が同値です。
`empty-iterator`が指す先にアクセスすると常に`std::terminate`が呼び出されます。
## 非メンバ関数
### 比較演算子
```cpp
bool operator==(const discard_comments&, const discard_comments&);
bool operator!=(const discard_comments&, const discard_comments&);
bool operator< (const discard_comments&, const discard_comments&);
bool operator<=(const discard_comments&, const discard_comments&);
bool operator> (const discard_comments&, const discard_comments&);
bool operator>=(const discard_comments&, const discard_comments&);
```
`discard_comments`は全て同じ値です。`==`には常に`true`を、`!=`には常に`false`を返します。
### `swap`
```cpp
void swap(discard_comments&, discard_comments&);
```
二つの`discard_comments`を交換します。
### ストリーム演算子
```cpp
std::ostream& operator<<(std::ostream&, const discard_comments&);
```
何も出力しません。
# 関連項目
- [value.hpp]({{<ref "value.md">}})

View File

@@ -0,0 +1,33 @@
+++
title = "conversion.hpp"
type = "docs"
+++
# conversion.hpp
`toml::get``toml::find`でユーザー定義型をサポートするための変換関数を自動定義するマクロを提供します。
```cpp
TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(NAME, ...)
```
## 例
```cpp
namespace foo
{
struct Foo
{
std::string s;
double d;
int i;
};
} // foo
TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(foo::Foo, s, d, i)
```
# 関連項目
- [from.hpp]({{<ref "from.md">}})
- [into.hpp]({{<ref "into.md">}})

View File

@@ -0,0 +1,779 @@
+++
title = "datetime.hpp"
type = "docs"
+++
# datetime.hpp
TOMLの`datetime`で使用される、日時情報を保存するクラスを定義します。
# `enum class month_t`
月を指定する`enum class`です。
`std::tm`との関係で、`local_date`は1月を`0`としています。
混乱を避けるため、月の名前で指定できるよう`month_t`が用意されています。
```cpp
namespace toml
{
enum class month_t : std::uint8_t
{
Jan = 0,
Feb = 1,
Mar = 2,
Apr = 3,
May = 4,
Jun = 5,
Jul = 6,
Aug = 7,
Sep = 8,
Oct = 9,
Nov = 10,
Dec = 11
};
}
```
# `local_date`
日付を保持する構造体です。
`year`は西暦を、`month``std::tm`との対応のため1月を`0`として、`day`は日付を保持します。
```cpp
namespace toml
{
struct local_date
{
std::int16_t year;
std::uint8_t month;
std::uint8_t day;
local_date() = default;
~local_date() = default;
local_date(local_date const&) = default;
local_date(local_date&&) = default;
local_date& operator=(local_date const&) = default;
local_date& operator=(local_date&&) = default;
local_date(int y, month_t m, int d);
explicit local_date(const std::tm& t);
explicit local_date(const std::chrono::system_clock::time_point& tp);
explicit local_date(const std::time_t t);
operator std::chrono::system_clock::time_point() const;
operator std::time_t() const;
};
bool operator==(const local_date&, const local_date&);
bool operator!=(const local_date&, const local_date&);
bool operator< (const local_date&, const local_date&);
bool operator<=(const local_date&, const local_date&);
bool operator> (const local_date&, const local_date&);
bool operator>=(const local_date&, const local_date&);
std::ostream& operator<<(std::ostream& os, const local_date& date);
std::string to_string(const local_date& date);
}
```
## メンバ変数
### `year`
```cpp
std::int16_t year;
```
西暦です。オフセットはありません。`2024`年は`2024`です。
### `month`
```cpp
std::uint8_t month;
```
月を表します。`std::tm`との対応のため、1月は`0`, 2月は`1`と続きます。
混乱を避けるため、構築の際は`month_t`を使用します。
### `day`
```cpp
std::uint8_t day;
```
日付を表します。1日は`1`です。
## メンバ関数
### コンストラクタ
```cpp
local_date() = default;
```
デフォルト実装を使用します。
### デストラクタ
```cpp
~local_date() = default;
```
デフォルト実装を使用します。
### コピー・ムーブコンストラクタ
```cpp
local_date(local_date const&) = default;
local_date(local_date&&) = default;
```
デフォルト実装を使用します。
### コピー・ムーブ代入演算子
```cpp
local_date& operator=(local_date const&) = default;
local_date& operator=(local_date&&) = default;
```
デフォルト実装を使用します。
### コンストラクタ(`int year, month_t month, int day`)
```cpp
local_date(int y, month_t m, int d);
```
指定した値から`local_date`を構築します。
境界チェックなどは行いません。
### コンストラクタ(`std::tm`)
```cpp
local_date(const std::tm&);
```
指定した値から`local_date`を構築します。
### コンストラクタ(`std::chrono::system_clock::time_point`)
```cpp
local_date(const std::chrono::system_clock::time_point&);
```
指定した値から`local_date`を構築します。
タイムゾーンは実行環境でのものが選択されます。
### コンストラクタ(`std::time_t`)
```cpp
local_date(const std::time_t);
```
指定した値から`local_date`を構築します。
タイムゾーンは実行環境でのものが選択されます。
### `operator std::chrono::system_clock::time_point`
```cpp
operator std::chrono::system_clock::time_point() const;
```
`std::chrono::system_clock::time_point`に変換します。
タイムゾーンは実行環境でのものが選択されます。
時刻は0時00分とします。
### `operator std::time_t`
```cpp
operator std::time_t() const;
```
`std::time_t`に変換します。
タイムゾーンは実行環境でのものが選択されます。
時刻は0時00分とします。
## 非メンバ関数
### 比較演算子
```cpp
bool operator==(const local_date&, const local_date&);
bool operator!=(const local_date&, const local_date&);
bool operator< (const local_date&, const local_date&);
bool operator<=(const local_date&, const local_date&);
bool operator> (const local_date&, const local_date&);
bool operator>=(const local_date&, const local_date&);
```
日付の順序によって比較します。
### ストリーム出力演算子
```cpp
std::ostream& operator<<(std::ostream& os, const local_date& date);
```
TOMLのデフォルトのフォーマットで出力を行います。
### `to_string`
```cpp
std::string to_string(const local_date& date);
```
TOMLのデフォルトのフォーマットで文字列化します。
# `local_time`
```cpp
namespace toml
{
struct local_time
{
std::uint8_t hour; // [0, 23]
std::uint8_t minute; // [0, 59]
std::uint8_t second; // [0, 60]
std::uint16_t millisecond; // [0, 999]
std::uint16_t microsecond; // [0, 999]
std::uint16_t nanosecond; // [0, 999]
local_time(int h, int m, int s, int ms = 0, int us = 0, int ns = 0);
explicit local_time(const std::tm& t);
template<typename Rep, typename Period>
explicit local_time(const std::chrono::duration<Rep, Period>& t);
operator std::chrono::nanoseconds() const;
local_time() = default;
~local_time() = default;
local_time(local_time const&) = default;
local_time(local_time&&) = default;
local_time& operator=(local_time const&) = default;
local_time& operator=(local_time&&) = default;
};
bool operator==(const local_time& lhs, const local_time& rhs);
bool operator!=(const local_time& lhs, const local_time& rhs);
bool operator< (const local_time& lhs, const local_time& rhs);
bool operator<=(const local_time& lhs, const local_time& rhs);
bool operator> (const local_time& lhs, const local_time& rhs);
bool operator>=(const local_time& lhs, const local_time& rhs);
std::ostream& operator<<(std::ostream& os, const local_time& time);
std::string to_string(const local_time& time);
}
```
## メンバ変数
### `hour`
```cpp
std::uint8_t hour;
```
時間を表します。`0`から`23`の値を取ります。
### `minute`
```cpp
std::uint8_t minute; // [0, 59]
```
分を表します。`0`から`59`の値を取ります。
### `second`
```cpp
std::uint8_t second; // [0, 60]
```
秒を表します。`0`から`60`の値を取ります。
### `millisecond`
```cpp
std::uint16_t millisecond; // [0, 999]
```
ミリ秒を表します。`0`から`999`の値を取ります。
### `microsecond`
```cpp
std::uint16_t microsecond; // [0, 999]
```
マイクロ秒を表します。`0`から`999`の値を取ります。
### `nanosecond`
```cpp
std::uint16_t nanosecond; // [0, 999]
```
ナノ秒を表します。`0`から`999`の値を取ります。
## メンバ関数
### デフォルトコンストラクタ
```cpp
local_time() = default;
```
全ての値を`0`で初期化します。
### コンストラクタ(h, m, s, ms = 0, us = 0, ns = 0)
```cpp
local_time(int h, int m, int s, int ms = 0, int us = 0, int ns = 0);
```
指定された時刻を使って構築します。
境界チェックは行われません。
### コンストラクタ(`std::tm`)
```cpp
explicit local_time(const std::tm& t);
```
`std::tm``tm_hour`, `tm_min`, `tm_sec`を使って構築します。
サブセコンドは全て`0`で初期化されます。
### コンストラクタ(`std::chrono::duration`)
```cpp
template<typename Rep, typename Period>
explicit local_time(const std::chrono::duration<Rep, Period>& t);
```
`duration`をその日の0時からの時間として構築します。
### `operator std::chrono::nanoseconds`
```cpp
operator std::chrono::nanoseconds() const;
```
`std::chrono::nanoseconds`へ変換します。
## 非メンバ関数
### 比較演算子
```cpp
bool operator==(const local_time& lhs, const local_time& rhs);
bool operator!=(const local_time& lhs, const local_time& rhs);
bool operator< (const local_time& lhs, const local_time& rhs);
bool operator<=(const local_time& lhs, const local_time& rhs);
bool operator> (const local_time& lhs, const local_time& rhs);
bool operator>=(const local_time& lhs, const local_time& rhs);
```
時刻の値によって比較を行います。
### ストリーム演算子
```cpp
std::ostream& operator<<(std::ostream& os, const local_time& time);
```
TOMLのデフォルトのフォーマットで出力を行います。
### `to_string`
```cpp
std::string to_string(const local_time& time);
```
TOMLのデフォルトのフォーマットで文字列化します。
# `time_offset`
```cpp
namespace toml
{
struct time_offset
{
std::int8_t hour{0}; // [-12, 12]
std::int8_t minute{0}; // [-59, 59]
time_offset(int h, int m);
operator std::chrono::minutes() const;
time_offset() = default;
~time_offset() = default;
time_offset(time_offset const&) = default;
time_offset(time_offset&&) = default;
time_offset& operator=(time_offset const&) = default;
time_offset& operator=(time_offset&&) = default;
};
bool operator==(const time_offset&, const time_offset&);
bool operator!=(const time_offset&, const time_offset&);
bool operator< (const time_offset&, const time_offset&);
bool operator<=(const time_offset&, const time_offset&);
bool operator> (const time_offset&, const time_offset&);
bool operator>=(const time_offset&, const time_offset&);
std::ostream& operator<<(std::ostream& os, const time_offset& offset);
std::string to_string(const time_offset& offset);
}
```
## メンバ変数
### `hour`
```cpp
std::int8_t hour{0}; // [-12, 12]
```
時間のオフセットです。-12から+12の範囲の値を取ります。
### `minute`
```cpp
std::int8_t minute{0}; // [-59, 59]
```
分のオフセットです。-59から+59の範囲の値を取ります。
## メンバ関数
### コンストラクタ
```cpp
time_offset(int h, int m);
```
時間と分を取って構築します。
境界チェックは行いません。
### `operator std::chrono::minutes`
```cpp
operator std::chrono::minutes() const;
```
`std::chrono::minutes`への変換を行います。
## 非メンバ関数
### 比較演算子
```cpp
bool operator==(const time_offset&, const time_offset&);
bool operator!=(const time_offset&, const time_offset&);
bool operator< (const time_offset&, const time_offset&);
bool operator<=(const time_offset&, const time_offset&);
bool operator> (const time_offset&, const time_offset&);
bool operator>=(const time_offset&, const time_offset&);
```
時刻の長さで比較します。
### ストリーム出力演算子
```cpp
std::ostream& operator<<(std::ostream& os, const time_offset&);
```
TOMLのデフォルトのフォーマットで出力を行います。
### `to_string`
```cpp
std::string to_string(const time_offset&);
```
TOMLのデフォルトのフォーマットで文字列化します。
# `local_datetime`
```cpp
namespace toml
{
struct local_datetime
{
local_date date;
local_time time;
local_datetime(local_date d, local_time t);
explicit local_datetime(const std::tm& t);
explicit local_datetime(const std::chrono::system_clock::time_point& tp);
explicit local_datetime(const std::time_t t);
operator std::chrono::system_clock::time_point() const;
operator std::time_t() const;
local_datetime() = default;
~local_datetime() = default;
local_datetime(local_datetime const&) = default;
local_datetime(local_datetime&&) = default;
local_datetime& operator=(local_datetime const&) = default;
local_datetime& operator=(local_datetime&&) = default;
};
bool operator==(const local_datetime&, const local_datetime&);
bool operator!=(const local_datetime&, const local_datetime&);
bool operator< (const local_datetime&, const local_datetime&);
bool operator<=(const local_datetime&, const local_datetime&);
bool operator> (const local_datetime&, const local_datetime&);
bool operator>=(const local_datetime&, const local_datetime&);
std::ostream& operator<<(std::ostream& os, const local_datetime& dt);
std::string to_string(const local_datetime& dt);
}
```
## メンバ変数
### `local_date date`
```cpp
local_date date;
```
日付部分のデータを保持します。
### `local_time time`
```cpp
local_time time;
```
時刻部分のデータを保持します。
## メンバ関数
### デフォルトコンストラクタ
`date`, `time`の双方をデフォルト構築します。
### コンストラクタ(`local_date, local_time`)
指定された`date``time`で構築します。
### コンストラクタ(`std::tm`)
`std::tm`から構築します。
タイムゾーンは実行環境でのものが選択されます。
### コンストラクタ(`std::chrono::system_clock::time_point`)
`std::chrono::system_clock::time_point`から構築します。
タイムゾーンは実行環境でのものが選択されます。
### コンストラクタ(`std::time_t`)
`std::time_t`から構築します。
タイムゾーンは実行環境でのものが選択されます。
### `operator std::chrono::system_clock::time_point`
`std::chrono::system_clock::time_point`へ変換します。
### `operator std::time_t`
`std::time_t`へ変換します。
## 非メンバ関数
### 比較演算子
```cpp
bool operator==(const local_datetime&, const local_datetime&);
bool operator!=(const local_datetime&, const local_datetime&);
bool operator< (const local_datetime&, const local_datetime&);
bool operator<=(const local_datetime&, const local_datetime&);
bool operator> (const local_datetime&, const local_datetime&);
bool operator>=(const local_datetime&, const local_datetime&);
```
日付順で比較します。
### ストリーム出力演算子
```cpp
std::ostream& operator<<(std::ostream& os, const local_datetime&);
```
TOMLのデフォルトのフォーマットで出力を行います。
### `to_string`
```cpp
std::string to_string(const local_datetime&);
```
TOMLのデフォルトのフォーマットで文字列化します。
# `offset_datetime`
```cpp
namespace toml
{
struct offset_datetime
{
local_date date;
local_time time;
time_offset offset;
offset_datetime(local_date d, local_time t, time_offset o);
offset_datetime(const local_datetime& dt, time_offset o);
explicit offset_datetime(const local_datetime& ld);
explicit offset_datetime(const std::chrono::system_clock::time_point& tp);
explicit offset_datetime(const std::time_t& t);
explicit offset_datetime(const std::tm& t);
operator std::chrono::system_clock::time_point() const;
operator std::time_t() const;
offset_datetime() = default;
~offset_datetime() = default;
offset_datetime(offset_datetime const&) = default;
offset_datetime(offset_datetime&&) = default;
offset_datetime& operator=(offset_datetime const&) = default;
offset_datetime& operator=(offset_datetime&&) = default;
};
bool operator==(const offset_datetime&, const offset_datetime&);
bool operator!=(const offset_datetime&, const offset_datetime&);
bool operator< (const offset_datetime&, const offset_datetime&);
bool operator<=(const offset_datetime&, const offset_datetime&);
bool operator> (const offset_datetime&, const offset_datetime&);
bool operator>=(const offset_datetime&, const offset_datetime&);
std::ostream& operator<<(std::ostream& os, const offset_datetime& dt);
std::string to_string(const offset_datetime& dt);
}
```
## メンバ変数
### `date`
```cpp
local_date date;
```
日付部分のデータを保持します。
### `time`
```cpp
local_time time;
```
時刻部分のデータを保持します。
### `offset`
```cpp
time_offset offset;
```
オフセット部分のデータを保持します。
## メンバ関数
### デフォルトコンストラクタ
`date`, `time`, `offset`を全てデフォルト構築します。
### コンストラクタ(`local_date, local_time, time_offset`)
指定された`date`, `time`, `offset`で構築します。
### コンストラクタ(`local_datetime, time_offset`)
`local_datetime``offset`から構築します。
### コンストラクタ(`std::tm`)
`std::tm`から構築します。
タイムゾーンはUTC(00:00)になります。
### コンストラクタ(`std::chrono::system_clock::time_point`)
`std::chrono::system_clock::time_point`から構築します。
タイムゾーンはUTC(00:00)になります。
### コンストラクタ(`std::time_t`)
`std::time_t`から構築します。
タイムゾーンはUTC(00:00)になります。
### `operator std::chrono::system_clock::time_point`
`std::chrono::system_clock::time_point`へ変換します。
タイムゾーンはUTC(00:00)になります。
### `operator std::time_t`
`std::time_t`へ変換します。
タイムゾーンはUTC(00:00)になります。
## 非メンバ関数
### 比較演算子
```cpp
bool operator==(const offset_datetime&, const offset_datetime&);
bool operator!=(const offset_datetime&, const offset_datetime&);
bool operator< (const offset_datetime&, const offset_datetime&);
bool operator<=(const offset_datetime&, const offset_datetime&);
bool operator> (const offset_datetime&, const offset_datetime&);
bool operator>=(const offset_datetime&, const offset_datetime&);
```
日付順で比較します。
同じ日付の場合、タイムゾーン順で比較されます。
### ストリーム出力演算子
```cpp
std::ostream& operator<<(std::ostream& os, const offset_datetime&);
```
TOMLのデフォルトのフォーマットで出力を行います。
### `to_string`
```cpp
std::string to_string(const offset_datetime&);
```
TOMLのデフォルトのフォーマットで文字列化します。

View File

@@ -0,0 +1,151 @@
+++
title = "error_info.hpp"
type = "docs"
+++
# error_info.hpp
`error_info.hpp`では、`error_info`と、それをフォーマットする関数が定義されます。
# `toml::error_info`
```cpp
namespace toml
{
struct error_info
{
error_info(std::string t, source_location l, std::string m, std::string s = "");
error_info(std::string t, std::vector<std::pair<source_location, std::string>> l, std::string s = "");
std::string const& title() const noexcept;
std::string & title() noexcept;
std::vector<std::pair<source_location, std::string>> const& locations() const noexcept;
void add_locations(source_location loc, std::string msg) noexcept;
std::string const& suffix() const noexcept;
std::string & suffix() noexcept;
};
template<typename ... Ts>
error_info make_error_info(
std::string title, source_location loc, std::string msg, Ts&& ... tail);
std::string format_error(const std::string& errkind, const error_info& err);
std::string format_error(const error_info& err);
template<typename ... Ts>
std::string format_error(std::string title,
source_location loc, std::string msg, Ts&& ... tail);
std::ostream& operator<<(std::ostream& os, const error_info& e);
}
```
## メンバ関数
### コンストラクタ(`title, loc, msg, suffix`)
指定されたタイトル、位置情報、メッセージ、suffixから`error_info`を構築します。
`suffix`はデフォルトで空です。
### コンストラクタ(`title, [{loc, msg}, ...], suffix`)
指定されたタイトル、位置情報とメッセージの配列、そして`suffix`から`error_info`を構築します。
`suffix`はデフォルトで空です。
## メンバ関数
### `std::string title()`
エラーメッセージのタイトルです。
### `std::vector<std::pair<source_location, std::string>> locations()`
エラーの発生した位置とそれに関するメッセージです。
複数指定可能です。
### `std::string suffix()`
最後に表示するメッセージです。ヒントや補足を表示します。
## 非メンバ関数
### `make_error_info`
```cpp
template<typename ... Ts>
error_info make_error_info(
std::string title, source_location loc, std::string msg, Ts&& ... tail);
```
新しく`error_info`を構築します。
`source_location`または`basic_value`の後には、それに関する`msg`が続かなければなりません。
[`value.hpp`]({{<ref "docs/reference/value#tomlmake_error_info">}})
では、 `source_location` の代わりに `toml::basic_value` を渡した際のオーバーロードが追加されます。
末尾には`suffix`を渡すことが可能です。
### `format_error`
`error_info` を以下のようにフォーマットします。
```
{title}
--> {locations().at(0).first.file_name()}
|
1 | {locations().at(0).first.line()}
| ^-- {locations().at(0).second}
|
2 | {locations().at(1).first.line()}
| ^-- {locations().at(1).second}
{suffix}
```
二つの `source_location` のファイル名が異なる場合は、ファイル名が再度表示されます。
```cpp
std::string format_error(const std::string& errkind, const error_info& err);
std::string format_error(const error_info& err);
```
`error_info`をフォーマットします。
`errkind`が与えられなかった場合、赤色太字の`[error]``title`の前につけ足されます。
`errkind`が与えられた場合(空文字列の場合も含みます)、それが`[error]`の代わりに表示されます。
```cpp
namespace toml
{
template<typename ... Ts>
std::string format_error(std::string title,
source_location loc, std::string msg, Ts&& ... tail);
} // toml
```
`make_error_info` を使って作成した `error_info``format_error` でフォーマットした文字列を返します。
[`value.hpp`]({{<ref "docs/reference/value#tomlformat_error">}})
では、 `source_location` の代わりに `toml::basic_value` を渡した際のオーバーロードが追加されます。
### ストリーム演算子
```cpp
std::ostream& operator<<(std::ostream& os, const error_info& e);
```
`format_error(e)`を呼び出し、それを出力します。
# 関連項目
- [color.hpp]({{<ref "color.md">}})
- [parser.hpp]({{<ref "parser.md">}})
- [source_location.hpp]({{<ref "source_location.md">}})

View File

@@ -0,0 +1,41 @@
+++
title = "exception.hpp"
type = "docs"
+++
# exception.hpp
# `toml::exception`
toml11で定義される例外型の基底クラスです。
```cpp
namespace toml
{
struct exception : public std::exception
{
public:
virtual ~exception() noexcept override = default;
virtual const char* what() const noexcept override {return "";}
};
} // toml
```
## メンバ関数
### デストラクタ
```cpp
virtual ~exception() noexcept override = default;
```
派生する際に上書きします。
### `what`
```cpp
virtual const char* what() const noexcept override {return "";}
```
エラーメッセージを返します。派生する際に上書きします。

View File

@@ -0,0 +1,251 @@
+++
title = "find.hpp"
type = "docs"
+++
# find.hpp
`toml::value`から値を検索し、同時に(必要な場合)型変換を行う関数です。
{{< hint info >}}
`toml::value` は格納する型を変更でき、`toml::find`はそれらに対応しているので、
厳密には全て `toml::basic_value<TC>` が使われています。ただしこれでは冗長なので、
関数の宣言と特に区別しなければならない場合を除いて、簡単のため説明文では `toml::value` と書きます。
説明文では、テンプレートパラメータ`TC`を変更して型が変更されていれば
`toml::value::integer_type` などの型は追従して変更されると解釈してください。
{{< /hint >}}
# `toml::find`
## 概要
`toml::find`には、取り出したい型をテンプレート引数で、検索したい値のキーを引数で与えます。
```cpp
template<typename T, typename TC, typename ... Keys>
T find(const basic_value<TC>& v, Keys ... keys);
```
サポートされている `T` の種類と変換の挙動に関しては、 `toml::get` と同様です。
`T` が指定されなかった場合、 `toml::value` が返されます。
キーは、 `toml::value::key_type` または `std::size_t` です。
複数個のキーが与えられた場合は、サブテーブルや配列に対して再帰的に検索が行われます。
`toml::value::key_type` が与えられた場合は `toml::table` として、 `std::size_t` が与えられた場合は `toml::array` として解釈されます。
### 再帰的な検索に関しての注意
TOMLには通常の bare key の他に、 `"``'` で囲まれた quoted key というものがあります。
quoted key を使うと、 `"foo.bar" = "baz"` というようなキーを書くことができ、この場合はサブテーブルは構築されず、キーは `foo.bar`となります。
このようなパターンに対応するため、toml11ではキーの中に`.`が含まれていても分割は行わず、そのままの文字列で検索を行います。
以下のTOMLファイルを考えます。
```toml
[foo]
[foo.bar]
baz = "hoge"
["foo.bar"]
baz = "fuga"
```
これに対応する`toml::find`の書き方は以下の通りです。
```cpp
const auto input = toml::parse("input.toml");
const auto baz1 = toml::find<std::string>(input, "foo", "bar", "baz"); // hoge
const auto baz2 = toml::find<std::string>(input, "foo.bar", "baz"); // fuga
```
参考:[toml.io/ja/v1.0.0#キー](https://toml.io/ja/v1.0.0#%E3%82%AD%E3%83%BC)
## `toml::find(value, key)`
`value``toml::table` として `key` を検索したあと、 `toml::get` で変換を行います。
```cpp
template<typename T, typename TC>
/* toml::get<T>(const value&) と同等 */ find(
const basic_value<TC>& v, const typename basic_value<TC>::key_type& ky);
template<typename T, typename TC>
/* toml::get<T>(value&) と同等 */ find(
basic_value<TC>& v, const typename basic_value<TC>::key_type& ky);
template<typename T, typename TC>
/* toml::get<T>(value&&) と同等 */ find(
basic_value<TC>&& v, const typename basic_value<TC>::key_type& ky);
```
`T`が指定されない場合は、変換を行わず`toml::value`を返します。
```cpp
template<typename TC>
basic_value<TC> const& find(
basic_value<TC> const& v, const typename basic_value<TC>::key_type& ky);
template<typename TC>
basic_value<TC>& find(
basic_value<TC>& v, const typename basic_value<TC>::key_type& ky);
template<typename TC>
basic_value<TC> find(
basic_value<TC>&& v, const typename basic_value<TC>::key_type& ky);
```
### 例外
`toml::value``table` を保持していなかった場合、 `toml::type_error` が送出されます。
格納している `table` が指定された要素を持っていなかった場合、 `std::out_of_range` が送出されます。
指定された要素が `T` に変換できない場合 `toml::get` が変換に失敗する場合) 、
`toml::type_error` が送出されます。
## `toml::find(value, index)`
`value``toml::array` として `index` 番目にアクセスし、 `toml::get` で変換を行います。
```cpp
template<typename T, typename TC>
/* toml::get<T>(const value&) と同等 */ find(
const basic_value<TC>& v, const std::size_t index);
template<typename T, typename TC>
/* toml::get<T>(value&) と同等 */ find(
basic_value<TC>& v, const std::size_t index);
template<typename T, typename TC>
/* toml::get<T>(value&&) と同等 */ find(
basic_value<TC>&& v, const std::size_t index);
```
`T`が指定されない場合は、変換を行わず`toml::value`を返します。
```cpp
template<typename TC>
basic_value<TC> const& find(basic_value<TC> const& v, const std::size_t ky);
template<typename TC>
basic_value<TC>& find(basic_value<TC>& v, const std::size_t ky);
template<typename TC>
basic_value<TC> find(basic_value<TC>&& v, const std::size_t ky);
```
### 例外
`toml::value``array` を保持していなかった場合、 `toml::type_error` が送出されます。
格納している `array` が指定された数の要素を持っていなかった場合、`std::out_of_range`が送出されます。
指定された要素が `T` に変換できない場合 `toml::get` が変換に失敗する場合) 、
`toml::type_error` が送出されます。
## `toml::find(value, keys...)`
```cpp
template<typename T, typename TC, typename K1, typename K2, typename ... Ks>
/* toml::get<T>(const value&) と同等 */ find(
const basic_value<TC>& v, const K1& k1, const K2& k2, const Ks& ... ks);
template<typename T, typename TC, typename K1, typename K2, typename ... Ks>
/* toml::get<T>(value&) と同等 */ find(
basic_value<TC>& v, const K1& k1, const K2& k2, const Ks& ... ks);
template<typename T, typename TC, typename K1, typename K2, typename ... Ks>
/* toml::get<T>(value&&) と同等 */ find(
basic_value<TC>&& v, const K1& k1, const K2& k2, const Ks& ... ks);
```
再帰的に`toml::find`が呼び出されます。
失敗する条件とその際に送出される例外は `toml::find` と同じです。
# `toml::find_or(value, key, fallback)`
```cpp
template<typename T, typename TC, typename Key>
T find_or(const basic_value<TC>& v, const Key& key, T&& opt);
```
`find_or` は失敗した際のためのデフォルト値を受け取ることで、失敗時に例外を投げないようにします。
このデフォルト値は受け取る型`T`と同じ型でなければなりません。
よって、 `toml::find<T>` とは違って、 `find_or` では `T` を指定せずとも推論されます。
`find_or<T>`のように `T` を指定することもできますが、その場合は常に新規な値が返されます。
参照を取得したい場合は、 `T` を指定しないでください。
## `T`が`basic_value`である場合
```cpp
template<typename TC, typename K>
basic_value<TC>& find_or(basic_value<TC>& v, const K& key, basic_value<TC>& opt) noexcept
template<typename TC, typename K>
basic_value<TC> const& find_or(const basic_value<TC>& v, const K& key, const basic_value<TC>& opt) noexcept
```
対応する値を検索し、変換せずに返します。変換が必要ないため、参照を返すことができます。
値が見つからなかった場合、デフォルト値を返します。
## `T`が`toml::value::{some_type}`である場合
```cpp
template<typename T, typename TC, typename K>
T& find_or(basic_value<TC>& v, const K& key, T& opt) noexcept
template<typename T, typename TC, typename K>
T const& find_or(const basic_value<TC>& v, const K& key, const T& opt) noexcept
```
対応する値を検索し、変換せずに返します。変換が必要ないため、参照を返すことができます。
値が見つからなかった場合、あるいは異なる型が格納されていた場合、デフォルト値を返します。
## `T`が`const char*`である場合
```cpp
template<typename TC, typename K>
std::string find_or(const basic_value<TC>& v, const K& k, const char* opt)
```
対応する値を検索し、 `std::string` として返します。
失敗時に `const char*` から `std::string` を構築するため、参照を返すことはできません。
## `T`がその他の型である場合
```cpp
template<typename T, typename TC, typename K>
T find_or(const basic_value<TC>& v, const K& key, T opt)
```
対応する値を検索し、 `T` に変換して返します。
変換を行うため、参照を返すことはできません。
## 複数のキーが与えられた場合
```cpp
template<typename Value, typename K1, typename K2, typename K3, typename ... Ks>
auto find_or(Value&& v, const K1& k1, const K2& k2, K3&& k3, Ks&& ... keys) noexcept
-> decltype(find_or(v, k2, std::forward<K3>(k3), std::forward<Ks>(keys)...))
```
キーの列の最後の要素がデフォルト値であると解釈して、再帰的に`find_or`を適用します。
`T` の推論結果が `toml::value` または `toml::value::some_type` になる場合、参照を返すことができます。
`T` を明示的に指定した場合、常に変換を行います。
# 関連項目
- [get.hpp]({{<ref "get.md">}})
- [value.hpp]({{<ref "value.md">}})

View File

@@ -0,0 +1,448 @@
+++
title = "format.hpp"
type = "docs"
+++
# format.hpp
`toml::value`のフォーマット情報を持つ構造体と列挙型を定義します。
# `indent_char`
インデント情報を表す列挙体です。
```cpp
enum class indent_char : std::uint8_t
{
space, // use space
tab, // use tab
none // no indent
};
std::ostream& operator<<(std::ostream& os, const indent_char& c);
std::string to_string(const indent_char);
```
`none`を選んだ場合、super tableでの値によらず、インデントは使用されません。
シリアライズ対象の値のなかに`space``tab`を指定する値が同時に存在していた場合、その動作は未規定で、指定していない方の文字が出現する可能性があります。
# `boolean_format_info`
`boolean`のフォーマット情報です。
```cpp
struct boolean_format_info {};
bool operator==(const boolean_format_info&, const boolean_format_info&) noexcept;
bool operator!=(const boolean_format_info&, const boolean_format_info&) noexcept;
```
`boolean`のフォーマット方法は一通りしかないため、設定できる値を持ちません。
# `integer_format`
```cpp
enum class integer_format : std::uint8_t
{
dec = 0,
bin = 1,
oct = 2,
hex = 3,
};
std::ostream& operator<<(std::ostream& os, const integer_format f);
std::string to_string(const integer_format);
```
`integer`の基数を指定します。
# `integer_format_info`
```cpp
struct integer_format_info
{
integer_format fmt = integer_format::dec;
std::size_t width = 0; // minimal width (may exceed)
std::size_t spacer = 0; // position of `_` (if 0, no spacer)
std::string suffix = ""; // _suffix (library extension)
};
bool operator==(const integer_format_info&, const integer_format_info&) noexcept;
bool operator!=(const integer_format_info&, const integer_format_info&) noexcept;
```
## メンバ変数
### `integer_format fmt`
基数を指定します。
### `std::size_t width`
最小の幅を指定します。値によってはこの幅を超えることがあります。
フォーマットした値がこの幅よりも小さい場合、`integer_format::dec`の場合は効果はありませんが、それ以外の場合は先頭にリーディング`0`が追加されます。
### `std::size_t spacer`
アンダースコア`_`を追加する幅を指定します。
`3`の場合`1_234_567`のように、`4`の場合`0xdead_beef`のようにフォーマットされます。
`0`の場合、アンダースコアは挿入されません。
不規則な幅を指定することはできません。
### `std::string suffix`
toml11拡張の`spec::ext_num_suffix``true`にしている場合、その`suffix`がここに保存されます。
参考:[spec.hpp]({{<ref "spec.md">}})
# `floating_format`
```cpp
enum class floating_format : std::uint8_t
{
defaultfloat = 0,
fixed = 1, // does not include exponential part
scientific = 2, // always include exponential part
hex = 3 // hexfloat extension
};
std::ostream& operator<<(std::ostream& os, const floating_format f);
std::string to_string(const floating_format);
```
`floating`のフォーマット形式を指定します。
それぞれ、`std::defaultfloat`, `std::fixed`, `std::scientific`, `std::hexfloat`に対応します。
`hexfloat`は、`toml::spec::ext_hex_float``true`の場合のみ使用可能です。
参考:[spec.hpp]({{<ref "spec.md">}})
# `floating_format_info`
```cpp
struct floating_format_info
{
floating_format fmt = floating_format::defaultfloat;
std::size_t prec = 0; // precision (if 0, use the default)
std::string suffix = ""; // 1.0e+2_suffix (library extension)
};
bool operator==(const floating_format_info&, const floating_format_info&) noexcept;
bool operator!=(const floating_format_info&, const floating_format_info&) noexcept;
```
## メンバ変数
### `floating_format fmt`
フォーマット形式を指定します。
### `std::size_t prec`
小数点以下の精度を指定します。
### `std::string suffix`
toml11拡張の`spec::ext_num_suffix``true`にしている場合、その`suffix`がここに保存されます。
参考:[spec.hpp]({{<ref "spec.md">}})
# `string_format`
```cpp
enum class string_format : std::uint8_t
{
basic = 0,
literal = 1,
multiline_basic = 2,
multiline_literal = 3
};
std::ostream& operator<<(std::ostream& os, const string_format f);
std::string to_string(const string_format);
```
文字列のフォーマット形式を指定します。
# `string_format_info`
```cpp
struct string_format_info
{
string_format fmt = string_format::basic;
bool start_with_newline = false;
};
bool operator==(const string_format_info&, const string_format_info&) noexcept;
bool operator!=(const string_format_info&, const string_format_info&) noexcept;
```
## メンバ変数
### `string_format fmt`
文字列のフォーマット情報を指定します。
### `bool start_with_newline`
`multiline_basic`または`multiline_literal`の場合、最初の`"""``'''`の後に改行を入れるかどうかを指定します。
# `datetime_delimiter_kind`
```cpp
enum class datetime_delimiter_kind : std::uint8_t
{
upper_T = 0,
lower_t = 1,
space = 2,
};
std::ostream& operator<<(std::ostream& os, const datetime_delimiter_kind d);
std::string to_string(const datetime_delimiter_kind);
```
`datetime`で日付と時刻の間のデリミタにどの文字を使うかを指定します。
`T`, `t`, ` `が使用可能です。
# `offset_datetime_format_info`
```cpp
struct offset_datetime_format_info
{
datetime_delimiter_kind delimiter = datetime_delimiter_kind::upper_T;
bool has_seconds = true;
std::size_t subsecond_precision = 6; // [us]
};
bool operator==(const offset_datetime_format_info&, const offset_datetime_format_info&) noexcept;
bool operator!=(const offset_datetime_format_info&, const offset_datetime_format_info&) noexcept;
```
## メンバ変数
### `datetime_delimiter_kind delimiter`
使用するデリミタを指定します。
### `bool has_seconds`
秒数を省略するかどうかを指定します。
### `std::size_t subsecond_precision`
秒以下の精度を何桁出力するかを指定します。
# `local_datetime_format_info`
```cpp
struct local_datetime_format_info
{
datetime_delimiter_kind delimiter = datetime_delimiter_kind::upper_T;
bool has_seconds = true;
std::size_t subsecond_precision = 6; // [us]
};
bool operator==(const local_datetime_format_info&, const local_datetime_format_info&) noexcept;
bool operator!=(const local_datetime_format_info&, const local_datetime_format_info&) noexcept;
```
## メンバ変数
### `datetime_delimiter_kind delimiter`
使用するデリミタを指定します。
### `bool has_seconds`
秒数を省略するかどうかを指定します。
### `std::size_t subsecond_precision`
秒以下の精度を何桁出力するかを指定します。
# `local_date_format_info`
```cpp
struct local_date_format_info
{
// nothing, for now
};
bool operator==(const local_date_format_info&, const local_date_format_info&) noexcept;
bool operator!=(const local_date_format_info&, const local_date_format_info&) noexcept;
```
`local_datetime`にはフォーマット指定するパラメータはありません。
# `local_time_format_info`
```cpp
struct local_time_format_info
{
bool has_seconds = true;
std::size_t subsecond_precision = 6; // [us]
};
bool operator==(const local_time_format_info&, const local_time_format_info&) noexcept;
bool operator!=(const local_time_format_info&, const local_time_format_info&) noexcept;
```
## メンバ変数
### `bool has_seconds`
秒数を省略するかどうかを指定します。
### `std::size_t subsecond_precision`
秒以下の精度を何桁出力するかを指定します。
# `array_format`
```cpp
enum class array_format : std::uint8_t
{
default_format = 0,
oneline = 1,
multiline = 2,
array_of_tables = 3 // [[format.in.this.way]]
};
std::ostream& operator<<(std::ostream& os, const array_format f);
std::string to_string(const array_format);
```
- `default_format`
- 適したフォーマットを自動的に選択します。ある程度長い配列は複数行になります。
- `oneline`
- 全ての要素を一行でフォーマットします。
- `multiline`
- 一行ごとに一つの要素を出力します。
- `array_of_tables`
- `[[array.of.tables]]`の形式でフォーマットします。`table`以外の要素を含むことはできません。
# `array_format_info`
```cpp
struct array_format_info
{
array_format fmt = array_format::default_format;
indent_char indent_type = indent_char::space;
std::int32_t body_indent = 4; // indent in case of multiline
std::int32_t closing_indent = 0; // indent of `]`
};
bool operator==(const array_format_info&, const array_format_info&) noexcept;
bool operator!=(const array_format_info&, const array_format_info&) noexcept;
```
## メンバ変数
### `array_format fmt`
フォーマット形式を指定します。
### `indent_char indent_type`
インデントに使用する文字の種類を選択します。
### `std::int32_t body_indent`
`array_format::multiline`の場合、要素の前に出力するインデントの文字数を指定します。
### `std::int32_t closing_indent`
`array_format::multiline`の場合、閉じ括弧`]`の前に出力するインデントの文字数を指定します。
# `table_format`
```cpp
enum class table_format : std::uint8_t
{
multiline = 0, // [foo] \n bar = "baz"
oneline = 1, // foo = {bar = "baz"}
dotted = 2, // foo.bar = "baz"
multiline_oneline = 3, // foo = { \n bar = "baz" \n }
implicit = 4 // [x] defined by [x.y.z]. skip in serializer.
};
std::ostream& operator<<(std::ostream& os, const table_format f);
std::string to_string(const table_format);
```
- `multiline`
- 複数行の通常のテーブルとしてフォーマットします。
- `oneline`
- インラインテーブルとしてフォーマットします。
- `dotted`
- `a.b.c = "d"`の形式でフォーマットします。
- `multiline_oneline`
- 改行を含むインラインテーブルとしてフォーマットします。TOML v1.1.0以降で使用可能です。
- 参考:[spec.hpp]({{<ref "spec.md">}})
- `implicit`
- `[x.y.z.w]`だけが定義されている際の`[x]`, `[x.y]`, `[x.y.z]`のように、暗黙定義としてスキップします。
{{< hint warning >}}
TOMLの文法上、`dotted`はサブテーブルを持つことができます。
```toml
[fruit]
apple.color = "red"
apple.taste.sweet = true
# [fruit.apple] # INVALID
# [fruit.apple.taste] # INVALID
[fruit.apple.texture] # you can add sub-tables
smooth = true
```
toml11は現時点ではこのフォーマットに対応していません。
`dotted`テーブルの下にあるテーブルは全て`dotted`になり、テーブルは強制的にインラインテーブルになります。
{{< /hint >}}
# `table_format_info`
```cpp
struct table_format_info
{
table_format fmt = table_format::multiline;
indent_char indent_type = indent_char::space;
std::int32_t body_indent = 0; // indent of values
std::int32_t name_indent = 0; // indent of [table]
std::int32_t closing_indent = 0; // in case of {inline-table}
};
bool operator==(const table_format_info&, const table_format_info&) noexcept;
bool operator!=(const table_format_info&, const table_format_info&) noexcept;
```
## メンバ変数
### `table_format fmt`
フォーマット方法を指定します。
### `indent_char indent_type`
インデントに使用する文字を指定します。
### `std::int32_t body_indent`
キーの前に出力するインデントの幅を指定します。
スーパーテーブルのインデント幅は加算されません。
### `std::int32_t name_indent`
`[table]`形式のキーのインデントを指定します。
スーパーテーブルのインデント幅は加算されません。
### `std::int32_t closing_indent`
`multiline_oneline`の場合に、閉じ括弧`}`の前のインデント幅を指定します。

View File

@@ -0,0 +1,55 @@
+++
title = "from.hpp"
type = "docs"
+++
# from.hpp
`toml::get``toml::find`で使用する、`toml::value`からの変換を定義する構造体です。
メンバ関数に`from_toml`を追加することによっても同じ機能を追加できますが、メンバ関数を追加できないクラスに対しては`from<T>`を使用してください。
このファイルでは特定の実装は提供しません。使用する際に、この構造体を特殊化してください。
```cpp
namespace toml
{
template<typename T>
struct from;
} // toml
```
## 例
```cpp
namespace extlib
{
struct foo
{
int a;
std::string b;
};
} // extlib
#include <toml11/from.hpp>
namespace toml
{
template<>
struct from<extlib::foo>
{
template<typename TC>
static extlib::foo from_toml(const toml::basic_value<TC>& v)
{
return extlib::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
}
};
} // toml
```
# 関連項目
- [conversion.hpp]({{<ref "conversion.md">}})
- [into.hpp]({{<ref "into.md">}})

View File

@@ -0,0 +1,444 @@
+++
title = "get.hpp"
type = "docs"
+++
# get.hpp
`toml::value`から値を取り出し、同時に(必要な場合)型変換を行う関数です。
{{< hint info >}}
`toml::value` は格納する型を変更でき、`toml::get`はそれらに対応しているので、
厳密には全て `toml::basic_value<TC>` が使われています。ただしこれでは冗長なので、
関数の宣言と特に区別しなければならない場合を除いて、簡単のため説明文では `toml::value` と書きます。
説明文では、テンプレートパラメータ`TC`を変更して型が変更されていれば
`toml::value::integer_type` などの型は追従して変更されると解釈してください。
{{< /hint >}}
# `toml::get<T>`
## 概要
基本的に、`toml::get`は以下のような関数として振る舞います。
`T``toml::get<int>(v)`のようにして与えます。
```cpp
template<typename T, typename TC>
T get(const basic_value<TC>& v);
```
ただし、`T`がどのような型であるかによって、`toml::get`は異なる挙動をします。
`T`の型の種類は、
1. 変換が必要ない型
2. 変換する必要がある型
に分けられます。
細かい条件と、特別にサポートしている具体的な型については後述します。
### 変換が必要ない型
変換が必要ないのは、渡された `toml::value` が格納している型です。
例えば、 `toml::value::integer_type``std::int64_t` のエイリアスなので、
`toml::get<std::int64_t>(v)` は変換を必要としません。
この場合、 `toml:get``integer` の値を `toml::value` から取り出し、その参照を返します。
渡された`toml::value`が可変参照(`&`)である場合、返す値も可変参照(`&`)です。
不変参照(`const&`)の場合、返す値も不変参照(`const&`)となります。
可変参照を返した場合、その参照を通して`toml::value`に格納されている値に上書きできます。
### 変換が必要な型
上記の型以外については変換が必要です。
例えば、`toml::value::integer_type``std::int64_t`のエイリアスなので、`toml::get<std::size_t>(toml::value&)`は変換が必要です。
この場合、`toml:get``integer`の値を`toml::value`から取り出し、それをキャストして返します。
toml11は簡単なキャストだけでなく、
`toml::array`からや`std::tuple<int, double, std::string>``std::array<double, 4>`
`toml::table`から`std::map<std::string, int>`などの複雑な型変換をサポートします。
具体的には、続くセクションを参照してください。
### 失敗した場合
期待した型変換を行えない場合があります。例えば、`table`を持っている`toml::value``toml::get<int>(v)`を適用した場合などです。
このような場合は、取り出そうとした型に最も似ている型への変換(今回は`int`なので、`as_integer`)が失敗したとして、`toml::type_error`が送出されます。
ファイルからパースした場合、以下のようなエラーメッセージが出力されます。
```
terminate called after throwing an instance of 'toml::type_error'
what(): toml::value::as_integer(): bad_cast to integer
--> input.toml
|
6 | [fruit]
| ^^^^^^^-- the actual type is table
```
## `T`が`toml::value`と同一のとき
```cpp
template< T, typename TC>
T& get(basic_value<TC>& v);
template<typename T, typename TC>
T const& get(const basic_value<TC>& v);
template<typename T, typename TC>
T get(basic_value<TC>&& v);
```
条件:
- `std::is_same<T, basic_value<TC>>` を満たす
`toml::value`から`toml::value`なので、変換は行われず、そのままの値が返されます。
他の関数の実装を一般化するためだけに存在しています。
失敗しません。
## `T`が`toml::value::{some_type}`のいずれかのとき
```cpp
template<typename T, typename TC>
T& get(basic_value<TC>& v);
template<typename T, typename TC>
T const& get(const basic_value<TC>& v);
template<typename T, typename TC>
T get(basic_value<TC>&& v);
```
条件:
- `T``toml::value`が格納できる型(`toml::value::boolean_type`など)のどれかと同一であること
`toml::value` が格納している型と同じ型、例えば `toml::value::integer_type`
`toml::get<T>``T` として指定されたとき、型変換の必要がないため参照を返すことが可能です。
異なる型が格納されていた場合、`toml::type_error` が送出されます。
## `T`が異なる`TypeConfig`を持つ`basic_value<OtherTC>`のとき
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `T``toml::basic_value<TC>`ではない
- `T``toml::basic_value<OtherTC>`である
異なる型を格納し得る`basic_value`が指定された場合、変換が行われます。
型変換が発生するので、返す値は新規な値であり、参照ではありません。
失敗しません(メモリ枯渇などの場合を除く)。
## `T`が整数型の場合
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `std::is_integral<T>` を満たす
- `std::is_same<T, bool>` ではない
- `toml::value::integer_type` ではない
`toml::value``integer_type` を保持しているとしてその値を取得し、それを `T` に変換して返します。
`toml::value::integer_type` 以外の型が格納されていた場合、 `toml::type_error` が送出されます。
## `T`が浮動小数点数型の場合
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `std::is_floating_point<T>` を満たす
- `toml::value::floating_type` ではない
`toml::value``floating_type`を保持しているとしてその値を取得し、それを`T`に変換して返します。
`toml::value::floating_type` 以外の型が格納されていた場合、 `toml::type_error` が送出されます。
## `T`が`std::string_view`の場合
C++17以降でのみ使用可能です。
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `std::is_same<std::string_view, T>` を満たす
`toml::value``string_type`を保持しているとしてその値を取得し、それから`std::string_view`を構築して返します。
`toml::value::string_type` 以外の型が格納されていた場合、 `toml::type_error` が送出されます。
## `T`が`std::chrono::duration`の場合
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `T``std::chrono::duration<Rep, Period>`である
`toml::value``local_time`を保持しているとしてその値を取得し、それを`std::chrono::duration`に変換して返します。
`toml::value::local_time` 以外の型が格納されていた場合、 `toml::type_error` が送出されます。
## `T`が`std::chrono::system_clock::time_point`の場合
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `std::is_same<T, std::chrono::system_clock::time_point>`を満たす
`toml::value``local_date`, `local_datetime`, `offset_datetime`のどれかを保持しているとしてその値を取得し、それを`std::chrono::system_clock::time_point`に変換して返します。
`local_date`, `local_datetime`, `offset_datetime` 以外の型が格納されていた場合、 `toml::type_error` が送出されます。
## `T`が`array-like`である場合
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `T``T::iterator`を持つ
- `T``T::value_type`を持つ
- `T``T::push_back(x)`を持つ
- `T``toml::value::array_type`ではない
- `T``std::string`ではない
- `T``std::string_view`ではない
- `T``map-like`ではない
- `T``from_toml()`メンバ関数を持たない
- `toml::from<T>`が定義されていない
- `toml::basic_value<TC>`からのコンストラクタが定義されていない
`std::vector<int>``std::deque<std::string>`などが該当します。
`toml::value``array`を保持しているとしてその値を取得し、それを指定されたコンテナに変換して返します。
`toml::value::array_type` 以外の型が格納されていた場合、 `toml::type_error` が送出されます。
## `T`が`std::array`である場合
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `T``std::array<U, N>`である
`toml::value``array`を保持しているとしてその値を取得し、それを指定されたコンテナに変換して返します。
`toml::value::array_type` 以外の型が格納されていた場合、 `toml::type_error` が送出されます。
`toml::value` が持つ `array` が十分な数の要素を持っていなかった場合、`std::out_of_range`が送出されます。
## `T`が`std::forward_list`である場合
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `T``std::forward_list<U>`である
`toml::value``array`を保持しているとしてその値を取得し、それを`std::forward_list`に変換して返します。
`toml::value::array_type` 以外の型が格納されていた場合、 `toml::type_error` が送出されます。
`forward_list``push_back`を持たないので、別に実装されています。
## `T`が`std::pair`である場合
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `T``std::pair<T1, T2>`である
`toml::value``array`を保持しているとしてその値を取得し、それを`std::pair<T1, T2>`に変換して返します。
`first``second` はそれぞれ再帰的に変換されます。
`toml::value::array_type` 以外の型が格納されていた場合、 `toml::type_error` が送出されます。
`toml::value` が持つ `array` の要素数がちょうど2個でなかった場合、`std::out_of_range`が送出されます。
## `T`が`std::tuple`である場合
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `T``std::tuple<T1, T2, ... TN>`である
`toml::value``array`を保持しているとしてその値を取得し、それを`std::tuple<T1, T2, ...TN>`に変換して返します。
各要素はそれぞれ再帰的に変換されます。
`toml::value::array_type` 以外の型が格納されていた場合、 `toml::type_error` が送出されます。
`toml::value` が持つ `array` の要素数がちょうど `std::tuple_size<T>::value` 個でなかった場合、`std::out_of_range`が送出されます。
## `T`が`map-like`である場合
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `T``T::iterator`を持つ
- `T``T::key_type`を持つ
- `T``T::value_type`を持つ
- `T``T::mapped_type`を持つ
- `T``toml::value::table_type`ではない
- `T``from_toml()`メンバ関数を持たない
- `toml::from<T>`が定義されていない
- `toml::basic_value<TC>`からのコンストラクタが定義されていない
`std::map<std::string, int>``std::unordered_map<std::string, float>`などが該当します。
`toml::value``table`を保持しているとしてその値を取得し、それを `T` に変換して返します。
各要素はそれぞれ再帰的に変換されます。
`basic_value::table_type` 以外の型が格納されていた場合、 `toml::type_error` が送出されます。
## `T`が`toml::from<T>`の特殊化を持つユーザー定義型である場合
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `toml::from<T>`が定義されている
`toml::from``T` に対する特殊化が定義されていた場合、それを使用した型変換が行われます。
個別にサポートされる型( `std::array`, `std::pair`, `std::tuple` )と衝突しないようにしてください。
## `T`が`T::from_toml`メンバ関数を持つユーザー定義型である場合
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `toml::from<T>`が定義されていない
- `T``from_toml()`メンバ関数を持つ
`T``from_toml(toml::basic_value<TC>)` メンバ関数が定義されていた場合、それを使用した型変換が行われます。
`toml::from<T>` が定義されていると、そちらが優先されます。
## `T`が`toml::basic_value<TC>`を取るコンストラクタを持つユーザー定義型である場合
```cpp
template<typename T, typename TC>
T get(basic_value<TC>& v);
```
条件:
- `toml::from<T>`が定義されていない
- `T``from_toml()`メンバ関数を持たない
- `T``toml::basic_value<TC>`を取るコンストラクタを持つ
`T``toml::basic_value<TC>` を取るコンストラクタが定義されていた場合、それを使用した型変換が行われます。
`toml::from<T>` または `T::from_toml` が定義されていると、そちらが優先されます。
# `toml::get_or<T>`
`get_or` は失敗した際のためのデフォルト値を受け取ることで、失敗時に例外を投げないようにします。
このデフォルト値は受け取る型`T`と同じ型でなければなりません。
よって、 `toml::get<T>` とは違って、 `get_or` では `T` を指定せずとも推論されます。
## `T`が`basic_value<TC>`である場合
```cpp
template<typename TC>
basic_value<TC> const& get_or(const basic_value<TC>& v, const basic_value<TC>& opt)
template<typename TC>
basic_value<TC> & get_or(basic_value<TC>& v, basic_value<TC>& opt)
template<typename TC>
basic_value<TC> get_or(basic_value<TC>&& v, basic_value<TC>&& opt)
```
変換先は同一の`toml::value`なので、失敗しません。
他の関数の実装を一般化するためだけに存在しています。
## `T`が`basic_value<TC>::{some_type}`である場合
```cpp
template<typename T, typename TC>
T const& get_or(const basic_value<TC>& v, const T& opt) noexcept
template<typename T, typename TC>
T & get_or(basic_value<TC>& v, T& opt) noexcept
template<typename T, typename TC>
T get_or(basic_value<TC>&& v, T&& opt) noexcept
```
`toml::get<T>`と同様の変換を行います。失敗した場合は第二引数が返されます。
## `T`が`const char*`である場合
```cpp
template<typename TC>
typename basic_value<TC>::string_type
get_or(const basic_value<TC>& v,
const typename basic_value<TC>::string_type::value_type* opt);
```
`const char*` が渡された場合、変換先は `std::string` として解釈されます。
## `T`がその他の場合
```cpp
template<typename TC>
typename std::remove_cv<typename std::remove_reference<T>::type>::type
get_or(const basic_value<TC>& v, T&& opt);
```
`toml::get<T>`と同様の変換を行います。失敗した場合は第二引数が返されます。
# 関連項目
- [find.hpp]({{<ref "find.md">}})
- [from.hpp]({{<ref "from.md">}})
- [value.hpp]({{<ref "value.md">}})

View File

@@ -0,0 +1,57 @@
+++
title = "into.hpp"
type = "docs"
+++
# into.hpp
`toml::value`のコンストラクタで使用する、ユーザー定義型からの変換を定義する構造体です。
メンバ関数に`into_toml`を追加することによっても同じ機能を追加できますが、メンバ関数を追加できないクラスに対しては`into<T>`を使用してください。
このファイルでは特定の実装は提供しません。使用する際に、この構造体を特殊化してください。
```cpp
namespace toml
{
template<typename T>
struct into;
} // toml
```
## 例
```cpp
namespace extlib
{
struct foo
{
int a;
std::string b;
};
} // extlib
#include <toml11/into.hpp>
namespace toml
{
template<>
struct into<extlib::foo>
{
template<typename TC>
static toml::basic_value<TC> into_toml(const extlib::foo& f)
{
using value_type = toml::basic_value<TC>;
using table_type = typename value_type::table_type;
return value_type(table_type{{"a", f.a}, {"b", f.b}});
}
};
} // toml
```
# 関連項目
- [conversion.hpp]({{<ref "conversion.md">}})
- [from.hpp]({{<ref "from.md">}})

View File

@@ -0,0 +1,83 @@
+++
title = "literal.hpp"
type = "docs"
+++
# literal.hpp
`literal.hpp`では、`_toml`リテラルが定義されます。
`_toml`リテラルは、文字列リテラルをパースして`toml::value`に変換します。
```cpp
namespace toml
{
inline namespace literals
{
inline namespace toml_literals
{
toml::value operator"" _toml(const char* str, std::size_t len);
toml::value operator"" _toml(const char8_t* str, std::size_t len); // C++20以降
} // toml_literals
} // literals
} // toml
```
## 自由関数
### `operator"" _toml(char)`
```cpp
toml::value operator"" _toml(const char* str, std::size_t len);
```
文字列リテラルをパースして`toml::value`に変換します。
通常のTOMLファイルの場合、`toml::parse`と同等の処理が行われます。
```cpp
const auto v1 = "a = 'foo'"_toml; // v1: {a = 'foo'}
```
改行を含む場合、生文字列リテラルが便利です。
```cpp
const auto v1 = R"(
a = 42
b = "foo"
)"_toml;
```
値が単体で書かれていた場合、その値になります。
```cpp
const auto v2 = "'foo'"_toml; // v2: 'foo'
```
TOMLは数値のみからなるキーを許可しています。
`[1]`のように、テーブル定義と配列の区別がつかない場合、テーブル定義が優先されます。
配列として解釈させるには、trailing commaを使用してください。
```cpp
const auto v3 = "[1]"_toml; // v3: {1 = {}}
const auto v4 = "[1,]"_toml; // v4: [1,]
```
### `operator"" _toml(char8_t)`
`char8_t`が利用可能な場合に定義されます。引数の型のほかに違いはありません。
# 例
```cpp
#include <toml.hpp>
int main()
{
using namespace toml::literals::toml_literals;
const auto v = "a = \"foo\""_toml;
assert(v.at("a").as_string() == "foo");
return 0;
}
```

View File

@@ -0,0 +1,359 @@
+++
title = "ordered_map.hpp"
type = "docs"
+++
# ordered_map.hpp
ファイル中の値の順番を維持するために使用する`toml::ordered_map`を定義します。
# `class ordered_map`
```cpp
namespace toml
{
template<typename Key, typename Val, typename Cmp = std::equal_to<Key>,
typename Allocator = std::allocator<std::pair<Key, Val>>>
class ordered_map;
}
```
`ordered_map`は、値を追加した順序を保ったまま値を保持し、その順でイテレートできる `map` 型です。
線形コンテナなので、検索には要素数に対して `O(n)` の時間がかかります。
検索を行う機会が少なく、値の順序を守る必要がある場合に使用してください。
## 非メンバ型
```cpp
namespace toml
{
struct ordered_type_config;
using ordered_value = basic_value<ordered_type_config>;
using ordered_table = typename ordered_value::table_type;
using ordered_array = typename ordered_value::array_type;
}
```
`toml::type_config``toml::value` の代わりに使用します。
{{< hint info >}}
`toml::parse` はデフォルトで `type_config` を使用するので、パースする際に
```cpp
const auto input = toml::parse<toml::ordered_type_config>("input.toml");
```
としてください。
{{< /hint >}}
## メンバ型
```cpp
using key_type = Key;
using mapped_type = Val;
using value_type = std::pair<Key, Val>;
using key_compare = Cmp;
using allocator_type = Allocator;
using container_type = std::vector<value_type, Allocator>;
using reference = typename container_type::reference;
using pointer = typename container_type::pointer;
using const_reference = typename container_type::const_reference;
using const_pointer = typename container_type::const_pointer;
using iterator = typename container_type::iterator;
using const_iterator = typename container_type::const_iterator;
using size_type = typename container_type::size_type;
using difference_type = typename container_type::difference_type;
```
## メンバ関数
### コンストラクタ
```cpp
ordered_map() = default;
```
空の `ordered_map` を構築します。
### コンストラクタ(コンパレータ、アロケータ)
```cpp
explicit ordered_map(const Cmp& cmp, const Allocator& alloc = Allocator());
explicit ordered_map(const Allocator& alloc);
```
キーの比較に使用するコンパレータや、コンテナのメモリ確保に使用するアロケータを指定して構築します。
### コピー・ムーブコンストラクタ
```cpp
ordered_map(const ordered_map&) = default;
ordered_map(ordered_map&&) = default;
ordered_map(const ordered_map& other, const Allocator& alloc);
ordered_map(ordered_map&& other, const Allocator& alloc);
```
別の `ordered_map` の内容をコピー・ムーブして構築します。
コンテナのメモリ確保に使用するアロケータを指定することも可能です。
### コンストラクタ(`Iterator`
```cpp
template<typename InputIterator>
ordered_map(InputIterator first, InputIterator last, const Cmp& cmp = Cmp(), const Allocator& alloc = Allocator());
template<typename InputIterator>
ordered_map(InputIterator first, InputIterator last, const Allocator& alloc = Allocator());
```
イテレータ範囲を受け取って構築します。
順序は、イテレータの順序に従います。
### コンストラクタ(`std::initializer_list`
```cpp
ordered_map(std::initializer_list<value_type> v, const Cmp& cmp = Cmp(), const Allocator& alloc = Allocator());
ordered_map(std::initializer_list<value_type> v, const Allocator& alloc);
```
`ordered_map{...}`の形式で初期化します。
### コピー・ムーブ代入演算子
```cpp
ordered_map& operator=(const ordered_map&) = default;
ordered_map& operator=(ordered_map&&) = default;
```
別の `ordered_map` の内容をコピー・ムーブ代入します。
### 代入演算子(`std::initializer_list`
```cpp
ordered_map& operator=(std::initializer_list<value_type> v);
```
`std::initializer_list` の内容を代入します。
### デストラクタ
```cpp
~ordered_map() = default;
```
`ordered_map` を破棄します。
### `begin()`, `end()`
```cpp
iterator begin() noexcept;
iterator end() noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
```
コンテナの内容を順序通りにイテレートします。
### `empty()`
```cpp
bool empty() const noexcept;
```
`ordered_map` が空の場合 `true` を、そうでない場合 `false` を返します。
### `size()`
```cpp
std::size_t size() const noexcept;
```
`ordered_map` の要素数を返します。
### `max_size()`
```cpp
std::size_t max_size() const noexcept;
```
`ordered_map` が持つことのできる最大の要素数を返します。
### `clear()`
```cpp
void clear();
```
内容を消去します。
### `push_back(kv)`
```cpp
void push_back(const value_type&);
void push_back(value_type&&);
```
キーと値のペアを末尾に追加します。
### `emplace_back(k, v)`
```cpp
void emplace_back(key_type, mapped_type);
```
キーと値のペアを末尾に追加します。
### `pop_back()`
```cpp
void pop_back();
```
末尾の値を削除します。
### `insert(kv)`
```cpp
void insert(value_type);
```
キーと値のペアを末尾に追加します。
### `emplace(k, v)`
```cpp
void emplace(key_type, mapped_type);
```
キーと値のペアを末尾に追加します。
### `count(k)`
```cpp
std::size_t count(const key_type&) const noexcept;
```
キーに対応する値の数を返します。
同じキーに複数の値を代入することはできないので、値が存在する場合は `1`, そうでない場合は `0` を返します。
### `contains(k)`
```cpp
bool contains(const key_type&) const noexcept;
```
キーに対応する値が存在するなら `true` を、そうでないなら `false` を返します。
### `find(k)`
```cpp
iterator find(const key_type& key) noexcept;
const_iterator find(const key_type& key) const noexcept;
```
キーに対応する値を検索し、それを指すイテレータを返します。
存在しなかった場合、`end()`を返します。
### `at(k)`
```cpp
mapped_type& at(const key_type& k);
mapped_type const& at(const key_type& k) const;
```
キーに対応する値を検索して返します。
存在しなかった場合、`std::out_of_range`を送出します。
### `operator[](k)`
```cpp
mapped_type& operator[](const key_type& k);
mapped_type const& operator[](const key_type& k) const;
```
キーに対応する値を検索して返します。
存在しなかった場合、新規な値を構築して返します。
`ordered_map``const` の場合は新規な値を構築できないので、 `std::out_of_range` を送出します。
### `key_comp()`
```cpp
key_compare key_comp() const;
```
比較に使用するコンパレータを返します。
## 使用上の注意
### キーの書き換え
{{< hint warning >}}
`ordered_map``value_type``std::pair<Key, Val>` を使用しているので、イテレータを介してキーを書き換えることが可能になってしまっています。
この方法でキーを書き換えることは推奨されません。
キーを書き換えて既存のキーと衝突した場合、衝突したうちの片方が検索できなくなります。
`operator[]``push_back`, `insert` による書き込みの場合は、既存のキーとの衝突が検出されます。
{{< /hint >}}
### 保たれる順序の詳細
{{< hint warning >}}
`ordered_map` はキーの順序を保ちますが、ここで保たれる順序は同じテーブルで定義されたキーの順序のみです。
よって、テーブルをまたいだ順序は保たれないことに注意してください。
例えば、以下のファイルの順序は保たれます。
```cpp
apple.type = "fruit"
apple.skin = "thin"
apple.color = "red"
orange.type = "fruit"
orange.skin = "thick"
orange.color = "orange"
```
対して以下のファイルの順序は保たれません。
```cpp
apple.type = "fruit"
orange.type = "fruit"
apple.skin = "thin"
orange.skin = "thick"
apple.color = "red"
orange.color = "orange"
```
`ordered_map` が保つ順序は、rootテーブルに定義された `apple``orange` の順序と、
`apple` 内で定義された `type`, `skin`, `color` の順序、
また `orange` 内で定義された `type`, `skin`, `color` の順序のみです。
{{< /hint >}}
## 関連項目
- [parser.hpp]({{<ref "parser.md">}})
- [types.hpp]({{<ref "types.md">}})
- [value.hpp]({{<ref "value.md">}})

View File

@@ -0,0 +1,381 @@
+++
title = "parser.hpp"
type = "docs"
+++
# parser.hpp
ファイルまたは文字列をパースする関数と、それが用いる例外を定義します。
`parse`は失敗した場合に例外を送出しますが、`try_parse`はエラー情報を返します。
# `parse`
与えられたファイルの内容をパースし、`toml::basic_value`を返します。
失敗した場合は`toml::syntax_error`が送出されます。
`basic_value`の持つ型情報は`template`で、TOML言語のバージョンは`toml::spec`で指定します。
### `parse(std::istream&, std::string filename, toml::spec)`
```cpp
namespace toml
{
template<typename TC = type_config>
basic_value<TC>
parse(std::istream& is,
std::string fname = "unknown file",
spec s = spec::default_version());
}
```
`std::istream&`を受け取ってその内容をパースします。
ファイル名の情報は第三引数で受け取ります。ファイル名が渡されなかった場合、`"unknown file"`になります。
### `parse(std::string filename, toml::spec)`
```cpp
namespace toml
{
template<typename TC = type_config>
basic_value<TC>
parse(std::string fname,
spec s = spec::default_version());
}
```
ファイル名を受け取って、その内容をパースします。
ファイルの読み込みに失敗した場合、`file_io_error`が送出されます。
パースに失敗した場合、`syntax_error`が送出されます。
### `parse(const char (&)[N] filename, toml::spec)`
```cpp
namespace toml
{
template<typename TC = type_config, std::size_t N>
basic_value<TC>
parse(const char (&fname)[N],
spec s = spec::default_version());
}
```
文字列リテラルを受け取って、そのファイルの内容をパースします。
ファイルの読み込みに失敗した場合、`file_io_error`が送出されます。
パースに失敗した場合、`syntax_error`が送出されます。
### `parse(std::filesystem::path, toml::spec)`
```cpp
namespace toml
{
template<typename TC = type_config>
basic_value<TC>
parse(const std::filesystem::path& fpath,
spec s = spec::default_version());
}
```
`<filesystem>`が利用可能な場合のみ定義されます。
ファイルパスを受け取って、そのファイルの内容をパースします。
ファイルの読み込みに失敗した場合、`file_io_error`が送出されます。
パースに失敗した場合、`syntax_error`が送出されます。
### `parse(FILE*, std::string filename, toml::spec)`
```cpp
namespace toml
{
template<typename TC = type_config>
result<basic_value<TC>, std::vector<error_info>>
parse(FILE* fp,
std::string filename,
spec s = spec::default_version());
}
```
`FILE*`が指すファイルを読み込んでパースします。
ファイルの読み込みに失敗した場合、`errno`が含まれた`file_io_error`が送出されます。
パースに失敗した場合、`syntax_error`が送出されます。
### `parse(std::vector<unsigned char>, std::string filename, toml::spec)`
```cpp
namespace toml
{
template<typename TC = type_config>
basic_value<TC>
parse(std::vector<unsigned char> content,
std::string filename,
spec s = spec::default_version());
}
```
バイト列をTOMLファイルとしてパースします。
パースに失敗した場合、`syntax_error`が送出されます。
# `parse_str`
### `parse_str(std::string, toml::spec)`
```cpp
namespace toml
{
template<typename TC = type_config>
basic_value<TC>
parse_str(std::string content,
spec s = spec::default_version(),
cxx::source_location loc = cxx::source_location::current());
}
```
文字列をTOMLファイルとしてパースします。
失敗した場合は`toml::syntax_error`が送出されます。
`basic_value`の持つ型情報は`template`で、TOML言語のバージョンは`toml::spec`で指定します。
第三引数の`cxx::source_location`を手動で設定する必要は通常ありません。
`std::source_location`, `std::experimental::source_location`, `__builtin_FILE`のいずれかが利用可能な場合、
`parse_str`が呼ばれた地点の情報が位置情報として保存されます。
# `try_parse`
与えられたファイルの内容をパースし、成功した場合は`toml::basic_value`を、失敗した場合は`std::vector<toml::error_info>`を返します。
`basic_value`の持つ型情報は`template`で、TOML言語のバージョンは`toml::spec`で指定します。
{{< hint warning >}}
`try_parse``parse`と異なり`syntax_error`などのtoml11で定義された例外は投げませんが、
標準ライブラリから送出される例外はそのまま送出されることに注意してください。
例えば、`std::ifstream`の内部で起きたエラーや、`std::vector`でのメモリ枯渇などは例外を送出します。
{{< /hint >}}
### `try_parse(std::istream&, std::string filename, toml::spec)`
```cpp
namespace toml
{
template<typename TC = type_config>
result<basic_value<TC>, std::vector<error_info>>
try_parse(std::istream& is,
std::string fname = "unknown file",
spec s = spec::default_version());
}
```
`std::istream&`を受け取ってその内容をパースします。
ファイル名の情報は第二引数で受け取ります。ファイル名が渡されなかった場合、`"unknown file"`になります。
パースに失敗した場合、エラー型である`std::vector<error_info>`を持つ`result`が返されます。
成功した場合、`basic_value`を持つ`result`が返されます。
### `try_parse(std::string filename, toml::spec)`
```cpp
namespace toml
{
template<typename TC = type_config>
result<basic_value<TC>, std::vector<error_info>>
try_parse(std::string fname,
spec s = spec::default_version());
}
```
ファイル名を受け取って、その内容をパースします。
パースに失敗した場合、エラー型である`std::vector<error_info>`を持つ`result`が返されます。
成功した場合、`basic_value`を持つ`result`が返されます。
### `try_parse(const char (&)[N] filename, toml::spec)`
```cpp
namespace toml
{
template<typename TC = type_config, std::size_t N>
result<basic_value<TC>, std::vector<error_info>>
try_parse(const char (&fname)[N],
spec s = spec::default_version());
}
```
文字列リテラルをファイル名として受け取って、その内容をパースします。
パースに失敗した場合、エラー型である`std::vector<error_info>`を持つ`result`が返されます。
成功した場合、`basic_value`を持つ`result`が返されます。
### `try_parse(std::filesystem::path, toml::spec)`
```cpp
namespace toml
{
template<typename TC = type_config>
result<basic_value<TC>, std::vector<error_info>>
try_parse(const std::filesystem::path& fpath,
spec s = spec::default_version());
}
```
ファイルパスを受け取って、その内容をパースします。
パースに失敗した場合、エラー型である`std::vector<error_info>`を持つ`result`が返されます。
成功した場合、`basic_value`を持つ`result`が返されます。
### `try_parse(FILE*, std::string filename, toml::spec)`
```cpp
namespace toml
{
template<typename TC = type_config>
result<basic_value<TC>, std::vector<error_info>>
try_parse(FILE* fp,
std::string filename,
spec s = spec::default_version());
}
```
`FILE*`を受け取って、そのファイルの内容をパースします。
パースに失敗した場合、エラー型である`std::vector<error_info>`を持つ`result`が返されます。
成功した場合、`basic_value`を持つ`result`が返されます。
### `try_parse(std::vector<unsigned char>, std::string filename, toml::spec)`
```cpp
namespace toml
{
template<typename TC = type_config>
result<basic_value<TC>, std::vector<error_info>>
try_parse(std::vector<unsigned char> content,
std::string filename,
spec s = spec::default_version());
}
```
バイト列を受け取って、その内容をTOMLファイルとしてパースします。
パースに失敗した場合、エラー型である`std::vector<error_info>`を持つ`result`が返されます。
成功した場合、`basic_value`を持つ`result`が返されます。
# `try_parse_str`
### `try_parse_str(std::string, toml::spec)`
```cpp
namespace toml
{
template<typename TC = type_config>
result<basic_value<TC>, std::vector<error_info>>
try_parse_str(std::string content,
spec s = spec::default_version(),
cxx::source_location loc = cxx::source_location::current());
}
```
文字列をTOMLファイルとしてパースし、成功した場合は`toml::basic_value`を、失敗した場合は`std::vector<toml::error_info>`を返します。
`parse_str`と異なり、`syntax_error`を送出せず、エラー情報を`result`の失敗型として返します。
`std::source_location`, `std::experimental::source_location`, `__builtin_FILE`のどれかが利用可能な場合、それを位置情報に記録します。
第三引数の`cxx::source_location`を手動で設定する必要は通常ありません。
`std::source_location`, `std::experimental::source_location`, `__builtin_FILE`のいずれかが利用可能な場合、
`parse_str`が呼ばれた地点の情報が位置情報として保存されます。
{{< hint warning >}}
`try_parse``parse`と異なり`syntax_error`などのtoml11で定義された例外は投げませんが、
標準ライブラリから送出される例外はそのまま送出されることに注意してください。
例えば、`std::ifstream`の内部で起きたエラーや、`std::vector`でのメモリ枯渇などは例外を送出します。
{{< /hint >}}
# `syntax_error`
```cpp
namespace toml
{
struct syntax_error final : public ::toml::exception
{
public:
syntax_error(std::string what_arg, std::vector<error_info> err);
~syntax_error() noexcept override = default;
const char* what() const noexcept override;
std::vector<error_info> const& errors() const noexcept
};
}
```
TOML言語の文法エラーが発見された場合に送出される例外です。
`parse`からは送出されますが、`try_parse`からは送出されません。
# `file_io_error`
```cpp
namespace toml
{
struct file_io_error final : public ::toml::exception
{
public:
file_io_error(const std::string& msg, const std::string& fname);
file_io_error(int errnum, const std::string& msg, const std::string& fname);
~file_io_error() noexcept override = default;
const char* what() const noexcept override;
bool has_errno() const noexcept;
int get_errno() const noexcept;
};
}
```
ファイルの内容を読むのに失敗した場合に送出される例外です。
`FILE*`を使ってファイルを読み込んだ場合は`errno`が設定されます。
### `has_errno`
`std::ifstream`が失敗した場合は`errno`は設定されません。
このとき、`has_errno``false`になります。
### `get_errno`
特に`FILE*`を渡していた場合に、`errno`の値を取得します。
`has_errno``false`の場合は`0`となります。
# 関連項目
- [error_info.hpp]({{<ref "error_info.md">}})
- [result.hpp]({{<ref "result.md">}})
- [spec.hpp]({{<ref "spec.md">}})
- [value.hpp]({{<ref "value.md">}})

View File

@@ -0,0 +1,529 @@
+++
title = "result.hpp"
type = "docs"
+++
# result.hpp
`result.hpp`は、成功値か失敗値かのどちらかを持つ`result`型を定義します。
これは、例外を投げない`toml::try_parse`の返り値として使用されます。
# success
成功値を持つ型です。
```cpp
namespace toml
{
template<typename T>
struct success
{
using value_type = T;
explicit success(value_type v);
~success() = default;
success(const success&) = default;
success(success&&) = default;
success& operator=(const success&) = default;
success& operator=(success&&) = default;
template<typename U>
explicit success(U&& v);
template<typename U>
explicit success(success<U> v);
value_type& get() noexcept;
value_type const& get() const noexcept;
};
template<typename T>
success<typename std::decay<T>::type> ok(T&& v);
template<std::size_t N>
success<std::string> ok(const char (&literal)[N])
}
```
## メンバ型
```cpp
using value_type = T;
```
成功値の型です。
## メンバ関数
### コンストラクタ
```cpp
explicit success(value_type v);
```
`value_type`を受け取って構築します。
```cpp
template<typename U>
explicit success(U&& v);
```
`value_type`に変換可能な他の型を受け取って構築します。
```cpp
template<typename U>
explicit success(success<U> v);
```
`value_type`に変換可能な他の型を持つ`success`型を受け取って構築します。
### `get()`
```cpp
value_type& get() noexcept;
value_type const& get() const noexcept;
```
値にアクセスします。
## 非メンバ関数
### `ok(T)`
```cpp
template<typename T>
success<typename std::decay<T>::type> ok(T&& v);
template<std::size_t N>
success<std::string> ok(const char (&literal)[N])
```
成功値から`success`型を構築して返します。
文字列リテラルを与えた場合は、`std::string`にして返します。
# `success<reference_wrapper<T>>`
`success`の特殊化。成功値が参照であるときに使用されます。
```cpp
namespace toml
{
template<typename T>
struct success<std::reference_wrapper<T>>
{
using value_type = T;
explicit success(std::reference_wrapper<value_type> v) noexcept;
value_type& get() noexcept;
value_type const& get() const noexcept;
};
}
```
## メンバ型
```cpp
using value_type = T;
```
成功値の型です。参照ではなく、`std::reference_wrapper<T>``T`です。
### `get()`
```cpp
value_type& get() noexcept;
value_type const& get() const noexcept;
```
値にアクセスします。
# failure
失敗値を持つ型です。
```cpp
namespace toml
{
template<typename T>
struct failure
{
using value_type = T;
explicit failure(value_type v);
~failure() = default;
failure(const failure&) = default;
failure(failure&&) = default;
failure& operator=(const failure&) = default;
failure& operator=(failure&&) = default;
template<typename U>
explicit failure(U&& v);
template<typename U>
explicit failure(failure<U> v);
value_type& get() noexcept;
value_type const& get() const noexcept;
};
template<typename T>
failure<typename std::decay<T>::type> err(T&& v);
template<std::size_t N>
failure<std::string> err(const char (&literal)[N]);
}
```
## メンバ型
```cpp
using value_type = T;
```
失敗値の型です。
## メンバ関数
### コンストラクタ
```cpp
explicit failure(value_type v);
```
`value_type`を受け取って構築します。
```cpp
template<typename U>
explicit failure(U&& v);
```
`value_type`に変換可能な他の型を受け取って構築します。
```cpp
template<typename U>
explicit failure(failure<U> v);
```
`value_type`に変換可能な他の型を持つ`failure`型を受け取って構築します。
### `get()`
```cpp
value_type& get() noexcept;
value_type const& get() const noexcept;
```
値にアクセスします。
## 非メンバ関数
### `err(T)`
```cpp
template<typename T>
failure<typename std::decay<T>::type> err(T&& v);
template<std::size_t N>
failure<std::string> err(const char (&literal)[N]);
```
失敗値から`failure`型を構築して返します。
文字列リテラルを与えた場合は、`std::string`にして返します。
# `failure<reference_wrapper<T>>`
`failure`の特殊化。失敗値が参照であるときに使用されます。
```cpp
namespace toml
{
template<typename T>
struct failure<std::reference_wrapper<T>>
{
using value_type = T;
explicit failure(std::reference_wrapper<value_type> v) noexcept;
value_type& get() noexcept {return value.get();}
value_type const& get() const noexcept {return value.get();}
};
}
```
## メンバ型
```cpp
using value_type = T;
```
失敗値の型です。参照ではなく、`std::reference_wrapper<T>``T`です。
### `get()`
```cpp
value_type& get() noexcept
value_type const& get() const noexcept
```
値にアクセスします。
# result
成功値か失敗値かのどちらかを持つ型です。
```cpp
namespace toml
{
template<typename T, typename E>
struct result
{
using success_type = success<T>;
using failure_type = failure<E>;
using value_type = typename success_type::value_type;
using error_type = typename failure_type::value_type;
result(success_type s);
result(failure_type f);
template<typename U>
result(success<U> s);
template<typename U>
result(failure<U> f);
result& operator=(success_type s);
result& operator=(failure_type f);
template<typename U>
result& operator=(success<U> s);
template<typename U>
result& operator=(failure<U> f);
~result() noexcept;
result(const result& other);
result(result&& other);
result& operator=(const result& other);
result& operator=(result&& other);
template<typename U, typename F>
result(result<U, F> other);
template<typename U, typename F>
result& operator=(result<U, F> other);
bool is_ok() const noexcept;
bool is_err() const noexcept;
explicit operator bool() const noexcept;
value_type& unwrap(cxx::source_location loc = cxx::source_location::current());
value_type const& unwrap(cxx::source_location loc = cxx::source_location::current()) const;
value_type& unwrap_or(value_type& opt) noexcept;
value_type const& unwrap_or(value_type const& opt) const noexcept;
error_type& unwrap_err(cxx::source_location loc = cxx::source_location::current());
error_type const& unwrap_err(cxx::source_location loc = cxx::source_location::current()) const;
value_type& as_ok() noexcept;
value_type const& as_ok() const noexcept;
error_type& as_err() noexcept;
error_type const& as_err() const noexcept;
};
}
```
## メンバ型
### `success_type`
`success<T>`です。
### `failure_type`
`failure<E>`です。
### `value_type`
成功型`T`です。`success_type::value_type`のエイリアスです。
成功型`T`として`std::reference_wrapper<U>`が渡された場合、その引数型の`U`になります。
### `error_type`
失敗型`E`です。`failure_type::value_type`のエイリアスです。
失敗型`E`として`std::reference_wrapper<F>`が渡された場合、その引数型の`F`になります。
## メンバ関数
### コンストラクタ
```cpp
result() = delete;
```
`result`型はデフォルトでは構築できません。
成功型か失敗型を与える必要があります。
```cpp
result(success_type s);
result(failure_type f);
```
成功型、失敗型を受け取って構築します。
```cpp
template<typename U>
result(success<U> s);
template<typename U>
result(failure<U> f);
```
`value_type``error_type`に変換可能な成功型、失敗型を受け取って構築します。
```cpp
template<typename U, typename F>
result(result<U, F> other);
template<typename U, typename F>
result& operator=(result<U, F> other);
```
変換可能な成功型、失敗型を持つ`result`から構築します。
### コピー・ムーブコンストラクタ
```cpp
result(const result& other);
result(result&& other);
```
コピー・ムーブ構築可能です。
### `operator=`
```cpp
result& operator=(const result& other);
result& operator=(result&& other);
```
コピー・ムーブ代入可能です。
```cpp
template<typename U>
result& operator=(success<U> s);
template<typename U>
result& operator=(failure<U> f);
```
変換可能な型を持つ成功型、失敗型は代入可能です。
### `is_ok()`
```cpp
bool is_ok() const noexcept;
```
成功値を持っている場合`true`を、そうでない場合`false`を返します。
### `is_err()`
```cpp
bool is_err() const noexcept;
```
失敗値を持っている場合`true`を、そうでない場合`false`を返します。
### `operator bool()`
```cpp
explicit operator bool() const noexcept;
```
成功値を持っている場合`true`を、そうでない場合`false`を返します。
### `unwrap()`
```cpp
value_type& unwrap(cxx::source_location loc = cxx::source_location::current());
value_type const& unwrap(cxx::source_location loc = cxx::source_location::current()) const;
```
成功値を取り出します。
成功値を持っていない場合、`toml::bad_result_access`が送出されます。
`std::source_location`または`std::experimental::source_location`が利用可能か、
あるいはコンパイラ拡張によって同等の情報が利用可能な場合、`what()`文字列に
`unwrap()`が発生したソースコードのファイル名と行数が表示されます。
利用可能でない場合、位置情報は表示されません。
### `unwrap_or()`
```cpp
value_type& unwrap_or(value_type& opt) noexcept;
value_type const& unwrap_or(value_type const& opt) const noexcept;
```
成功値を持っていた場合それを、持っていなかった場合は引数で与えられた値を返します。
### `unwrap_err()`
```cpp
error_type& unwrap_err(cxx::source_location loc = cxx::source_location::current());
error_type const& unwrap_err(cxx::source_location loc = cxx::source_location::current()) const;
```
失敗値を取り出します。
失敗値を持っていない場合、`toml::bad_result_access`が送出されます。
`std::source_location`または`std::experimental::source_location`が利用可能か、
あるいはコンパイラ拡張によって同等の情報が利用可能な場合、`what()`文字列に
`unwrap()`が発生したソースコードのファイル名と行数が表示されます。
利用可能でない場合、位置情報は表示されません。
### `as_ok()`
```cpp
value_type& as_ok() noexcept;
value_type const& as_ok() const noexcept;
```
チェックなしで成功値を返します。
成功値を持っていなかった場合、その動作は未定義となります。
### `as_err()`
```cpp
error_type& as_err() noexcept;
error_type const& as_err() const noexcept;
```
チェックなしで失敗値を返します。
失敗値を持っていなかった場合、その動作は未定義となります。
# bad_result_access
`result``unwrap`または`unwrap_err`で失敗した際に送出される例外です。
```cpp
namespace toml
{
struct bad_result_access : public ::toml::exception
{
public:
explicit bad_result_access(const std::string& what_arg);
virtual ~bad_result_access() noexcept override = default;
virtual const char* what() const noexcept override;
protected:
std::string what_;
};
}
```

View File

@@ -0,0 +1,66 @@
+++
title = "serializer.hpp"
type = "docs"
+++
# serializer.hpp
# `format`
シリアライズを行います。
```cpp
namespace toml
{
template<typename TC>
std::string format(const basic_value<TC>& v,
const spec s = spec::default_version());
template<typename TC>
std::string format(const typename basic_value<TC>::key_type& k,
const basic_value<TC>& v,
const spec s = spec::default_version());
template<typename TC>
std::string format(const std::vector<typename basic_value<TC>::key_type>& ks,
const basic_value<TC>& v,
const spec s = spec::default_version());
}
```
フォーマット情報と`spec`が矛盾する場合、例えば`v1.0.0``table_format::multiline_oneline`が指定されているときなどは、`spec`が優先されます。
### `format(v, spec)`
`toml::value`を、それが持つフォーマット情報と`spec`に従ってフォーマットします。
`table_type`だった場合、それがルートであるとしてフォーマットします。
それ以外の値だった場合、値のみをフォーマットします。
### `format(k, v, spec)`
`toml::value`を、与えられたキーと同時にフォーマットします。
`v`はそのキー以下に定義されていると解釈されます。
### `format([k,...], v, spec)`
`v`はそのキー以下に定義されていると解釈されます。
キーが複数与えられた場合、再帰的に定義されたテーブルとして解釈されます。
# `serialization_error`
シリアライズ中に発生したエラーを報告します。
```cpp
namespace toml
{
struct serialization_error final : public ::toml::exception
{
public:
explicit serialization_error(std::string what_arg, source_location loc);
~serialization_error() noexcept override = default;
const char* what() const noexcept override;
source_location const& location() const noexcept;
};
}
```

View File

@@ -0,0 +1,233 @@
+++
title = "source_location.hpp"
type = "docs"
+++
# source_location.hpp
`source_location.hpp`では、TOMLファイル内のある領域を指すクラスが定義されます。
このクラスは、エラーメッセージで問題の箇所を指摘するために使われます。
# `toml::source_location`
`source_location`は、TOMLファイル内のある領域を指すクラスです。
```cpp
namespace toml
{
struct source_location
{
public:
explicit source_location(/* implementation-defined */);
~source_location() = default;
source_location(source_location const&) = default;
source_location(source_location &&) = default;
source_location& operator=(source_location const&) = default;
source_location& operator=(source_location &&) = default;
bool is_ok() const noexcept;
std::size_t length() const noexcept;
std::size_t first_line_number() const noexcept;
std::size_t first_column_number() const noexcept;
std::size_t last_line_number() const noexcept;
std::size_t last_column_number() const noexcept;
std::string const& file_name() const noexcept;
std::size_t num_lines() const noexcept;
std::string const& first_line() const;
std::string const& last_line() const;
std::vector<std::string> const& lines() const noexcept;
};
template<typename ... Ts>
std::string format_location(const source_location& loc, const std::string& msg, const Ts& ... locs_and_msgs);
} //toml
```
## メンバ関数
### コンストラクタ
```cpp
explicit source_location(/* implementation-defined */);
```
`toml::source_location``toml::parse`または`_toml`リテラル以外で構築することはできません。
### `is_ok()`
```cpp
bool is_ok() const noexcept;
```
`source_location`が有効な値を保持している場合、`true`を、そうでない場合`false`を返します。
`toml::parse``_toml`リテラル以外から構築した`toml::value``location()`の結果は、指す対象がないため、`is_ok``false`を返します。
### `length()`
```cpp
std::size_t length() const noexcept;
```
`source_location`が指す領域の長さを返します。
有効な値を保持していない場合、`0`を返します。
### `first_line_number()`
```cpp
std::size_t first_line_number() const noexcept;
```
`source_location`が指す領域の最初の行の行番号を返します。
有効な値を保持していない場合、`1`を返します。
### `first_column_number()`
```cpp
std::size_t first_column_number() const noexcept;
```
`source_location`が指す領域の最初の列の列番号を返します。
有効な値を保持していない場合、`1`を返します。
### `last_line_number()`
```cpp
std::size_t last_line_number() const noexcept;
```
`source_location`が指す領域の最後の行の行番号を返します。
有効な値を保持していない場合、`1`を返します。
### `last_column_number()`
```cpp
std::size_t last_column_number() const noexcept;
```
`source_location`が指す領域の最後の列の列番号を返します。
有効な値を保持していない場合、`1`を返します。
### `file_name()`
```cpp
std::string const& file_name() const noexcept;
```
`source_location`が指す領域を含むファイルのファイル名を返します。
有効な値を保持していない場合、`"unknown file"`を返します。
### `num_lines()`
```cpp
std::size_t num_lines() const noexcept;
```
`source_location`が指す領域の行数を返します。
有効な値を保持していない場合、`0`を返します。
### `first_line()`
```cpp
std::string const& first_line() const;
```
`source_location`が指す領域の最初の行を返します。
有効な値を保持していない場合、`std::out_of_range`例外が送出されます。
### `last_line()`
```cpp
std::string const& last_line() const;
```
`source_location`が指す領域の最後の行を返します。
有効な値を保持していない場合、`std::out_of_range`例外が送出されます。
### `lines()`
```cpp
std::vector<std::string> const& lines() const noexcept;
```
`source_location`が指す領域の全ての行を返します。
有効な値を保持していない場合、空の`std::vector`への参照を返します。
## 非メンバ関数
### `format_location`
```cpp
template<typename ... Ts>
std::string format_location(const source_location& loc, const std::string& msg, const Ts& ... locs_and_msgs);
```
`source_location`が指す箇所と、それについてのメッセージを以下のようにフォーマットします。
```
-> {filename.toml}
|
1 | a = 42
| ^-- {message}
```
この時、色付けがONになっている場合、ANSIエスケープシーケンスによって色情報が追加されます。
locs_and_msgsが複数個ある場合、それらは`const source_location&``const std::string&`の順である必要があります。
#### 例:複数の`source_location`と`std::string`
複数の`source_location``std::string`を渡した場合、以下のようにフォーマットされます。
```cpp
source_location& loc0;
source_location& loc1;
source_location& loc2;
std::string msg0;
std::string msg1;
std::string msg2;
format_location(loc0, msg0,
loc1, msg1,
loc2, msg2);
```
```
-> {filename0.toml}
|
1 | a = 42
| ^-- {message0}
|
-> {filename1.toml}
|
2 | b = 3.14
| ^-- {message1}
|
-> {filename2.toml}
|
3 | c = "foo"
| ^-- {message2}
```
# 関連項目
- [error_info.hpp]({{<ref "error_info.md">}})
- [value.hpp]({{<ref "value.md">}})

View File

@@ -0,0 +1,314 @@
+++
title = "spec.hpp"
type = "docs"
+++
# spec.hpp
`spec.hpp`では、TOMLのバージョンを指定するためのクラスが定義されます。
# `toml::semantic_version`
`semantic_version`は、バージョン情報を格納するクラスです。
```cpp
namespace toml
{
struct semantic_version
{
constexpr semantic_version(std::uint32_t mjr, std::uint32_t mnr, std::uint32_t p) noexcept;
std::uint32_t major;
std::uint32_t minor;
std::uint32_t patch;
};
constexpr semantic_version
make_semver(std::uint32_t major, std::uint32_t minor, std::uint32_t patch) noexcept;
constexpr bool operator==(const semantic_version&, const semantic_version&) noexcept;
constexpr bool operator!=(const semantic_version&, const semantic_version&) noexcept;
constexpr bool operator< (const semantic_version&, const semantic_version&) noexcept;
constexpr bool operator<=(const semantic_version&, const semantic_version&) noexcept;
constexpr bool operator> (const semantic_version&, const semantic_version&) noexcept;
constexpr bool operator>=(const semantic_version&, const semantic_version&) noexcept;
std::ostream& operator<<(std::ostream& os, const semantic_version& ver);
} //toml
```
## メンバ関数
### コンストラクタ
```cpp
constexpr semantic_version(std::uint32_t mjr, std::uint32_t mnr, std::uint32_t p) noexcept;
```
`major`, `minor`, `patch`バージョンを指定して構築します。
## 非メンバ関数
### 比較演算子
```cpp
constexpr bool operator==(const semantic_version&, const semantic_version&) noexcept;
constexpr bool operator!=(const semantic_version&, const semantic_version&) noexcept;
constexpr bool operator< (const semantic_version&, const semantic_version&) noexcept;
constexpr bool operator<=(const semantic_version&, const semantic_version&) noexcept;
constexpr bool operator> (const semantic_version&, const semantic_version&) noexcept;
constexpr bool operator>=(const semantic_version&, const semantic_version&) noexcept;
```
semantic versioningに従って比較します。
### ストリーム演算子
```cpp
std::ostream& operator<<(std::ostream& os, const semantic_version& ver);
```
`{major}.{minor}.{patch}`の形式で出力します。
### `to_string`
```cpp
std::string to_string(const semantic_version& ver);
```
`{major}.{minor}.{patch}`の形式で文字列化します。
# `toml::spec`
`spec`は、TOMLのバージョン情報を格納するクラスです。
```cpp
struct spec
{
constexpr static spec default_version() noexcept;
constexpr static spec v(std::uint32_t mjr, std::uint32_t mnr, std::uint32_t p) noexcept;
constexpr explicit spec(const semantic_version& semver) noexcept;
semantic_version version; // toml version
// diff from v1.0.0 -> v1.1.0
bool v1_1_0_allow_control_characters_in_comments;
bool v1_1_0_allow_newlines_in_inline_tables;
bool v1_1_0_allow_trailing_comma_in_inline_tables;
bool v1_1_0_allow_non_english_in_bare_keys;
bool v1_1_0_add_escape_sequence_e;
bool v1_1_0_add_escape_sequence_x;
bool v1_1_0_make_seconds_optional;
// library extensions
bool ext_hex_float; // allow hex float
bool ext_num_suffix; // allow number suffix
bool ext_null_value; // allow null value
};
```
## メンバ関数
### コンストラクタ
```cpp
constexpr explicit spec(const semantic_version& semver) noexcept;
```
指定されたTOMLバージョンで`spec`を構築します。
TOML v1.0.0と、TOML v1.1.0に対応しています。
### `default_version()`
```cpp
constexpr static spec default_version() noexcept;
```
デフォルトのバージョンで`spec`を構築します。
`toml::parse``toml::format`でのデフォルト値として使われます。
toml11 v4.0.0での値は、v1.0.0です。
### `v(major, minor, patch)`
```cpp
constexpr static spec v(std::uint32_t mjr, std::uint32_t mnr, std::uint32_t p) noexcept;
```
指定されたバージョンで`spec`を構築します。
## メンバ変数
各フラグは機能追加がされたバージョンを指定されたとき、自動的に`true`になります。
変更して渡すことで、`toml::parse``toml::format`の挙動を変更できます。
{{<hint warning>}}
TOML v1.1.0の一部の機能にはかなり長い議論が続いており、まだ差し戻される可能性があります。
実際に差し戻された場合、toml11はマイナーバージョンアップでそれらの機能を削除、もしくは対応するそれ以降のバージョンに移動します。
そのような意味で、将来のバージョンに関する機能は全て不安定なものと考えてください。
{{</hint>}}
### 例
```cpp
auto spec = toml::spec::v(1, 0, 0);
// v1.0.0の機能に追加して、inline table内の改行を許可する。
// それ以外のv1.1.0の機能は有効化されない。
spec.v1_1_0_allow_newlines_in_inline_tables = true;
auto input = toml::parse("input_file.toml", spec);
```
### `v1_1_0_allow_control_characters_in_comments`
```cpp
bool v1_1_0_allow_control_characters_in_comments;
```
ほとんどの制御文字をコメントに含むことを許可します。
toml v1.1.0で追加。
### `v1_1_0_allow_newlines_in_inline_tables`
```cpp
bool v1_1_0_allow_newlines_in_inline_tables;
```
inline table内で改行することを許可します。
toml v1.1.0で追加。
### `v1_1_0_allow_trailing_comma_in_inline_tables`
```cpp
bool v1_1_0_allow_trailing_comma_in_inline_tables;
```
inline table内での末尾コンマを許可します。
toml v1.1.0で追加。
### `v1_1_0_add_escape_sequence_e`
```cpp
bool v1_1_0_add_escape_sequence_e;
```
`\e`でESC文字を指定できるようになります。
toml v1.1.0で追加。
### `v1_1_0_add_escape_sequence_x`
```cpp
bool v1_1_0_add_escape_sequence_x;
```
`\xHH`で1バイトの文字を指定できるようになります。
toml v1.1.0で追加。
### `v1_1_0_make_seconds_optional`
```cpp
bool v1_1_0_make_seconds_optional;
```
時刻での秒数指定を省略可能にします。
指定されなかった秒数は`0`で初期化されます。
toml v1.1.0で追加。
### `ext_hex_float`
```cpp
bool ext_hex_float;
```
toml11限定の言語拡張です。
どのバージョンを指定しても、`false`で初期化されます。
使用する際は個別に`true`にしてください。
浮動小数点数の16進数表記を許可します。
16進数表記は`printf``%a/%A`を指定した場合に準拠します。
```
hexf = 0xC0FFEEp-10
```
`toml::format` は、渡された `toml::spec``ext_hex_format``true` の場合のみ
16進表記でフォーマットします。
フォーマット情報で `hex` が指定されているにも関わらず `toml::format` に渡された
`toml::spec``ext_hex_float``false` だった場合、16進数指定は無視され、
10進表記で最大の精度で出力されます。
### `ext_num_suffix`
```cpp
bool ext_num_suffix;
```
toml11限定の言語拡張です。
どのバージョンを指定しても、`false`で初期化されます。
使用する際は個別に`true`にしてください。
10進数の整数と浮動小数点数に接尾辞を追加します。型を問わず、16進や8進、2進表記には適用されません。
数値と接尾辞の間は`_`で区切られている必要があります。
数値部分との区別のため、接尾辞は数値で始まることはできません。
```
distance = 10_m # valid
distance = 10_2m # invalid
distance = 10_2_m # valid
```
接尾辞は `std::string suffix` としてフォーマット情報に保持されます。
数値部分とを分ける `_``suffix` に含まれません。
```cpp
toml::value distance = toml::find(input, "distance");
assert(distance.as_integer_fmt().suffix == std::string("m"));
```
`toml::format` は、渡された `toml::spec``ext_num_suffix``true` の場合のみ
これをフォーマットします。
`suffix`は以下のような文法を持ちます。
```abnf
non-digit-graph = ALPHA / non-ascii
graph = ALPHA / DIGIT / non-ascii
suffix = _ non-digit-graph *( graph / ( _ graph ) )
```
### `ext_null_value`
```cpp
bool ext_null_value;
```
toml11限定の言語拡張です。
値として `null` を許可します。
`null` を指定された `toml::value` は値を持たず、 `is_empty()``true` になります。
`toml::format` は、渡された `toml::spec``ext_null_value``true` の場合のみ
`null` としてフォーマットします。
そうでない場合、 `toml::format` がエラーで終了します。

View File

@@ -0,0 +1,14 @@
+++
title = "toml.hpp"
type = "docs"
+++
# toml.hpp
`toml.hpp`は、他の全てのヘッダを `include` します。
これによって、toml11の全機能が使用可能になります。
このヘッダファイルと `toml_fwd.hpp``${TOML11_INCLUDE_DIR}/` 以下に、
他のヘッダファイルは `${toml11_include_dir}/toml11/` 以下にあります。

View File

@@ -0,0 +1,24 @@
+++
title = "toml_fwd.hpp"
type = "docs"
+++
# toml_fwd.hpp
`toml_fwd.hpp`は、toml11で定義される構造体の前方宣言と、マクロ定義を持ちます。
toml11の構造体についての前方宣言しか必要なく実装が必要ない場合、
`toml.hpp` のかわりにこちらを `include` することでコンパイル時間を短縮できます。
{{<hint warning>}}
このファイルには前方宣言しか含まれていないため、
`toml::basic_value<toml::type_config>::table_type` として定義される
`toml::table` と、同様に定義される `toml::array` は使用できません。
それらには `basic_value` の実装が必要だからです。
{{</hint>}}
このヘッダファイルと `toml.hpp``${TOML11_INCLUDE_DIR}/` 以下に、
他のヘッダファイルは `${TOML11_INCLUDE_DIR}/toml11/` 以下にあります。

View File

@@ -0,0 +1,154 @@
+++
title = "types.hpp"
type = "docs"
+++
# types.hpp
型情報を与えるクラスが定義されます。
# `type_config`
`type_config`は、`toml::basic_value`に与えられるパラメータをまとめた型です。
`toml::basic_value<T>`内で異なる型を使用する場合、これを別に定義して渡します。
記載のある要素は全て必須の要素です。
通常のストリーム演算子を使用できない数値型を使用する場合、`read_int``read_float`に相当するものを定義し、置き換えてください。
```cpp
namespace toml
{
struct type_config
{
using comment_type = preserve_comments;
using boolean_type = bool;
using integer_type = std::int64_t;
using floating_type = double;
using string_type = std::string;
template<typename T>
using array_type = std::vector<T>;
template<typename K, typename T>
using table_type = std::unordered_map<K, T>;
static result<integer_type, error_info>
parse_int(const std::string& str, const source_location src, const std::uint8_t base);
static result<floating_type, error_info>
parse_float(const std::string& str, const source_location src, const bool is_hex);
};
using value = basic_value<type_config>;
using table = typename value::table_type;
using array = typename value::array_type;
} // toml
```
## `static` メンバ関数
### `parse_int(str, src, base)`
```cpp
static result<integer_type, error_info>
parse_int(const std::string& str, const source_location src, const std::uint8_t base);
```
通常のストリーム演算子などを使用できない型を`integer_type`として使用する場合、この関数を実装してください。
`str`には、prefix、`0x`などの場合leading zero、underscoreが取り除かれた文字列が渡されます。
`src`には、その文字列が定義されていた箇所を指す`source_location`が渡されます。
`base`には、`10`, `2`, `8`, `16`のいずれかが渡されます。
### `parse_float(str, src, is_hex)`
```cpp
static result<floating_type, error_info>
parse_float(const std::string& str, const source_location src, const bool is_hex);
```
通常のストリーム演算子などを使用できない型を`floating_type`として使用する場合、この関数を実装してください。
`str`には、prefix、leading zero、underscoreが取り除かれた文字列が渡されます。
`src`には、その文字列が定義されていた箇所を指す`source_location`が渡されます。
`is_hex`には、フォーマットが`hexfloat`であるかどうかが渡されます。`hexfloat`拡張を使用しない場合は使われないので、実装する必要はありません。
`hexfloat`拡張に関しては、[spec.hpp]({{<ref "spec.md">}})を参照してください。
## 非メンバ関数
### `read_int`
```cpp
template<typename T>
result<T, error_info>
read_int(const std::string& str, const source_location src, const std::uint8_t base);
```
デフォルトで使用される関数です。`std::istringstream`を使用してパースします。
`operator>>``std::hex`等のマニピュレータ、`std::numeric_limits<T>`が定義されている場合(`boost::multiprecision`など)、特に変更なしにこれを使用できます。
### `read_float`
```cpp
template<typename T>
result<T, error_info>
read_float(const std::string& str, const source_location src, const bool is_hex);
```
デフォルトで使用される関数です。decimalの場合は`std::istringstream`を、hexfloatの場合は`sscanf()`を使用してパースします。
`double``float`に対応しています。
それ以外の型の場合、`operator>>`が定義されていて、かつ`hex`を使用しないなら、これを使用できます。
# `ordered_type_config`
`ordered_type_config`は、`toml::type_config`のテーブル型を`toml::ordered_map`に変更したものです。
また、`toml::ordered_value`エイリアスを定義します。
そのほかに`type_config`との違いはありません。
```cpp
namespace toml
{
struct ordered_type_config
{
using comment_type = preserve_comments;
using boolean_type = bool;
using integer_type = std::int64_t;
using floating_type = double;
using string_type = std::string;
template<typename T>
using array_type = std::vector<T>;
template<typename K, typename T>
using table_type = ordered_map<K, T>;
static result<integer_type, error_info>
parse_int(const std::string& str, const source_location src, const std::uint8_t base)
{
return read_int<integer_type>(str, src, base);
}
static result<floating_type, error_info>
parse_float(const std::string& str, const source_location src, const bool is_hex)
{
return read_float<floating_type>(str, src, is_hex);
}
};
using ordered_value = basic_value<ordered_type_config>;
using ordered_table = typename ordered_value::table_type;
using ordered_array = typename ordered_value::array_type;
} // toml
```

View File

@@ -0,0 +1,896 @@
+++
title = "value.hpp"
type = "docs"
+++
# value.hpp
`value.hpp`では、`basic_value`が定義されます。
# `toml::basic_value`
`basic_value`は、TOMLの値を格納するクラスです。
```cpp
namespace toml
{
template <class TypeConfig>
class basic_value;
// 以下はtypes.hppで定義される
// using value = basic_value<type_config>;
// using table = typename basic_value<type_config>::table_type;
// using array = typename basic_value<type_config>::array_type;
template<typename TC>
bool operator==(const basic_value<TC>&, const basic_value<TC>&);
template<typename TC>
bool operator!=(const basic_value<TC>&, const basic_value<TC>&);
template<typename TC>
bool operator< (const basic_value<TC>&, const basic_value<TC>&);
template<typename TC>
bool operator<=(const basic_value<TC>&, const basic_value<TC>&);
template<typename TC>
bool operator> (const basic_value<TC>&, const basic_value<TC>&);
template<typename TC>
bool operator>=(const basic_value<TC>&, const basic_value<TC>&);
} //toml
```
## メンバ型
以下のメンバ型が定義されます。
`TypeConfig`を使って、メンバ型を変更することができます。
参考: [types.hpp]({{<ref "types.md">}})
| 名前 | 定義 |
|:-----------------------|:-------------------------------------|
| `char_type` | `typename TypeConfig::char_type` |
| `key_type` | `typename TypeConfig::string_type` |
| `value_type` | `basic_value<TypeConfig>` |
| `boolean_type` | `typename TypeConfig::boolean_type` |
| `integer_type` | `typename TypeConfig::integer_type` |
| `floating_type` | `typename TypeConfig::floating_type` |
| `string_type` | `typename TypeConfig::string_type` |
| `local_time_type` | `toml::local_time` |
| `local_date_type` | `toml::local_date` |
| `local_datetime_type` | `toml::local_datetime` |
| `offset_datetime_type` | `toml::offset_datetime` |
| `array_type` | `typename TypeConfig::template array_type<value_type>`|
| `table_type` | `typename TypeConfig::template table_type<key_type, value_type>`|
| `comment_type` | `typename TypeConfig::comment_type` |
## メンバ関数
### デフォルトコンストラクタ
```cpp
basic_value() noexcept
```
空の`toml::value`を構築します。
構築された`toml::value`は空になります。
### コピー・ムーブコンストラクタ
```cpp
basic_value(const basic_value& v)
basic_value(basic_value&& v)
```
値、フォーマット情報、コメント、ファイル領域の全ての情報をコピー・ムーブします。
### コピー・ムーブコンストラクタ(コメント指定)
```cpp
basic_value(basic_value v, std::vector<std::string> com)
```
コメントを上書きしながらコピー・ムーブします。
### 変換コンストラクタ
```cpp
template<typename TI>
basic_value(basic_value<TI> other)
template<typename TI>
basic_value(basic_value<TI> other, std::vector<std::string> com)
```
異なる`type_config`を持つ`basic_value`からコピー・ムーブします。
### コンストラクタ (boolean)
```cpp
basic_value(boolean_type x)
basic_value(boolean_type x, boolean_format_info fmt)
basic_value(boolean_type x, std::vector<std::string> com)
basic_value(boolean_type x, boolean_format_info fmt, std::vector<std::string> com)
```
`bool`と、そのフォーマット情報、コメントを受け取って構築します。
### コンストラクタ (integer)
```cpp
basic_value(integer_type x)
basic_value(integer_type x, integer_format_info fmt)
basic_value(integer_type x, std::vector<std::string> com)
basic_value(integer_type x, integer_format_info fmt, std::vector<std::string> com)
```
`integer`と、そのフォーマット情報、コメントを受け取って構築します。
### コンストラクタ(floating)
```cpp
template<typename T, /* T は std::is_floating_point<T> を満たす */>
basic_value(T x)
template<typename T, /* T は std::is_floating_point<T> を満たす */>
basic_value(T x, floating_format_info fmt)
template<typename T, /* T は std::is_floating_point<T> を満たす */>
basic_value(T x, std::vector<std::string> com)
template<typename T, /* T は std::is_floating_point<T> を満たす */>
basic_value(T x, floating_format_info fmt, std::vector<std::string> com)
```
`floating`と、そのフォーマット情報、コメントを受け取って構築します。
### コンストラクタ(string)
```cpp
basic_value(string_type x)
basic_value(string_type x, string_format_info fmt)
basic_value(string_type x, std::vector<std::string> com)
basic_value(string_type x, string_format_info fmt, std::vector<std::string> com)
basic_value(const string_type::value_type* x)
basic_value(const string_type::value_type* x, string_format_info fmt)
basic_value(const string_type::value_type* x, std::vector<std::string> com)
basic_value(const string_type::value_type* x, string_format_info fmt, std::vector<std::string> com)
// C++17以降
basic_value(string_view_type x)
basic_value(string_view_type x, string_format_info fmt)
basic_value(string_view_type x, std::vector<std::string> com)
basic_value(string_view_type x, string_format_info fmt, std::vector<std::string> com)
```
`string`と、そのフォーマット情報、コメントを受け取って構築します。
`string_view_type`は、`string_type`と同じ`value_type``traits_type`を持ちます。
### コンストラクタ(local_date)
```cpp
basic_value(local_date_type x)
basic_value(local_date_type x, local_date_format_info fmt)
basic_value(local_date_type x, std::vector<std::string> com)
basic_value(local_date_type x, local_date_format_info fmt, std::vector<std::string> com)
```
`local_date_type`と、そのフォーマット情報、コメントを受け取って構築します。
### コンストラクタ(local_time)
```cpp
basic_value(local_time_type x)
basic_value(local_time_type x, local_time_format_info fmt)
basic_value(local_time_type x, std::vector<std::string> com)
basic_value(local_time_type x, local_time_format_info fmt, std::vector<std::string> com)
template<typename Rep, typename Period>
basic_value(const std::chrono::duration<Rep, Period>& x)
template<typename Rep, typename Period>
basic_value(const std::chrono::duration<Rep, Period>& x, local_time_format_info fmt)
template<typename Rep, typename Period>
basic_value(const std::chrono::duration<Rep, Period>& x, std::vector<std::string> com)
template<typename Rep, typename Period>
basic_value(const std::chrono::duration<Rep, Period>& x, local_time_format_info fmt, std::vector<std::string> com)
```
`local_time_type`と、そのフォーマット情報、コメントを受け取って構築します。
`std::chrono::duration`は、`00:00:00`からの時間幅として構築します。
### コンストラクタ(local_datetime)
```cpp
basic_value(local_datetime_type x)
basic_value(local_datetime_type x, local_date_format_info fmt)
basic_value(local_datetime_type x, std::vector<std::string> com)
basic_value(local_datetime_type x, local_date_format_info fmt, std::vector<std::string> com)
```
`local_datetime_type`と、そのフォーマット情報、コメントを受け取って構築します。
### コンストラクタ(offset_datetime)
```cpp
basic_value(offset_datetime_type x)
basic_value(offset_datetime_type x, offset_date_format_info fmt)
basic_value(offset_datetime_type x, std::vector<std::string> com)
basic_value(offset_datetime_type x, offset_date_format_info fmt, std::vector<std::string> com)
basic_value(std::chrono::system_clock::time_point x)
basic_value(std::chrono::system_clock::time_point x, offset_date_format_info fmt)
basic_value(std::chrono::system_clock::time_point x, std::vector<std::string> com)
basic_value(std::chrono::system_clock::time_point x, offset_date_format_info fmt, std::vector<std::string> com)
```
`offset_datetime_type`と、そのフォーマット情報、コメントを受け取って構築します。
`std::chrono::system_clock::time_point`の場合、それが指す時点として構築します。
### コンストラクタ(array)
```cpp
basic_value(array_type x)
basic_value(array_type x, integer_format_info fmt)
basic_value(array_type x, std::vector<std::string> com)
basic_value(array_type x, integer_format_info fmt, std::vector<std::string> com)
template<typename T, /* T is array-like */>
basic_value(T x)
template<typename T, /* T is array-like */>
basic_value(T x, array_format_info fmt)
template<typename T, /* T is array-like */>
basic_value(T x, std::vector<std::string> com)
template<typename T, /* T is array-like */>
basic_value(T x, array_format_info fmt, std::vector<std::string> com)
```
`array`と、そのフォーマット情報、コメントを受け取って構築します。
`array-like`は、以下の条件を満たす型です。
- `T::iterator` を持つ。
- `T::value_type` を持つ。
- `T::key_type` を持た**ない**。
- `T::mapped_type` を持た**ない**。
- `std::string` では**ない**。
- `std::string_view` では**ない**。(C++17以降)
### コンストラクタ(table)
```cpp
basic_value(table_type x)
basic_value(table_type x, integer_format_info fmt)
basic_value(table_type x, std::vector<std::string> com)
basic_value(table_type x, integer_format_info fmt, std::vector<std::string> com)
template<typename T, /* T is table-like */>
basic_value(T x)
template<typename T, /* T is table-like */>
basic_value(T x, table_format_info fmt)
template<typename T, /* T is table-like */>
basic_value(T x, std::vector<std::string> com)
template<typename T, /* T is table-like */>
basic_value(T x, table_format_info fmt, std::vector<std::string> com)
```
`table`と、そのフォーマット情報、コメントを受け取って構築します。
`table-like`は、以下の条件を満たす型です。
- `T::iterator` を持つ。
- `T::value_type` を持つ。
- `T::key_type` を持つ。
- `T::mapped_type` を持つ。
### コンストラクタ(user-defined)
```cpp
template<typename T /* toml::into<T>が定義されていること */>
basic_value(const T& ud);
template<typename T /* toml::into<T>が定義されていること */>
basic_value(const T& ud, std::vector<std::string> com);
template<typename T /* into<T>は定義されておらず、T{}.into_toml()が存在すること */>
basic_value(const T& ud);
template<typename T /* into<T>は定義されておらず、T{}.into_toml()が存在すること */>
basic_value(const T& ud, std::vector<std::string> com);
```
`toml::into<T>` が定義されていた場合、 `toml::into<T>(ud)` の結果から構築します。
`toml::into<T>` が定義されておらず、 `T``into_toml()` メンバ関数が定義されていた場合、
`ud.into_toml()`の結果から構築します。
-----
### `operator=(basic_value)`
```cpp
basic_value& operator=(const basic_value& v)
basic_value& operator=(basic_value&& v)
template<typename TI>
basic_value& operator=(basic_value<TI> other)
```
右辺の`basic_value`を代入します。
### `operator=(T)`
```cpp
template<typename T>
basic_value& operator=(T x)
```
Tに対応する値を代入します。
`source_location`の指す内容は破棄されます。
もし同じ型の値を持っていたなら、元のフォーマット情報が保持されます。
-----
### `is<T>()`
```cpp
bool is<T>() const noexcept
```
#### 条件
`T`は厳密にTOML型であること。つまり、値に対応する`toml::value::xxx_type`のいずれかであること。
#### 戻り値
格納している型が`T`と一致した場合`true`を、そうでない場合は`false`を返します。
-----
### `is(toml::value_t)`
```cpp
bool is(toml::value_t t) const noexcept
```
#### 戻り値
格納している型のタグが`t`と一致した場合`true`を、そうでない場合は`false`を返します。
-----
### `is_xxx()`
```cpp
bool is_boolean() const noexcept;
bool is_integer() const noexcept;
bool is_floating() const noexcept;
bool is_string() const noexcept;
bool is_offset_datetime() const noexcept;
bool is_local_datetime() const noexcept;
bool is_local_date() const noexcept;
bool is_local_time() const noexcept;
bool is_array() const noexcept;
bool is_table() const noexcept;
```
#### 戻り値
格納している型がその型である場合`true`を、そうでない場合は`false`を返します。
-----
### `is_empty()`
```cpp
bool is_empty() const noexcept;
```
#### 戻り値
デフォルト構築され値が代入されていない場合`true`を、そうでない場合は`false`を返します。
### `is_array_of_tables()`
```cpp
bool is_array_of_tables() const noexcept;
```
#### 戻り値
格納している型が配列であり、空ではなく、全要素がテーブルの場合は`true`を、そうでない場合は`false`を返します。
-----
### `type()`
```cpp
toml::value_t type() const noexcept
```
#### 戻り値
格納している型に対応するタグを返します。
-----
### `as_xxx()`
```cpp
boolean_type const& as_boolean () const;
integer_type const& as_integer () const;
floating_type const& as_floating () const;
string_type const& as_string () const;
offset_datetime_type const& as_offset_datetime() const;
local_datetime_type const& as_local_datetime () const;
local_date_type const& as_local_date () const;
local_time_type const& as_local_time () const;
array_type const& as_array () const;
table_type const& as_table () const;
boolean_type & as_boolean ();
integer_type & as_integer ();
floating_type & as_floating ();
string_type & as_string ();
offset_datetime_type& as_offset_datetime();
local_datetime_type & as_local_datetime ();
local_date_type & as_local_date ();
local_time_type & as_local_time ();
array_type & as_array ();
table_type & as_table ();
```
#### 戻り値
指定された型への参照を返します。
#### 例外
格納されている値の型が指定と異なる場合、`toml::type_error`を送出します。
-----
### `as_xxx(std::nothrow)`
`std::nothrow`オブジェクトを渡して呼び出します。
```cpp
boolean_type const& as_boolean (const std::nothrow_t&) const noexcept;
integer_type const& as_integer (const std::nothrow_t&) const noexcept;
floating_type const& as_floating (const std::nothrow_t&) const noexcept;
string_type const& as_string (const std::nothrow_t&) const noexcept;
offset_datetime_type const& as_offset_datetime(const std::nothrow_t&) const noexcept;
local_datetime_type const& as_local_datetime (const std::nothrow_t&) const noexcept;
local_date_type const& as_local_date (const std::nothrow_t&) const noexcept;
local_time_type const& as_local_time (const std::nothrow_t&) const noexcept;
array_type const& as_array (const std::nothrow_t&) const noexcept;
table_type const& as_table (const std::nothrow_t&) const noexcept;
boolean_type & as_boolean (const std::nothrow_t&) noexcept;
integer_type & as_integer (const std::nothrow_t&) noexcept;
floating_type & as_floating (const std::nothrow_t&) noexcept;
string_type & as_string (const std::nothrow_t&) noexcept;
offset_datetime_type& as_offset_datetime(const std::nothrow_t&) noexcept;
local_datetime_type & as_local_datetime (const std::nothrow_t&) noexcept;
local_date_type & as_local_date (const std::nothrow_t&) noexcept;
local_time_type & as_local_time (const std::nothrow_t&) noexcept;
array_type & as_array (const std::nothrow_t&) noexcept;
table_type & as_table (const std::nothrow_t&) noexcept;
```
#### 戻り値
指定された型への参照を返します。
#### 備考
格納されている値の型が指定と異なる場合、未定義動作となります。
-----
### `as_xxx_fmt()`
フォーマット情報にアクセスします。
```cpp
boolean_format_info & as_boolean_fmt ();
integer_format_info & as_integer_fmt ();
floating_format_info & as_floating_fmt ();
string_format_info & as_string_fmt ();
offset_datetime_format_info& as_offset_datetime_fmt();
local_datetime_format_info & as_local_datetime_fmt ();
local_date_format_info & as_local_date_fmt ();
local_time_format_info & as_local_time_fmt ();
array_format_info & as_array_fmt ();
table_format_info & as_table_fmt ();
boolean_format_info const& as_boolean_fmt () const;
integer_format_info const& as_integer_fmt () const;
floating_format_info const& as_floating_fmt () const;
string_format_info const& as_string_fmt () const;
offset_datetime_format_info const& as_offset_datetime_fmt() const;
local_datetime_format_info const& as_local_datetime_fmt () const;
local_date_format_info const& as_local_date_fmt () const;
local_time_format_info const& as_local_time_fmt () const;
array_format_info const& as_array_fmt () const;
table_format_info const& as_table_fmt () const;
```
#### 戻り値
指定された型のフォーマット情報を持つ構造体への参照を返します。
#### 例外
格納されている値の型が指定と異なる場合、`toml::type_error`を送出します。
-----
### `as_xxx_fmt(std::nothrow)`
`std::nothrow`オブジェクトを渡して呼び出します。
```cpp
boolean_format_info & as_boolean_fmt (const std::nothrow_t&) noexcept;
integer_format_info & as_integer_fmt (const std::nothrow_t&) noexcept;
floating_format_info & as_floating_fmt (const std::nothrow_t&) noexcept;
string_format_info & as_string_fmt (const std::nothrow_t&) noexcept;
offset_datetime_format_info& as_offset_datetime_fmt(const std::nothrow_t&) noexcept;
local_datetime_format_info & as_local_datetime_fmt (const std::nothrow_t&) noexcept;
local_date_format_info & as_local_date_fmt (const std::nothrow_t&) noexcept;
local_time_format_info & as_local_time_fmt (const std::nothrow_t&) noexcept;
array_format_info & as_array_fmt (const std::nothrow_t&) noexcept;
table_format_info & as_table_fmt (const std::nothrow_t&) noexcept;
boolean_format_info const& as_boolean_fmt (const std::nothrow_t&) const noexcept;
integer_format_info const& as_integer_fmt (const std::nothrow_t&) const noexcept;
floating_format_info const& as_floating_fmt (const std::nothrow_t&) const noexcept;
string_format_info const& as_string_fmt (const std::nothrow_t&) const noexcept;
offset_datetime_format_info const& as_offset_datetime_fmt(const std::nothrow_t&) const noexcept;
local_datetime_format_info const& as_local_datetime_fmt (const std::nothrow_t&) const noexcept;
local_date_format_info const& as_local_date_fmt (const std::nothrow_t&) const noexcept;
local_time_format_info const& as_local_time_fmt (const std::nothrow_t&) const noexcept;
array_format_info const& as_array_fmt (const std::nothrow_t&) const noexcept;
table_format_info const& as_table_fmt (const std::nothrow_t&) const noexcept;
```
#### 戻り値
指定された型のフォーマット情報を持つ構造体への参照を返します。
#### 備考
格納されている値の型が指定と異なる場合、未定義動作となります。
-----
### `at(key)`
```cpp
value_type& at(const key_type& key);
value_type const& at(const key_type& key) const;
```
#### 戻り値
今の`value``table`にキャストしたあと、`key`によって指定される要素を返します。
#### 例外
もし格納している値が`table`ではなかった場合、`toml::type_error`を送出します。
もし格納している`table`が指定された要素を持っていなかった場合、`std::out_of_range`を送出します。
-----
#### `operator[](key)`
```cpp
value_type& operator[](const key_type& k);
```
##### 戻り値
今の`value``table`にキャストしたあと、`key`によって指定される要素への参照です。
もし`key`によって指定される要素が存在しない場合、デフォルト構築されます。
##### 例外
もし格納している値が`table`ではなかった場合、`toml::type_error`を送出します。
-----
### `count(key)`
```cpp
std::size_t count(const key_type& key) const;
```
#### 戻り値
今の`value``table`にキャストしたあと、`key`に対応する要素が含まれていれば`1`、そうでなければ`0`を返します。
#### 例外
もし格納している値が`table`ではなかった場合、`toml::type_error`を送出します。
-----
### `contains(key)`
```cpp
bool contains(const key_type& key) const;
```
#### 戻り値
今の`value``table`にキャストしたあと、`key`に対応する要素が含まれていれば`true`、そうでなければ`false`を返します。
#### 例外
もし格納している値が`table`ではなかった場合、`toml::type_error`を送出します。
-----
### `at(idx)`
```cpp
value_type& at(const std::size_t idx);
value_type const& at(const std::size_t idx) const;
```
#### 戻り値
今の`value``array`にキャストしたあと、`idx`によって指定される要素を返します。
#### 例外
もし格納している値が`array`ではなかった場合、`toml::type_error`を送出します。
もし格納している`array`が指定された要素を持っていなかった場合、`std::out_of_range`を送出します。
-----
### `operator[](idx)`
```cpp
value_type& operator[](const std::size_t idx) noexcept;
value_type const& operator[](const std::size_t idx) const noexcept;
```
#### 戻り値
今の`value``array`にキャストしたあと、`idx`によって指定される要素への参照を返します。
#### 備考
一切のチェックを行いません。
もし格納している値が`array`ではなかった場合、あるいは`idx`によって指定される要素が存在しない場合、未定義動作となります。
-----
### `push_back(value)`
```cpp
void push_back(const value_type& x);
void push_back(value_type&& x);
```
`value``array`にキャストしたのち、その`array`に対して`push_back`を実行します。
#### 戻り値
なし。
#### 例外
格納している値が`array`ではなかった場合、`toml::type_error`を送出します。
-----
### `emplace_back(args...)`
```cpp
template<typename ... Ts>
value_type& emplace_back(Ts&& ... args)
```
`value``array`にキャストしたのち、その`array`に対して`emplace_back`を実行します。
#### 戻り値
構築した値への参照。
#### 例外
格納している値が`array`ではなかった場合、`toml::type_error`を送出します。
-----
### `size()`
```cpp
std::size_t size() const;
```
#### 戻り値
今の`value``array``string``table`のどれかにキャストしたあと、その要素数を返します。
`string`の場合、文字数を返します。
#### 例外
格納している値が`array`, `string`, `table`のどれでもなかった場合、`toml::type_error`を送出します。
-----
### `location()`
```cpp
source_location location() const;
```
#### 戻り値
その`value`が定義されたTOML文書内の位置を表す`source_location`オブジェクトを返します。
もしTOML文書のパースによって構築されたものでない場合、どこも指示さない`source_location`を返します。
-----
### `comments()`
```cpp
comment_type const& comments() const noexcept;
comment_type& comments() noexcept;
```
#### 戻り値
コメント用コンテナへの参照を返します。
## 非メンバ関数
### `operator==`
```cpp
template<typename TC>
bool operator==(const basic_value<TC>&, const basic_value<TC>&);
```
以下を満たすとき、2つの`basic_value<T>`は同値となります。
- TOML型が同一
- 含む値が同一
- コメントがバイト単位で同一
### `operator!=`
```cpp
template<typename TC>
bool operator!=(const basic_value<TC>& lhs, const basic_value<TC>& rhs)
{
return !(lhs == rhs);
}
```
### `operator<`
`array_type``table_type``operator<`を持っている場合のみ定義されます。
```cpp
template<typename TC>
bool operator<(const basic_value<TC>&, const basic_value<TC>&);
```
以下の順番で比較されます。
1. TOML型
2. TOML型が同一の場合、その値
3. TOML型とその値が同一の場合、コメント
TOML型は、以下の順に小さい値を持ちます。
1. `toml::value_t::empty`
2. `toml::value_t::boolean`
3. `toml::value_t::integer`
4. `toml::value_t::floating`
5. `toml::value_t::string`
6. `toml::value_t::offset_datetime`
7. `toml::value_t::local_datetime`
8. `toml::value_t::local_date`
9. `toml::value_t::local_time`
10. `toml::value_t::array`
11. `toml::value_t::table`
### `operator<=`
`array_type``table_type``operator<`を持っている場合のみ定義されます。
```cpp
template<typename TC>
bool operator<=(const basic_value<TC>& lhs, const basic_value<TC>& rhs)
{
return (lhs < rhs) || (lhs == rhs);
}
```
### `operator>`
`array_type``table_type``operator<`を持っている場合のみ定義されます。
```cpp
template<typename TC>
bool operator>(const basic_value<TC>& lhs, const basic_value<TC>& rhs)
{
return !(lhs <= rhs);
}
```
### `operator>=`
`array_type``table_type``operator<`を持っている場合のみ定義されます。
```cpp
template<typename TC>
bool operator>=(const basic_value<TC>& lhs, const basic_value<TC>& rhs)
{
return !(lhs < rhs);
}
```
# `toml::type_error`
型エラーの際に送出される例外です。
型エラーが生じた値の位置情報が格納されています。
```cpp
struct type_error final : public ::toml::exception
{
public:
type_error(std::string what_arg, source_location loc);
~type_error() noexcept override = default;
const char* what() const noexcept override;
source_location const& location() const noexcept;
};
```
# `toml::make_error_info`
```cpp
template<typename TC, typename ... Ts>
error_info make_error_info(
std::string title, const basic_value<TC>& v, std::string msg, Ts&& ... tail);
```
`basic_value``location()` を呼び出して、その `source_location`
[`make_error_info`]({{<ref "docs/reference/error_info#make_error_info">}})
に渡して `error_info` を作成します。
詳しくは [`error_info`]({{<ref "docs/reference/error_info">}}) を参照してください。
# `toml::format_error`
```cpp
template<typename TC, typename ... Ts>
std::string format_error(std::string title,
const basic_value<TC>& v, std::string msg, Ts&& ... tail);
```
`basic_value``location()` を呼び出して、その `source_location`
[`format_error`]({{<ref "docs/reference/error_info#format_error">}})
に渡して `error_info` を作成し、それを文字列化して返します。
詳しくは [`error_info`]({{<ref "docs/reference/error_info">}}) を参照してください。
# 関連項目
- [comments.hpp]({{<ref "comments.md">}})
- [source_location.hpp]({{<ref "source_location.md">}})
- [types.hpp]({{<ref "types.md">}})
- [visit.hpp]({{<ref "visit.md">}})

View File

@@ -0,0 +1,54 @@
+++
title = "value_t.hpp"
type = "docs"
+++
# value_t.hpp
型情報を表す列挙型です。
# `value_t`
`value_t`は、`toml::value`が持つ型情報を扱う際に使用します。
```cpp
namespace toml
{
enum class value_t : std::uint8_t
{
empty = 0,
boolean = 1,
integer = 2,
floating = 3,
string = 4,
offset_datetime = 5,
local_datetime = 6,
local_date = 7,
local_time = 8,
array = 9,
table = 10
};
std::ostream& operator<<(std::ostream& os, value_t t);
std::string to_string(value_t t);
} // toml
```
## 非メンバ関数
### ストリーム演算子
```cpp
std::ostream& operator<<(std::ostream& os, value_t t);
```
`value_t`の値を文字列化してストリームへ出力します。
### `to_string`
```cpp
std::string to_string(value_t t);
```
`value_t`の値を文字列化して返します。

View File

@@ -0,0 +1,37 @@
+++
title = "version.hpp"
type = "docs"
+++
# version.hpp
`version.hpp`では、toml11とC++のバージョン情報に関係するマクロが定義されます。
## マクロ
### `TOML11_VERSION_MAJOR`
toml11のメジャーバージョンです。
### `TOML11_VERSION_MINOR`
toml11のマイナーバージョンです。
### `TOML11_VERSION_PATCH`
toml11のパッチバージョンです。
## 関数
### `license_notice`
```cpp
namespace toml
{
const char* license_notice() noexcept;
}
```
ライセンス条項を返します。
ソースコードを公開せずに頒布する際の利便性のために用意されています。

View File

@@ -0,0 +1,69 @@
+++
title = "visit.hpp"
type = "docs"
+++
# visit.hpp
`visit.hpp`では、`toml::visit`が定義されます。
# `toml::visit`
## 関数
```cpp
namespace toml
{
template<typename Visitor, typename TC>
/* Visitor を basic_value<TC>の値で呼び出した際の返り値 */
visit(Visitor&& visitor, const basic_value<TC>& v);
template<typename Visitor, typename TC>
/* Visitor を basic_value<TC>の値で呼び出した際の返り値 */
visit(Visitor&& visitor, basic_value<TC>& v)
template<typename Visitor, typename TC>
/* Visitor を basic_value<TC>の値で呼び出した際の返り値 */
visit(Visitor&& visitor, basic_value<TC>&& v)
}
```
`basic_value<TC>`が保持している型に対応する`Visitor`のオーバーロードを呼び出し、その結果を返します。
#### 条件
`Visitor`は、`basic_value<TC>`が保持している型のどれに対しても呼び出し可能な関数または関数オブジェクトでなければなりません。
また、それぞれのオーバーロードで返り値は同じであることが要求されます。
#### 例
```cpp
#include <toml.hpp>
#include <iostream>
struct type_name_of
{
std::string operator()(const toml::value::boolean_type &) const {return "boolean";}
std::string operator()(const toml::value::integer_type &) const {return "integer";}
std::string operator()(const toml::value::floating_type &) const {return "floating";}
std::string operator()(const toml::value::string_type &) const {return "string";}
std::string operator()(const toml::value::local_time_type &) const {return "local_time";}
std::string operator()(const toml::value::local_date_type &) const {return "local_date";}
std::string operator()(const toml::value::local_datetime_type &) const {return "local_datetime";}
std::string operator()(const toml::value::offset_datetime_type&) const {return "offset_datetime";}
std::string operator()(const toml::value::array_type &) const {return "array";}
std::string operator()(const toml::value::table_type &) const {return "table";}
};
int main()
{
toml::value v(3.14);
std::cout << toml::visit(type_name_of{}, v) << std::endl; // floating
return 0;
}
```
# 関連項目
- [value.hpp]({{<ref "value.md">}})