mirror of
https://github.com/ToruNiina/toml11.git
synced 2024-09-19 15:19:54 +00:00
Merge branch 'v4_1_0' into try-get
This commit is contained in:
commit
00d6124f59
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@ -53,7 +53,7 @@ jobs:
|
||||
sudo apt-get install clang-${{ matrix.compiler }}
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -B build/ -DCMAKE_VERBOSE_MAKEFILE=1 -DCMAKE_CXX_COMPILER=clang++-${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=${{ matrix.precompile }}
|
||||
cmake -B build/ -DCMAKE_CXX_COMPILER=clang++-${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=${{ matrix.precompile }}
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build/
|
||||
|
10
README.md
10
README.md
@ -8,7 +8,7 @@
|
||||
|
||||
[日本語版](https://github.com/ToruNiina/toml11/blob/main/README_ja.md)
|
||||
|
||||
toml11 is a feature-rich TOML language library for C++.
|
||||
toml11 is a feature-rich TOML language library for C++11/14/17/20.
|
||||
|
||||
- It complies with [the latest TOML language specification](https://toml.io/en/v1.0.0).
|
||||
- It passes all the standard TOML language [test cases](https://github.com/toml-lang/toml-test).
|
||||
@ -124,6 +124,14 @@ $ cmake -B ./build/ -DTOML11_PRECOMPILE=ON -DCMAKE_CXX_STANDARD=11/14/17/20
|
||||
$ cmake --build ./build/
|
||||
```
|
||||
|
||||
When linking the library, use `target_link_libraries` in CMake
|
||||
|
||||
```cmake
|
||||
target_link_libraries(your_target PUBLIC toml11::toml11)
|
||||
```
|
||||
|
||||
or pass `-DTOML11_COMPILE_SOURCES` to the compiler.
|
||||
|
||||
### Building Example
|
||||
|
||||
To compile the examples in the `examples/` directory, set `-DTOML11_BUILD_EXAMPLES=ON`.
|
||||
|
10
README_ja.md
10
README_ja.md
@ -5,7 +5,7 @@
|
||||
[![License](https://img.shields.io/github/license/ToruNiina/toml11.svg?style=flat)](LICENSE)
|
||||
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1209136.svg)](https://doi.org/10.5281/zenodo.1209136)
|
||||
|
||||
toml11は、C++のための豊富な機能を持つTOML言語ライブラリです。
|
||||
toml11は、C++11,14,17,20のための豊富な機能を持つTOML言語ライブラリです。
|
||||
|
||||
- [TOML言語の最新規格](https://toml.io/ja/v1.0.0)に準拠しています。
|
||||
- TOML言語標準のテストケースすべてにパスしています。
|
||||
@ -122,6 +122,14 @@ $ cmake -B ./build/ -DTOML11_PRECOMPILE=ON -DCMAKE_CXX_STANDARD=11/14/17/20
|
||||
$ cmake --build ./build/
|
||||
```
|
||||
|
||||
ライブラリをリンクする場合は、CMakeで
|
||||
|
||||
```cmake
|
||||
target_link_libraries(your_target PUBLIC toml11::toml11)
|
||||
```
|
||||
|
||||
とするか、コンパイラに`-DTOML11_COMPILE_SOURCES`を渡してください。
|
||||
|
||||
### Building example
|
||||
|
||||
`-DTOML11_BUILD_EXAMPLES=ON`とすることで、`examples/`をコンパイルできます。
|
||||
|
@ -42,10 +42,18 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
#### Specifying a File with `std::filesystem::path`
|
||||
|
||||
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}}) can accept a `std::filesystem::path`.
|
||||
|
||||
This requires C++17 or later, as it relies on the `<filesystem>` support.
|
||||
|
||||
#### Specifying an Input Stream with `std::istream`
|
||||
|
||||
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}}) can also accept an `std::istream`.
|
||||
|
||||
Open a stream in binary mode by passing `std::ios::binary` to avoid inconsistency between the file size and the number of characters due to automatic conversion of newline characters by the standard library.
|
||||
|
||||
Without the filename information, error messages will display `"unknown file"`. To avoid this, you can pass the filename as a `std::string` in the second argument when using `std::istream`.
|
||||
|
||||
You can use streams other than `std::ifstream`, such as `std::istringstream`. Note that the entire content is readable at the time of the call.
|
||||
@ -64,16 +72,12 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
#### Specifying a File with `std::filesystem::path`
|
||||
|
||||
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}}) can accept a `std::filesystem::path`.
|
||||
|
||||
This requires C++17 or later, as it relies on the `<filesystem>` support.
|
||||
|
||||
#### Specifying a File with `FILE*`
|
||||
|
||||
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}}) can also accept a `FILE*`.
|
||||
|
||||
Open a stream in binary mode by passing `"rb"` to avoid inconsistency between the file size and the number of characters due to automatic conversion of newline characters by the standard library.
|
||||
|
||||
As with `std::istream`, you need to provide the filename as a string in the second argument.
|
||||
|
||||
When passing a `FILE*`, if the file read fails, `errno` will be reported.
|
||||
|
@ -54,6 +54,14 @@ By defining `-DTOML11_PRECOMPILE=ON` when running cmake, you can precompile some
|
||||
$ cmake -B ./build/ -DTOML11_PRECOMPILE=ON
|
||||
```
|
||||
|
||||
When linking the library, use `target_link_libraries` in CMake
|
||||
|
||||
```cmake
|
||||
target_link_libraries(your_target PUBLIC toml11::toml11)
|
||||
```
|
||||
|
||||
or pass `-DTOML11_COMPILE_SOURCES` to the compiler to suppress header-only features.
|
||||
|
||||
However, since toml11 supports multiple C++ versions and may switch types based on the value of `__cplusplus`,
|
||||
there is a possibility of link failures if the version used during build differs from the version used during usage.
|
||||
If you encounter issues, set the required version using `CMAKE_CXX_STANDARD` during compilation.
|
||||
|
@ -17,23 +17,6 @@ In case of failure, `toml::syntax_error` is thrown.
|
||||
|
||||
The type information of `basic_value` is provided by a `template`, and the TOML language version is specified by `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());
|
||||
}
|
||||
```
|
||||
|
||||
Parses the content of the given `std::istream&`.
|
||||
|
||||
The filename information is taken as the third argument. If the filename is not provided, it defaults to `"unknown file"`.
|
||||
|
||||
### `parse(std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
@ -90,6 +73,25 @@ If reading the file fails, `toml::file_io_error` is thrown.
|
||||
|
||||
If parsing fails, `toml::syntax_error` is thrown.
|
||||
|
||||
### `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());
|
||||
}
|
||||
```
|
||||
|
||||
Parses the content of the given `std::istream&`.
|
||||
|
||||
Open a stream in binary mode by passing `std::ios::binary` to avoid inconsistency between the file size and the number of characters due to automatic conversion of newline characters by the standard library.
|
||||
|
||||
The filename information is taken as the third argument. If the filename is not provided, it defaults to `"unknown file"`.
|
||||
|
||||
### `parse(FILE*, std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
@ -105,6 +107,8 @@ parse(FILE* fp,
|
||||
|
||||
Parses the content of the file pointed to by `FILE*`.
|
||||
|
||||
Open a stream in binary mode by passing `"rb"` to avoid inconsistency between the file size and the number of characters due to automatic conversion of newline characters by the standard library.
|
||||
|
||||
If reading the file fails, `file_io_error` containing `errno` is thrown.
|
||||
|
||||
If parsing fails, `syntax_error` is thrown.
|
||||
@ -166,27 +170,6 @@ For instance, errors occurring internally within `std::ifstream` or memory exhau
|
||||
|
||||
{{< /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());
|
||||
}
|
||||
```
|
||||
|
||||
Takes a `std::istream&` and parses its content.
|
||||
|
||||
The file name information is taken as the second argument. If a file name is not provided, it defaults to `"unknown file"`.
|
||||
|
||||
If parsing fails, a `result` holding the error type `std::vector<error_info>` is returned.
|
||||
|
||||
If successful, a `result` holding a `basic_value` is returned.
|
||||
|
||||
### `try_parse(std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
@ -241,6 +224,29 @@ If parsing fails, a `result` holding the error type `std::vector<error_info>` is
|
||||
|
||||
If successful, a `result` holding a `basic_value` is returned.
|
||||
|
||||
### `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());
|
||||
}
|
||||
```
|
||||
|
||||
Takes a `std::istream&` and parses its content.
|
||||
|
||||
Open a stream in binary mode by passing `std::ios::binary` to avoid inconsistency between the file size and the number of characters due to automatic conversion of newline characters by the standard library.
|
||||
|
||||
The file name information is taken as the second argument. If a file name is not provided, it defaults to `"unknown file"`.
|
||||
|
||||
If parsing fails, a `result` holding the error type `std::vector<error_info>` is returned.
|
||||
|
||||
If successful, a `result` holding a `basic_value` is returned.
|
||||
|
||||
### `try_parse(FILE*, std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
@ -256,6 +262,8 @@ try_parse(FILE* fp,
|
||||
|
||||
Takes a `FILE*` and parses its content.
|
||||
|
||||
Open a stream in binary mode by passing `"rb"` to avoid inconsistency between the file size and the number of characters due to automatic conversion of newline characters by the standard library.
|
||||
|
||||
If parsing fails, a `result` holding the error type `std::vector<error_info>` is returned.
|
||||
|
||||
If successful, a `result` holding a `basic_value` is returned.
|
||||
|
@ -44,11 +44,21 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
#### `std::filesystem::path`でファイルを指定する
|
||||
|
||||
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}})
|
||||
には、`std::filesystem::path`を渡すことも可能です。
|
||||
|
||||
当然ですが、`<filesystem>`がサポートされるC++17以降でなければ使用できません。
|
||||
|
||||
#### `std::istream`で入力ストリームを指定する
|
||||
|
||||
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}})
|
||||
には、`std::istream`を渡すことも可能です。
|
||||
|
||||
標準ライブラリが改行文字を自動変換することによるファイルサイズと文字数との不整合を避けるため、
|
||||
`std::ios::binary`を使ってバイナリモードで開いてください。
|
||||
|
||||
その際、ファイル名の情報がなくなるため、エラーメッセージ中では `"unknown file"` となります。
|
||||
|
||||
これを避けるため、 `std::istream` を取る場合は第二引数に `std::string` でファイル名を取ることもできます。
|
||||
@ -70,18 +80,14 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
#### `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*`を渡すことも可能です。
|
||||
|
||||
標準ライブラリによる改行文字の自動変換によるファイルサイズと文字数との不整合を避けるため、
|
||||
`fopen("example.toml", "rb")`のようにしてバイナリモードで開いてください。
|
||||
|
||||
この場合も、`std::istream`のときと同様に、第二引数に文字列でファイル名を与える必要があります。
|
||||
|
||||
`FILE*`を渡した場合、ファイルの読み込みに失敗した際には`errno`が報告されます。
|
||||
|
@ -54,6 +54,14 @@ target_link_libraries(main PRIVATE toml11::toml11)
|
||||
$ cmake -B ./build/ -DTOML11_PRECOMPILE=ON
|
||||
```
|
||||
|
||||
ライブラリをリンクする場合は、CMakeで
|
||||
|
||||
```cmake
|
||||
target_link_libraries(your_target PUBLIC toml11::toml11)
|
||||
```
|
||||
|
||||
とするか、ヘッダ内の関数の`inline`化を避けるためにコンパイラに`-DTOML11_COMPILE_SOURCES`を渡してください。
|
||||
|
||||
ただし、toml11は複数のC++バージョンに対応するため、`__cplusplus`の値などによって型を切り替えることがあります。
|
||||
そのため、ビルドした際のバージョンと使用時のバージョンが異なる場合、リンクに失敗する可能性があります。
|
||||
問題が生じた場合は`CMAKE_CXX_STANDARD`によって必要なバージョンを設定してコンパイルしてください。
|
||||
|
@ -17,23 +17,6 @@ type = "docs"
|
||||
|
||||
`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
|
||||
@ -90,6 +73,25 @@ parse(const std::filesystem::path& fpath,
|
||||
|
||||
パースに失敗した場合、`syntax_error`が送出されます。
|
||||
|
||||
### `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&`を受け取ってその内容をパースします。
|
||||
|
||||
標準ライブラリが改行文字を自動変換することによるファイルサイズと文字数との不整合を避けるため、
|
||||
`std::ios::binary`を使ってバイナリモードで開いてください。
|
||||
|
||||
ファイル名の情報は第三引数で受け取ります。ファイル名が渡されなかった場合、`"unknown file"`になります。
|
||||
|
||||
### `parse(FILE*, std::string filename, toml::spec)`
|
||||
|
||||
@ -106,6 +108,9 @@ parse(FILE* fp,
|
||||
|
||||
`FILE*`が指すファイルを読み込んでパースします。
|
||||
|
||||
標準ライブラリが改行文字を自動変換することによるファイルサイズと文字数との不整合を避けるため、
|
||||
`fopen`には`"rb"`などを渡してバイナリモードで開いてください。
|
||||
|
||||
ファイルの読み込みに失敗した場合、`errno`が含まれた`file_io_error`が送出されます。
|
||||
|
||||
パースに失敗した場合、`syntax_error`が送出されます。
|
||||
@ -167,28 +172,6 @@ parse_str(std::string content,
|
||||
|
||||
{{< /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
|
||||
@ -244,6 +227,30 @@ try_parse(const std::filesystem::path& fpath,
|
||||
|
||||
成功した場合、`basic_value`を持つ`result`が返されます。
|
||||
|
||||
### `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&`を受け取ってその内容をパースします。
|
||||
|
||||
標準ライブラリが改行文字を自動変換することによるファイルサイズと文字数との不整合を避けるため、
|
||||
`std::ios::binary`を使ってバイナリモードで開いてください。
|
||||
|
||||
ファイル名の情報は第二引数で受け取ります。ファイル名が渡されなかった場合、`"unknown file"`になります。
|
||||
|
||||
パースに失敗した場合、エラー型である`std::vector<error_info>`を持つ`result`が返されます。
|
||||
|
||||
成功した場合、`basic_value`を持つ`result`が返されます。
|
||||
|
||||
### `try_parse(FILE*, std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
@ -259,6 +266,9 @@ try_parse(FILE* fp,
|
||||
|
||||
`FILE*`を受け取って、そのファイルの内容をパースします。
|
||||
|
||||
標準ライブラリが改行文字を自動変換することによるファイルサイズと文字数との不整合を避けるため、
|
||||
`fopen`には`"rb"`などを渡してバイナリモードで開いてください。
|
||||
|
||||
パースに失敗した場合、エラー型である`std::vector<error_info>`を持つ`result`が返されます。
|
||||
|
||||
成功した場合、`basic_value`を持つ`result`が返されます。
|
||||
|
@ -41,6 +41,10 @@ struct error_info
|
||||
std::string suffix_; // hint or something like that
|
||||
};
|
||||
|
||||
// forward decl
|
||||
template<typename TypeConfig>
|
||||
class basic_value;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
inline error_info make_error_info_rec(error_info e)
|
||||
@ -53,6 +57,10 @@ inline error_info make_error_info_rec(error_info e, std::string s)
|
||||
return e;
|
||||
}
|
||||
|
||||
template<typename TC, typename ... Ts>
|
||||
error_info make_error_info_rec(error_info e,
|
||||
const basic_value<TC>& v, std::string msg, Ts&& ... tail);
|
||||
|
||||
template<typename ... Ts>
|
||||
error_info make_error_info_rec(error_info e,
|
||||
source_location loc, std::string msg, Ts&& ... tail)
|
||||
|
@ -3524,7 +3524,7 @@ try_parse(std::istream& is, std::string fname = "unknown file", spec s = spec::d
|
||||
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize));
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize), '\0');
|
||||
is.read(reinterpret_cast<char*>(letters.data()), fsize);
|
||||
|
||||
return detail::parse_impl<TC>(std::move(letters), std::move(fname), std::move(s));
|
||||
@ -3714,7 +3714,15 @@ try_parse(FILE* fp, std::string filename, spec s = spec::default_version())
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize));
|
||||
std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
const auto actual = std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
if(actual != static_cast<std::size_t>(fsize))
|
||||
{
|
||||
return err(std::vector<error_info>{error_info(
|
||||
std::string("File size changed: \"") + filename +
|
||||
std::string("\" make sure that FILE* is in binary mode "
|
||||
"to avoid LF <-> CRLF conversion"), {}
|
||||
)});
|
||||
}
|
||||
|
||||
return detail::parse_impl<TC>(std::move(letters), std::move(filename), std::move(s));
|
||||
}
|
||||
@ -3752,7 +3760,12 @@ parse(FILE* fp, std::string filename, spec s = spec::default_version())
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize));
|
||||
std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
const auto actual = std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
if(actual != static_cast<std::size_t>(fsize))
|
||||
{
|
||||
throw file_io_error(errno, "File size changed; make sure that "
|
||||
"FILE* is in binary mode to avoid LF <-> CRLF conversion", filename);
|
||||
}
|
||||
|
||||
auto res = detail::parse_impl<TC>(std::move(letters), std::move(filename), std::move(s));
|
||||
if(res.is_ok())
|
||||
|
@ -2102,12 +2102,16 @@ operator>=(const basic_value<TC>& lhs, const basic_value<TC>& rhs)
|
||||
}
|
||||
|
||||
// error_info helper
|
||||
namespace detail
|
||||
{
|
||||
template<typename TC, typename ... Ts>
|
||||
error_info make_error_info_rec(error_info e,
|
||||
const basic_value<TC>& v, std::string msg, Ts&& ... tail)
|
||||
{
|
||||
return make_error_info_rec(std::move(e), v.location(), std::move(msg), std::forward<Ts>(tail)...);
|
||||
}
|
||||
} // detail
|
||||
|
||||
template<typename TC, typename ... Ts>
|
||||
error_info make_error_info(
|
||||
std::string title, const basic_value<TC>& v, std::string msg, Ts&& ... tail)
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#define TOML11_VERSION_MAJOR 4
|
||||
#define TOML11_VERSION_MINOR 0
|
||||
#define TOML11_VERSION_PATCH 1
|
||||
#define TOML11_VERSION_PATCH 2
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error "__cplusplus is not defined"
|
||||
|
@ -52,8 +52,7 @@ struct local_time_format_info;
|
||||
struct array_format_info;
|
||||
struct table_format_info;
|
||||
|
||||
template<typename Key, typename Val, typename Cmp = std::equal_to<Key>,
|
||||
typename Allocator = std::allocator<std::pair<Key, Val>>>
|
||||
template<typename Key, typename Val, typename Cmp, typename Allocator>
|
||||
class ordered_map;
|
||||
|
||||
struct syntax_error;
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#define TOML11_VERSION_MAJOR 4
|
||||
#define TOML11_VERSION_MINOR 0
|
||||
#define TOML11_VERSION_PATCH 1
|
||||
#define TOML11_VERSION_PATCH 2
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error "__cplusplus is not defined"
|
||||
@ -3584,7 +3584,7 @@ struct has_specialized_into_impl
|
||||
template<typename T>
|
||||
static std::false_type check(...);
|
||||
template<typename T, std::size_t S = sizeof(::toml::into<T>)>
|
||||
static std::true_type check(::toml::from<T>*);
|
||||
static std::true_type check(::toml::into<T>*);
|
||||
};
|
||||
|
||||
|
||||
@ -5447,6 +5447,10 @@ struct error_info
|
||||
std::string suffix_; // hint or something like that
|
||||
};
|
||||
|
||||
// forward decl
|
||||
template<typename TypeConfig>
|
||||
class basic_value;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
inline error_info make_error_info_rec(error_info e)
|
||||
@ -5459,6 +5463,10 @@ inline error_info make_error_info_rec(error_info e, std::string s)
|
||||
return e;
|
||||
}
|
||||
|
||||
template<typename TC, typename ... Ts>
|
||||
error_info make_error_info_rec(error_info e,
|
||||
const basic_value<TC>& v, std::string msg, Ts&& ... tail);
|
||||
|
||||
template<typename ... Ts>
|
||||
error_info make_error_info_rec(error_info e,
|
||||
source_location loc, std::string msg, Ts&& ... tail)
|
||||
@ -7588,12 +7596,16 @@ operator>=(const basic_value<TC>& lhs, const basic_value<TC>& rhs)
|
||||
}
|
||||
|
||||
// error_info helper
|
||||
namespace detail
|
||||
{
|
||||
template<typename TC, typename ... Ts>
|
||||
error_info make_error_info_rec(error_info e,
|
||||
const basic_value<TC>& v, std::string msg, Ts&& ... tail)
|
||||
{
|
||||
return make_error_info_rec(std::move(e), v.location(), std::move(msg), std::forward<Ts>(tail)...);
|
||||
}
|
||||
} // detail
|
||||
|
||||
template<typename TC, typename ... Ts>
|
||||
error_info make_error_info(
|
||||
std::string title, const basic_value<TC>& v, std::string msg, Ts&& ... tail)
|
||||
@ -15063,7 +15075,7 @@ try_parse(std::istream& is, std::string fname = "unknown file", spec s = spec::d
|
||||
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize));
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize), '\0');
|
||||
is.read(reinterpret_cast<char*>(letters.data()), fsize);
|
||||
|
||||
return detail::parse_impl<TC>(std::move(letters), std::move(fname), std::move(s));
|
||||
@ -15253,7 +15265,15 @@ try_parse(FILE* fp, std::string filename, spec s = spec::default_version())
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize));
|
||||
std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
const auto actual = std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
if(actual != static_cast<std::size_t>(fsize))
|
||||
{
|
||||
return err(std::vector<error_info>{error_info(
|
||||
std::string("File size changed: \"") + filename +
|
||||
std::string("\" make sure that FILE* is in binary mode "
|
||||
"to avoid LF <-> CRLF conversion"), {}
|
||||
)});
|
||||
}
|
||||
|
||||
return detail::parse_impl<TC>(std::move(letters), std::move(filename), std::move(s));
|
||||
}
|
||||
@ -15291,7 +15311,12 @@ parse(FILE* fp, std::string filename, spec s = spec::default_version())
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize));
|
||||
std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
const auto actual = std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
if(actual != static_cast<std::size_t>(fsize))
|
||||
{
|
||||
throw file_io_error(errno, "File size changed; make sure that "
|
||||
"FILE* is in binary mode to avoid LF <-> CRLF conversion", filename);
|
||||
}
|
||||
|
||||
auto res = detail::parse_impl<TC>(std::move(letters), std::move(filename), std::move(s));
|
||||
if(res.is_ok())
|
||||
|
@ -1,6 +1,7 @@
|
||||
set(TOML11_TEST_NAMES
|
||||
test_comments
|
||||
test_datetime
|
||||
test_error_message
|
||||
test_find
|
||||
test_try_find
|
||||
test_find_or
|
||||
@ -24,6 +25,7 @@ set(TOML11_TEST_NAMES
|
||||
test_parse_table
|
||||
test_result
|
||||
test_scanner
|
||||
test_serialize
|
||||
test_syntax_boolean
|
||||
test_syntax_integer
|
||||
test_syntax_floating
|
||||
|
79
tests/test_error_message.cpp
Normal file
79
tests/test_error_message.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
||||
#include "doctest.h"
|
||||
|
||||
#include <toml.hpp>
|
||||
|
||||
TEST_CASE("testing custom error message using source_location")
|
||||
{
|
||||
const toml::value root = toml::parse_str(R"(
|
||||
range = [0, 42]
|
||||
val = 54
|
||||
)");
|
||||
|
||||
const auto& lower = root.at("range").at(0);
|
||||
const auto& upper = root.at("range").at(1);
|
||||
const auto& val = root.at("val");
|
||||
|
||||
const auto err = toml::make_error_info("val not in range",
|
||||
lower.location(), "lower limit is defined here",
|
||||
upper.location(), "upper limit is defined here",
|
||||
val.location(), "this is not in the range",
|
||||
"Hint: upper limit is inclusive"
|
||||
);
|
||||
|
||||
CHECK_EQ(err.title(), "val not in range");
|
||||
CHECK_EQ(err.locations().size(), 3);
|
||||
CHECK_EQ(err.locations().at(0).second, "lower limit is defined here");
|
||||
CHECK_EQ(err.locations().at(1).second, "upper limit is defined here");
|
||||
CHECK_EQ(err.locations().at(2).second, "this is not in the range" );
|
||||
}
|
||||
|
||||
TEST_CASE("testing custom error message using value")
|
||||
{
|
||||
const toml::value root = toml::parse_str(R"(
|
||||
range = [0, 42]
|
||||
val = 54
|
||||
)");
|
||||
|
||||
const auto& lower = root.at("range").at(0);
|
||||
const auto& upper = root.at("range").at(1);
|
||||
const auto& val = root.at("val");
|
||||
|
||||
const auto err = toml::make_error_info("val not in range",
|
||||
lower, "lower limit is defined here",
|
||||
upper, "upper limit is defined here",
|
||||
val, "this is not in the range",
|
||||
"Hint: upper limit is inclusive"
|
||||
);
|
||||
|
||||
CHECK_EQ(err.title(), "val not in range");
|
||||
CHECK_EQ(err.locations().size(), 3);
|
||||
CHECK_EQ(err.locations().at(0).second, "lower limit is defined here");
|
||||
CHECK_EQ(err.locations().at(1).second, "upper limit is defined here");
|
||||
CHECK_EQ(err.locations().at(2).second, "this is not in the range" );
|
||||
}
|
||||
|
||||
TEST_CASE("testing custom error message using source_location and value")
|
||||
{
|
||||
const toml::value root = toml::parse_str(R"(
|
||||
range = [0, 42]
|
||||
val = 54
|
||||
)");
|
||||
|
||||
const auto& lower = root.at("range").at(0);
|
||||
const auto& upper = root.at("range").at(1);
|
||||
const auto& val = root.at("val");
|
||||
|
||||
const auto err = toml::make_error_info("val not in range",
|
||||
lower, "lower limit is defined here",
|
||||
upper, "upper limit is defined here",
|
||||
val.location(), "this is not in the range",
|
||||
"Hint: upper limit is inclusive"
|
||||
);
|
||||
|
||||
CHECK_EQ(err.title(), "val not in range");
|
||||
CHECK_EQ(err.locations().size(), 3);
|
||||
CHECK_EQ(err.locations().at(0).second, "lower limit is defined here");
|
||||
CHECK_EQ(err.locations().at(1).second, "upper limit is defined here");
|
||||
CHECK_EQ(err.locations().at(2).second, "this is not in the range" );
|
||||
}
|
150
tests/test_serialize.cpp
Normal file
150
tests/test_serialize.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
||||
#include "doctest.h"
|
||||
|
||||
#include <toml.hpp>
|
||||
|
||||
#include <clocale>
|
||||
|
||||
TEST_CASE("testing serialization")
|
||||
{
|
||||
using namespace toml::literals::toml_literals;
|
||||
|
||||
const auto spec_example = R"(# This is a TOML document
|
||||
|
||||
title = "TOML Example"
|
||||
|
||||
[owner]
|
||||
name = "Tom Preston-Werner"
|
||||
dob = 1979-05-27T07:32:00-08:00
|
||||
|
||||
[database]
|
||||
enabled = true
|
||||
ports = [ 8000, 8001, 8002 ]
|
||||
data = [ ["delta", "phi"], [3.14] ]
|
||||
temp_targets = { cpu = 79.5, case = 72.0 }
|
||||
|
||||
[servers]
|
||||
|
||||
[servers.alpha]
|
||||
ip = "10.0.0.1"
|
||||
role = "frontend"
|
||||
|
||||
[servers.beta]
|
||||
ip = "10.0.0.2"
|
||||
role = "backend")"_toml;
|
||||
|
||||
// format and parse
|
||||
const auto v = toml::parse_str(toml::format(spec_example));
|
||||
|
||||
CHECK_EQ(v, spec_example);
|
||||
}
|
||||
|
||||
TEST_CASE("testing serialization with complicated keys")
|
||||
{
|
||||
using namespace toml::literals::toml_literals;
|
||||
|
||||
const auto spec_example = R"(
|
||||
[keys]
|
||||
|
||||
key = "value"
|
||||
bare_key = "value"
|
||||
bare-key = "value"
|
||||
1234 = "value"
|
||||
|
||||
"127.0.0.1" = "value"
|
||||
"character encoding" = "value"
|
||||
"ʎǝʞ" = "value"
|
||||
'key2' = "value"
|
||||
'quoted "value"' = "value"
|
||||
|
||||
"" = "blank"
|
||||
|
||||
fruits.apple.skin = "thin"
|
||||
fruits.apple.color = "red"
|
||||
|
||||
fruits.orange.skin = "thick"
|
||||
fruits.orange.color = "orange"
|
||||
|
||||
site."google.com" = true
|
||||
3.14159 = "pi"
|
||||
)"_toml;
|
||||
|
||||
// format and parse
|
||||
const auto v = toml::parse_str(toml::format(spec_example));
|
||||
|
||||
CHECK_EQ(v, spec_example);
|
||||
}
|
||||
|
||||
TEST_CASE("testing serialization with array of tables")
|
||||
{
|
||||
using namespace toml::literals::toml_literals;
|
||||
|
||||
const auto spec_example = R"(
|
||||
points = [ { x = 1, y = 2, z = 3 },
|
||||
{ x = 7, y = 8, z = 9 },
|
||||
{ x = 2, y = 4, z = 8 } ]
|
||||
|
||||
[[products]]
|
||||
name = "Hammer"
|
||||
sku = 738594937
|
||||
|
||||
[[products]] # empty table within the array
|
||||
|
||||
[[products]]
|
||||
name = "Nail"
|
||||
sku = 284758393
|
||||
|
||||
color = "gray"
|
||||
|
||||
[[fruits]]
|
||||
name = "apple"
|
||||
|
||||
[fruits.physical] # subtable
|
||||
color = "red"
|
||||
shape = "round"
|
||||
|
||||
[[fruits.varieties]] # nested array of tables
|
||||
name = "red delicious"
|
||||
|
||||
[[fruits.varieties]]
|
||||
name = "granny smith"
|
||||
|
||||
[[fruits]]
|
||||
name = "banana"
|
||||
|
||||
[[fruits.varieties]]
|
||||
name = "plantain"
|
||||
)"_toml;
|
||||
|
||||
// format and parse
|
||||
const auto v = toml::parse_str(toml::format(spec_example));
|
||||
|
||||
CHECK_EQ(v, spec_example);
|
||||
}
|
||||
|
||||
TEST_CASE("testing serialization with locale")
|
||||
{
|
||||
std::string current_locale = std::setlocale(LC_ALL, nullptr);
|
||||
|
||||
// fr_FR is a one of locales that uses `,` as a decimal separator.
|
||||
if(const char* try_hyphen = std::setlocale(LC_ALL, "fr_FR.UTF-8"))
|
||||
{
|
||||
current_locale = std::string(try_hyphen);
|
||||
}
|
||||
else if(const char* try_nohyphen = std::setlocale(LC_ALL, "fr_FR.utf8"))
|
||||
{
|
||||
current_locale = std::string(try_nohyphen);
|
||||
}
|
||||
|
||||
MESSAGE("current_locale = ", current_locale);
|
||||
|
||||
const auto v1 = toml::parse_str(R"(
|
||||
pi = 3.1415_9265
|
||||
large_int = 123_456_789
|
||||
)");
|
||||
const auto v2 = toml::parse_str(toml::format(v1));
|
||||
|
||||
// actually, it checkl if v1 is serialized correctly under FR locale
|
||||
// where 3.1415 -> 3,1415
|
||||
CHECK_EQ(v1, v2);
|
||||
}
|
Loading…
Reference in New Issue
Block a user