Compare commits

...

10 Commits

Author SHA1 Message Date
ToruNiina
c4aecc8e4b chore: update README badges 2019-02-13 22:36:29 +09:00
Toru Niina
60c81d06a0 Merge pull request #25 from ToruNiina/hotfix
fix: open file as binary-mode #16
2019-02-13 21:14:15 +09:00
ToruNiina
46569da231 fix: avoid auto-conversion while making test case 2019-02-13 19:51:54 +09:00
ToruNiina
5e20a8ff16 fix: add scope to the test case to flush 2019-02-13 19:26:52 +09:00
ToruNiina
dd9319245e fix: open file as binary-mode #16
to avoid inconsistency between file size (obtained by tellg) and the
size of the actual contents that would be read later
2019-02-13 19:18:09 +09:00
ToruNiina
53f6b8268b fix: compare offset_datetime correctly 2019-02-13 13:34:26 +09:00
ToruNiina
32dcc35918 move return_type_of_t from result to traits 2019-02-13 13:34:03 +09:00
ToruNiina
8c3854b28b update README 2019-01-31 15:37:25 +09:00
Toru Niina
75af9c79df Merge pull request #22 from xaxousis/master
Fix multiple definition error
2019-01-31 01:34:33 +09:00
Quentin Khan
1dfe32acd8 Fix multiple definition error 2019-01-30 17:06:23 +01:00
7 changed files with 96 additions and 47 deletions

View File

@@ -3,10 +3,11 @@ toml11
[![Build Status](https://travis-ci.org/ToruNiina/toml11.svg?branch=master)](https://travis-ci.org/ToruNiina/toml11) [![Build Status](https://travis-ci.org/ToruNiina/toml11.svg?branch=master)](https://travis-ci.org/ToruNiina/toml11)
[![Build status](https://ci.appveyor.com/api/projects/status/m2n08a926asvg5mg?svg=true)](https://ci.appveyor.com/project/ToruNiina/toml11) [![Build status](https://ci.appveyor.com/api/projects/status/m2n08a926asvg5mg?svg=true)](https://ci.appveyor.com/project/ToruNiina/toml11)
[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE) [![Version](https://img.shields.io/github/release/ToruNiina/toml11.svg?style=flat)](https://github.com/ToruNiina/toml11/releases)
[![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) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1209136.svg)](https://doi.org/10.5281/zenodo.1209136)
c++11 header-only toml parser depending only on c++ standard library. C++11 header-only toml parser depending only on C++ standard library.
compatible to the latest version of [TOML v0.5.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md) after version 2.0.0. compatible to the latest version of [TOML v0.5.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md) after version 2.0.0.
@@ -42,8 +43,14 @@ In the case of file open error, it will throw `std::runtime_error`.
You can also pass a `stream` to the `toml::parse` function after checking the status. You can also pass a `stream` to the `toml::parse` function after checking the status.
Note that on __Windows OS__, stream that is opened as text-mode automatically converts
CRLF ("\r\n") into LF ("\n") and this leads inconsistency between file size and
the contents that would be read. This causes weird error. To use a file stream
with `toml::parse`, don't forget to pass binary mode flag when you open the
stream.
```cpp ```cpp
std::ifstream ifs("sample.toml"); std::ifstream ifs("sample.toml", std::ios_base::binary);
assert(ifs.good()); assert(ifs.good());
const auto data = toml::parse(ifs /*, "filename" (optional)*/); const auto data = toml::parse(ifs /*, "filename" (optional)*/);
``` ```
@@ -485,6 +492,8 @@ I thank the contributor for providing great feature to this repository.
- Guillaume Fraux (@Luthaf) - Guillaume Fraux (@Luthaf)
- Windows support and CI on Appvayor - Windows support and CI on Appvayor
- Intel Compiler support - Intel Compiler support
- Quentin Khan (@xaxousis)
- Found & Fixed a bug around ODR
## Licensing terms ## Licensing terms

View File

@@ -213,6 +213,22 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM)
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
} }
{
const std::string table(
"\xEF\xBB\xBF" // BOM
"key = \"value\"\n"
"[table]\n"
"key = \"value\"\n"
);
{
std::ofstream ofs("tmp.toml");
ofs << table;
}
const auto data = toml::parse("tmp.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
}
{ {
const std::string table( const std::string table(
"\xEF\xBB\xBF" // BOM "\xEF\xBB\xBF" // BOM
@@ -223,6 +239,25 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM)
std::istringstream iss(table); std::istringstream iss(table);
const auto data = toml::parse(iss, "test_file_with_BOM_CRLF.toml"); const auto data = toml::parse(iss, "test_file_with_BOM_CRLF.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
}
{
const std::string table(
"\xEF\xBB\xBF" // BOM
"key = \"value\"\r\n"
"[table]\r\n"
"key = \"value\"\r\n"
);
{
// with text-mode, "\n" is converted to "\r\n" and the resulting
// value will be "\r\r\n". To avoid the additional "\r", use binary
// mode.
std::ofstream ofs("tmp.toml", std::ios_base::binary);
ofs.write(table.data(), table.size());
}
const auto data = toml::parse("tmp.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
} }

View File

@@ -1517,7 +1517,7 @@ inline table parse(std::istream& is, std::string fname = "unknown file")
inline table parse(const std::string& fname) inline table parse(const std::string& fname)
{ {
std::ifstream ifs(fname.c_str()); std::ifstream ifs(fname.c_str(), std::ios_base::binary);
if(!ifs.good()) if(!ifs.good())
{ {
throw std::runtime_error("toml::parse: file open error -> " + fname); throw std::runtime_error("toml::parse: file open error -> " + fname);

View File

@@ -2,6 +2,7 @@
// Distributed under the MIT License. // Distributed under the MIT License.
#ifndef TOML11_RESULT_H #ifndef TOML11_RESULT_H
#define TOML11_RESULT_H #define TOML11_RESULT_H
#include "traits.hpp"
#include <type_traits> #include <type_traits>
#include <stdexcept> #include <stdexcept>
#include <utility> #include <utility>
@@ -13,19 +14,6 @@
namespace toml namespace toml
{ {
#if __cplusplus >= 201703L
template<typename F, typename ... Args>
using return_type_of_t = std::invoke_result_t<F, Args...>;
#else
// result_of is deprecated after C++17
template<typename F, typename ... Args>
using return_type_of_t = typename std::result_of<F(Args...)>::type;
#endif
template<typename T> template<typename T>
struct success struct success
{ {
@@ -441,21 +429,21 @@ struct result
// F: T -> U // F: T -> U
// retval: result<U, E> // retval: result<U, E>
template<typename F> template<typename F>
result<return_type_of_t<F, value_type&>, error_type> result<detail::return_type_of_t<F, value_type&>, error_type>
map(F&& f) & map(F&& f) &
{ {
if(this->is_ok()){return ok(f(this->as_ok()));} if(this->is_ok()){return ok(f(this->as_ok()));}
return err(this->as_err()); return err(this->as_err());
} }
template<typename F> template<typename F>
result<return_type_of_t<F, value_type const&>, error_type> result<detail::return_type_of_t<F, value_type const&>, error_type>
map(F&& f) const& map(F&& f) const&
{ {
if(this->is_ok()){return ok(f(this->as_ok()));} if(this->is_ok()){return ok(f(this->as_ok()));}
return err(this->as_err()); return err(this->as_err());
} }
template<typename F> template<typename F>
result<return_type_of_t<F, value_type &&>, error_type> result<detail::return_type_of_t<F, value_type &&>, error_type>
map(F&& f) && map(F&& f) &&
{ {
if(this->is_ok()){return ok(f(std::move(this->as_ok())));} if(this->is_ok()){return ok(f(std::move(this->as_ok())));}
@@ -466,21 +454,21 @@ struct result
// F: E -> F // F: E -> F
// retval: result<T, F> // retval: result<T, F>
template<typename F> template<typename F>
result<value_type, return_type_of_t<F, error_type&>> result<value_type, detail::return_type_of_t<F, error_type&>>
map_err(F&& f) & map_err(F&& f) &
{ {
if(this->is_err()){return err(f(this->as_err()));} if(this->is_err()){return err(f(this->as_err()));}
return ok(this->as_ok()); return ok(this->as_ok());
} }
template<typename F> template<typename F>
result<value_type, return_type_of_t<F, error_type const&>> result<value_type, detail::return_type_of_t<F, error_type const&>>
map_err(F&& f) const& map_err(F&& f) const&
{ {
if(this->is_err()){return err(f(this->as_err()));} if(this->is_err()){return err(f(this->as_err()));}
return ok(this->as_ok()); return ok(this->as_ok());
} }
template<typename F> template<typename F>
result<value_type, return_type_of_t<F, error_type&&>> result<value_type, detail::return_type_of_t<F, error_type&&>>
map_err(F&& f) && map_err(F&& f) &&
{ {
if(this->is_err()){return err(f(std::move(this->as_err())));} if(this->is_err()){return err(f(std::move(this->as_err())));}
@@ -491,21 +479,21 @@ struct result
// F: T -> U // F: T -> U
// retval: U // retval: U
template<typename F, typename U> template<typename F, typename U>
return_type_of_t<F, value_type&> detail::return_type_of_t<F, value_type&>
map_or_else(F&& f, U&& opt) & map_or_else(F&& f, U&& opt) &
{ {
if(this->is_err()){return std::forward<U>(opt);} if(this->is_err()){return std::forward<U>(opt);}
return f(this->as_ok()); return f(this->as_ok());
} }
template<typename F, typename U> template<typename F, typename U>
return_type_of_t<F, value_type const&> detail::return_type_of_t<F, value_type const&>
map_or_else(F&& f, U&& opt) const& map_or_else(F&& f, U&& opt) const&
{ {
if(this->is_err()){return std::forward<U>(opt);} if(this->is_err()){return std::forward<U>(opt);}
return f(this->as_ok()); return f(this->as_ok());
} }
template<typename F, typename U> template<typename F, typename U>
return_type_of_t<F, value_type&&> detail::return_type_of_t<F, value_type&&>
map_or_else(F&& f, U&& opt) && map_or_else(F&& f, U&& opt) &&
{ {
if(this->is_err()){return std::forward<U>(opt);} if(this->is_err()){return std::forward<U>(opt);}
@@ -516,21 +504,21 @@ struct result
// F: E -> U // F: E -> U
// retval: U // retval: U
template<typename F, typename U> template<typename F, typename U>
return_type_of_t<F, error_type&> detail::return_type_of_t<F, error_type&>
map_err_or_else(F&& f, U&& opt) & map_err_or_else(F&& f, U&& opt) &
{ {
if(this->is_ok()){return std::forward<U>(opt);} if(this->is_ok()){return std::forward<U>(opt);}
return f(this->as_err()); return f(this->as_err());
} }
template<typename F, typename U> template<typename F, typename U>
return_type_of_t<F, error_type const&> detail::return_type_of_t<F, error_type const&>
map_err_or_else(F&& f, U&& opt) const& map_err_or_else(F&& f, U&& opt) const&
{ {
if(this->is_ok()){return std::forward<U>(opt);} if(this->is_ok()){return std::forward<U>(opt);}
return f(this->as_err()); return f(this->as_err());
} }
template<typename F, typename U> template<typename F, typename U>
return_type_of_t<F, error_type&&> detail::return_type_of_t<F, error_type&&>
map_err_or_else(F&& f, U&& opt) && map_err_or_else(F&& f, U&& opt) &&
{ {
if(this->is_ok()){return std::forward<U>(opt);} if(this->is_ok()){return std::forward<U>(opt);}
@@ -542,21 +530,21 @@ struct result
// toml::err(error_type) should be convertible to U. // toml::err(error_type) should be convertible to U.
// normally, type U is another result<S, F> and E is convertible to F // normally, type U is another result<S, F> and E is convertible to F
template<typename F> template<typename F>
return_type_of_t<F, value_type&> detail::return_type_of_t<F, value_type&>
and_then(F&& f) & and_then(F&& f) &
{ {
if(this->is_ok()){return f(this->as_ok());} if(this->is_ok()){return f(this->as_ok());}
return err(this->as_err()); return err(this->as_err());
} }
template<typename F> template<typename F>
return_type_of_t<F, value_type const&> detail::return_type_of_t<F, value_type const&>
and_then(F&& f) const& and_then(F&& f) const&
{ {
if(this->is_ok()){return f(this->as_ok());} if(this->is_ok()){return f(this->as_ok());}
return err(this->as_err()); return err(this->as_err());
} }
template<typename F> template<typename F>
return_type_of_t<F, value_type&&> detail::return_type_of_t<F, value_type&&>
and_then(F&& f) && and_then(F&& f) &&
{ {
if(this->is_ok()){return f(std::move(this->as_ok()));} if(this->is_ok()){return f(std::move(this->as_ok()));}
@@ -568,21 +556,21 @@ struct result
// toml::ok(value_type) should be convertible to U. // toml::ok(value_type) should be convertible to U.
// normally, type U is another result<S, F> and T is convertible to S // normally, type U is another result<S, F> and T is convertible to S
template<typename F> template<typename F>
return_type_of_t<F, error_type&> detail::return_type_of_t<F, error_type&>
or_else(F&& f) & or_else(F&& f) &
{ {
if(this->is_err()){return f(this->as_err());} if(this->is_err()){return f(this->as_err());}
return ok(this->as_ok()); return ok(this->as_ok());
} }
template<typename F> template<typename F>
return_type_of_t<F, error_type const&> detail::return_type_of_t<F, error_type const&>
or_else(F&& f) const& or_else(F&& f) const&
{ {
if(this->is_err()){return f(this->as_err());} if(this->is_err()){return f(this->as_err());}
return ok(this->as_ok()); return ok(this->as_ok());
} }
template<typename F> template<typename F>
return_type_of_t<F, error_type&&> detail::return_type_of_t<F, error_type&&>
or_else(F&& f) && or_else(F&& f) &&
{ {
if(this->is_err()){return f(std::move(this->as_err()));} if(this->is_err()){return f(std::move(this->as_err()));}

View File

@@ -15,6 +15,9 @@ namespace detail
template<typename T> template<typename T>
using unwrap_t = typename std::decay<T>::type; using unwrap_t = typename std::decay<T>::type;
// ---------------------------------------------------------------------------
// check whether type T is a kind of container/map class
struct has_iterator_impl struct has_iterator_impl
{ {
template<typename T> static std::true_type check(typename T::iterator*); template<typename T> static std::true_type check(typename T::iterator*);
@@ -63,6 +66,9 @@ struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){}
#undef decltype(...) #undef decltype(...)
#endif #endif
// ---------------------------------------------------------------------------
// C++17 and/or/not
template<typename ...> struct conjunction : std::true_type{}; template<typename ...> struct conjunction : std::true_type{};
template<typename T> struct conjunction<T> : T{}; template<typename T> struct conjunction<T> : T{};
template<typename T, typename ... Ts> template<typename T, typename ... Ts>
@@ -80,6 +86,9 @@ struct disjunction<T, Ts...> :
template<typename T> template<typename T>
struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{}; struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};
// ---------------------------------------------------------------------------
// normal type checker
template<typename T> struct is_std_pair : std::false_type{}; template<typename T> struct is_std_pair : std::false_type{};
template<typename T1, typename T2> template<typename T1, typename T2>
struct is_std_pair<std::pair<T1, T2>> : std::true_type{}; struct is_std_pair<std::pair<T1, T2>> : std::true_type{};
@@ -92,7 +101,9 @@ template<typename T> struct is_chrono_duration: std::false_type{};
template<typename Rep, typename Period> template<typename Rep, typename Period>
struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{}; struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};
// to use toml::get<std::tuple<T1, T2, ...>> in C++11 // ---------------------------------------------------------------------------
// C++14 index_sequence
template<std::size_t ... Ns> struct index_sequence{}; template<std::size_t ... Ns> struct index_sequence{};
template<typename IS, std::size_t N> struct push_back_index_sequence{}; template<typename IS, std::size_t N> struct push_back_index_sequence{};
@@ -116,6 +127,21 @@ struct index_sequence_maker<0>
template<std::size_t N> template<std::size_t N>
using make_index_sequence = typename index_sequence_maker<N-1>::type; using make_index_sequence = typename index_sequence_maker<N-1>::type;
// ---------------------------------------------------------------------------
// return_type_of_t
#if __cplusplus >= 201703L
template<typename F, typename ... Args>
using return_type_of_t = std::invoke_result_t<F, Args...>;
#else
// result_of is deprecated after C++17
template<typename F, typename ... Args>
using return_type_of_t = typename std::result_of<F(Args...)>::type;
#endif
}// detail }// detail
}//toml }//toml
#endif // TOML_TRAITS #endif // TOML_TRAITS

View File

@@ -137,17 +137,6 @@ template<> struct toml_value_t<LocalDate >{static constexpr value_t value =
template<> struct toml_value_t<LocalTime >{static constexpr value_t value = value_t::LocalTime ;}; template<> struct toml_value_t<LocalTime >{static constexpr value_t value = value_t::LocalTime ;};
template<> struct toml_value_t<Array >{static constexpr value_t value = value_t::Array ;}; template<> struct toml_value_t<Array >{static constexpr value_t value = value_t::Array ;};
template<> struct toml_value_t<Table >{static constexpr value_t value = value_t::Table ;}; template<> struct toml_value_t<Table >{static constexpr value_t value = value_t::Table ;};
template<typename T> constexpr value_t toml_value_t<T>::value;
constexpr value_t toml_value_t<Boolean >::value;
constexpr value_t toml_value_t<Integer >::value;
constexpr value_t toml_value_t<Float >::value;
constexpr value_t toml_value_t<String >::value;
constexpr value_t toml_value_t<OffsetDatetime>::value;
constexpr value_t toml_value_t<LocalDatetime >::value;
constexpr value_t toml_value_t<LocalDate >::value;
constexpr value_t toml_value_t<LocalTime >::value;
constexpr value_t toml_value_t<Array >::value;
constexpr value_t toml_value_t<Table >::value;
template<typename T> template<typename T>
struct is_exact_toml_type : disjunction< struct is_exact_toml_type : disjunction<

View File

@@ -767,6 +767,8 @@ inline bool operator<(const toml::value& lhs, const toml::value& rhs)
return lhs.cast<value_t::Float >() < rhs.cast<value_t::Float >(); return lhs.cast<value_t::Float >() < rhs.cast<value_t::Float >();
case value_t::String : case value_t::String :
return lhs.cast<value_t::String >() < rhs.cast<value_t::String >(); return lhs.cast<value_t::String >() < rhs.cast<value_t::String >();
case value_t::OffsetDatetime:
return lhs.cast<value_t::OffsetDatetime>() < rhs.cast<value_t::OffsetDatetime>();
case value_t::LocalDatetime: case value_t::LocalDatetime:
return lhs.cast<value_t::LocalDatetime>() < rhs.cast<value_t::LocalDatetime>(); return lhs.cast<value_t::LocalDatetime>() < rhs.cast<value_t::LocalDatetime>();
case value_t::LocalDate: case value_t::LocalDate: