diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7107ae6..ff227d2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -13,14 +13,14 @@ If you wish to submit a PR, please be aware that:
others, add an include directive to `include/toml++/toml.h`
3. Run `python/generate_single_header.py`
-### Building and testing
+### Building and running the tests
Testing is done using [Catch2], included in the respository as a submodule under `extern/Catch2`.
The first time you want to begin testing you'll need to ensure submodules have been fetched:
```bash
git submodule update --init --recursive extern/Catch2
```
-#### Windows
+#### Testing on Windows with Visual Studio
Install [Visual Studio 2019] and [Test Adapter for Catch2], then open `vs/toml++.sln` and build the
projects in the `tests` solution folder. Visual Studio's Test Explorer should pick these up and
@@ -29,7 +29,7 @@ allow you to run the tests directly.
If test discovery fails you can usually fix it by clicking enabling
`Auto Detect runsettings Files` (settings gear icon > `Configure Run Settings`).
-#### Linux
+#### Testing on Linux (and WSL)
Install [meson] and [ninja] if necessary, then test with both gcc and clang:
```bash
CXX=g++ meson build-gcc
diff --git a/README.md b/README.md
index 727eedd..dc51540 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,7 @@
- Works with or without exceptions
- Doesn't require RTTI
- First-class support for serializing to JSON
+ - Tested on Clang and GCC and MSVC (VS2019)
diff --git a/docs/Doxyfile-mcss b/docs/Doxyfile-mcss
index a2b25d9..485e011 100644
--- a/docs/Doxyfile-mcss
+++ b/docs/Doxyfile-mcss
@@ -17,3 +17,4 @@ HTML_EXTRA_FILES = tomlplusplus.js \
##! Report an issue \
##!
Documentation generated using m.css
##! M_HTML_HEADER =
+##! M_FAVICON = favicon.ico
diff --git a/docs/favicon.ico b/docs/favicon.ico
new file mode 100644
index 0000000..518213d
Binary files /dev/null and b/docs/favicon.ico differ
diff --git a/examples/parse_file.cpp b/examples/parse_file.cpp
index f288241..67206f2 100644
--- a/examples/parse_file.cpp
+++ b/examples/parse_file.cpp
@@ -27,12 +27,7 @@ int main(int argc, char** argv)
}
catch (const toml::parse_error& err)
{
- std::cerr
- << "Error parsing file '"sv << *err.source().path
- << "':\n"sv << err.description()
- << "\n ("sv << err.source().begin << ")"sv
- << std::endl;
-
+ std::cerr << "Error parsing file:\n"sv << err << std::endl;
return 1;
}
return 0;
diff --git a/examples/toml_to_json_transcoder.cpp b/examples/toml_to_json_transcoder.cpp
index 6111b5a..5b460f2 100644
--- a/examples/toml_to_json_transcoder.cpp
+++ b/examples/toml_to_json_transcoder.cpp
@@ -29,13 +29,9 @@ int main(int argc, char** argv)
const auto table = toml::parse(file, std::move(path));
std::cout << toml::json_formatter{ table } << std::endl;
}
- catch (const toml::parse_error & err)
+ catch (const toml::parse_error& err)
{
- std::cerr
- << "Error parsing file '"sv << *err.source().path
- << "':\n"sv << err.description()
- << "\n ("sv << err.source().begin << ")"sv
- << std::endl;
+ std::cerr << "Error parsing file:\n"sv << err << std::endl;
return 1;
}
@@ -51,10 +47,7 @@ int main(int argc, char** argv)
}
catch (const toml::parse_error& err)
{
- std::cerr
- << "Error parsing stdin:\n"sv << err.description()
- << "\n ("sv << err.source().begin << ")"sv
- << std::endl;
+ std::cerr << "Error parsing stdin:\n"sv << err << std::endl;
return 1;
}
diff --git a/include/toml++/toml.h b/include/toml++/toml.h
index ae64f80..325a9d0 100644
--- a/include/toml++/toml.h
+++ b/include/toml++/toml.h
@@ -78,7 +78,8 @@
/// - Proper UTF-8 handling (incl. BOM)
/// - Works with or without exceptions
/// - Doesn't require RTTI
-/// - First-class support for serializing to JSON
+/// - First-class support for serializing to JSON
+/// - Tested on Clang and GCC and MSVC (VS2019)
///
///////////////////////////////////////////////////////////////////////
///
@@ -88,14 +89,15 @@
/// There's some minor configuration you can do to customize some basic library functionality, but that's totally
/// optional. See the [README](https://github.com/marzer/tomlplusplus/blob/master/README.md) for more info.
///
-///
-/// On Linkers and the One-Definition-Rule
-/// Header-only libraries are great for minimal setup, but can cause ODR violations and complex linker errors
+/// \remark
+/// \parblock
+/// Header-only libraries are great for minimal setup, but can cause ODR violations and complex linker errors
/// in situations where multiple modules include them separately, each with different versions, configuration options,
-/// exception handling modes, et cetera.
-/// `toml++` attempts to combat this problem by nesting everything inside an additional inline namespace that
-/// changes according to the library's major version and the compiler's exception-handling mode.
-///
+/// exception handling modes, et cetera.
+///
+/// `toml++` attempts to combat this problem by nesting everything inside an additional inline namespace that
+/// changes according to the library's major version and the compiler's exception-handling mode.
+/// \endparblock
///
///////////////////////////////////////////////////////////////////////
///
@@ -173,23 +175,47 @@
/// }
/// \ecpp
///
+/// Instances of toml::parse_error can be printed directly to streams:
+/// \cpp
+/// try
+/// {
+/// auto tbl = toml::parse("enabled = trUe"sv); //fails; TOML booleans are case-sensitive
+/// }
+/// catch (const toml::parse_error & err)
+/// {
+/// std::cerr << "Parsing failed:\n"sv << err << std::endl;
+/// return 1;
+/// }
+/// \ecpp
+///
+/// \out
+/// Parsing failed:
+/// Encountered unexpected character while parsing boolean; expected 'true', saw 'trU'
+/// (error occurred at line 1, column 13)
+/// \eout
+///
+/// If the default error formatting is not be suitable for your use-case you can access the error's
+/// toml::source_region and description directly from the error object (as in the examples above).
+///
/// \see
/// - toml::parse_file()
/// - toml::parse_result
-/// - toml::parse_error
+/// - toml::parse_error
+/// - toml::source_region
+/// - toml::source_position
///
///////////////////////////////////
///
-/// \subsection mainpage-example-parsing-strings Parsing TOML directly from strings
-///
+/// \subsection mainpage-example-parsing-strings Parsing TOML directly from strings and streams
+/// Strings and std::istreams can be read directly using toml::parse():
/// \cpp
/// #include
+/// #include
/// #include
/// using namespace std::string_view_literals;
///
/// int main()
/// {
-/// // parse error handling omitted for brevity.
/// static constexpr auto source = R"(
/// [library]
/// name = "toml++"
@@ -199,8 +225,20 @@
/// [dependencies]
/// cpp = 17
/// )"sv;
-/// auto tbl = toml::parse(source);
-/// std::cout << tbl << std::endl;
+///
+/// // parse directly from a string view:
+/// {
+/// auto tbl = toml::parse(source);
+/// std::cout << tbl << std::endl;
+/// }
+///
+/// // parse from a string stream:
+/// {
+/// std::stringstream ss{ std::string{ source } };
+/// auto tbl = toml::parse(ss);
+/// std::cout << tbl << std::endl;
+/// }
+///
/// return 0;
/// }
/// \ecpp
@@ -213,7 +251,10 @@
/// authors = ["Mark Gillard "]
/// name = "toml++"
/// version = "0.1.0"
+///
+/// ... exactly as above, but twice
/// \eout
+///
/// \see toml::parse()
///
///////////////////////////////////
@@ -353,7 +394,9 @@
///////////////////////////////////////////////////////////////////////
///
/// \section mainpage-contributing Contributing
-/// See the [Contributing](https://github.com/marzer/tomlplusplus/blob/master/README.md#contributing) section of the repository README.
+/// Contributions are very welcome! Either by [reporting issues](https://github.com/marzer/tomlplusplus/issues) or submitting pull requests.
+/// If you wish to submit a pull request, please see [CONTRIBUTING](https://github.com/marzer/tomlplusplus/blob/master/CONTRIBUTING.md)
+/// for all the details you need to get going.
///
///////////////////////////////////////////////////////////////////////
///
@@ -366,6 +409,6 @@
/// 'Flexible and Economical UTF - 8 Decoder', which is also subject to the terms of the MIT license - see
/// [LICENSE-utf8-decoder](https://github.com/marzer/tomlplusplus/blob/master/LICENSE-utf8-decoder).
///
-/// \remark Note that if you're using the single-header version of the library you don't need to distribute these files;
+/// \remark If you're using the single-header version of the library you don't need to distribute these files;
/// their contents is included in the preamble at the top of the file.
///
diff --git a/include/toml++/toml_common.h b/include/toml++/toml_common.h
index 777ef7f..c858907 100644
--- a/include/toml++/toml_common.h
+++ b/include/toml++/toml_common.h
@@ -594,6 +594,33 @@ TOML_START
{
return source_;
}
+
+ /// \brief Prints a parse_error to a stream.
+ ///
+ /// \detail \cpp
+ /// try
+ /// {
+ /// auto tbl = toml::parse("enabled = trUe"sv);
+ /// }
+ /// catch (const toml::parse_error & err)
+ /// {
+ /// std::cerr << "Parsing failed:\n"sv << err << std::endl;
+ /// }
+ /// \ecpp
+ ///
+ /// \out
+ /// Parsing failed:
+ /// Encountered unexpected character while parsing boolean; expected 'true', saw 'trU'
+ /// (error occurred at line 1, column 13)
+ /// \eout
+ ///
+ /// \param lhs The stream.
+ /// \param rhs The parse_error.
+ ///
+ /// \returns The input stream.
+ template
+ friend std::basic_ostream& operator << (std::basic_ostream& lhs, const parse_error& rhs)
+ TOML_MAY_THROW;
};
#else
@@ -633,6 +660,10 @@ TOML_START
{
return source_;
}
+
+ template
+ friend std::basic_ostream& operator << (std::basic_ostream& lhs, const parse_error& rhs)
+ TOML_MAY_THROW;
};
#endif
diff --git a/include/toml++/toml_parser.h b/include/toml++/toml_parser.h
index f5b4d81..ff1abc6 100644
--- a/include/toml++/toml_parser.h
+++ b/include/toml++/toml_parser.h
@@ -9,6 +9,26 @@ TOML_START
#if TOML_DOXYGEN || !TOML_EXCEPTIONS
/// \brief The result of a parsing operation.
+ ///
+ /// \detail A parse_result is effectively a discriminated union containing either a toml::table
+ /// or a toml::parse_error. Most member functions assume a particular one of these two states,
+ /// and calling them when in the wrong state will cause errors (e.g. attempting to access the
+ /// error object when parsing was successful). \cpp
+ /// parse_result result = toml::parse_file("config.toml");
+ /// if (result)
+ /// do_stuff_with_a_table(result); //implicitly converts to table&
+ /// else
+ /// std::cerr << "Parse failed:\n"sv << result.error() << std::endl;
+ ///
+ /// \ecpp
+ ///
+ /// \out
+ /// example output:
+ ///
+ /// Parse failed:
+ /// Encountered unexpected character while parsing boolean; expected 'true', saw 'trU'
+ /// (error occurred at line 1, column 13 of 'config.toml')
+ /// \eout
///
/// \warning This type only exists when exceptions are disabled.
/// Otherwise parse_result is just an alias for toml::table: \cpp
@@ -26,22 +46,6 @@ TOML_START
///
/// #endif
/// \ecpp
- ///
- /// \detail A parse_result is effectively a discriminated union containing either a toml::table
- /// or a toml::parse_error. Most member functions assume a particular one of these two states,
- /// and calling them when in the wrong state will cause errors (e.g. attempting to access the
- /// error object when parsing was successful). \cpp
- /// parse_result result = toml::parse_file("config.toml");
- /// if (result)
- /// do_stuff_with_a_table(result); //implicitly converts to table&
- /// else
- /// std::cerr
- /// << "Error parsing file '"sv << *result.error().source().path
- /// << "':\n"sv << result.error().description()
- /// << "\n ("sv << result.error().source().begin << ")"sv
- /// << std::endl;
- ///
- /// \ecpp
class parse_result final
{
private:
@@ -971,6 +975,7 @@ TOML_IMPL_START
TOML_ERROR_CHECK({});
TOML_ASSERT(cp && (*cp == U't' || *cp == U'f'));
+ start_recording(true);
auto result = *cp == U't';
if (!consume_expected_sequence(result ? U"true"sv : U"false"sv))
{
@@ -979,9 +984,10 @@ TOML_IMPL_START
else
abort_with_error(
"Encountered unexpected character while parsing "sv, node_type::boolean,
- "; expected 'true' or 'false', saw '"sv, *cp, '\''
+ "; expected '"sv, result ? "true"sv : "false"sv, "', saw '"sv, recording_buffer, '\''
);
}
+ stop_recording();
TOML_ERROR_CHECK({});
if (cp && !is_value_terminator(*cp))
@@ -1008,6 +1014,7 @@ TOML_IMPL_START
abort_with_error("Encountered EOF while parsing "sv, node_type::floating_point);
};
+ start_recording(true);
const int sign = *cp == U'-' ? -1 : 1;
if (*cp == U'+' || *cp == U'-')
{
@@ -1022,9 +1029,10 @@ TOML_IMPL_START
eof_check();
abort_with_error(
"Encountered unexpected character while parsing "sv, node_type::floating_point,
- "; expected '"sv, inf ? "inf"sv : "nan"sv, "', saw '"sv, *cp, '\''
+ "; expected '"sv, inf ? "inf"sv : "nan"sv, "', saw '"sv, recording_buffer, '\''
);
}
+ stop_recording();
TOML_ERROR_CHECK({});
if (cp && !is_value_terminator(*cp))
diff --git a/include/toml++/toml_print_to_stream.h b/include/toml++/toml_print_to_stream.h
index 1327be9..01ef94e 100644
--- a/include/toml++/toml_print_to_stream.h
+++ b/include/toml++/toml_print_to_stream.h
@@ -302,7 +302,7 @@ TOML_START
);
impl::print_to_stream("line "sv, lhs);
impl::print_to_stream(rhs.line, lhs);
- impl::print_to_stream(", column ", lhs);
+ impl::print_to_stream(", column "sv, lhs);
impl::print_to_stream(rhs.column, lhs);
return lhs;
}
@@ -324,5 +324,16 @@ TOML_START
}
return lhs;
}
+
+ template
+ std::basic_ostream& operator << (std::basic_ostream& lhs, const parse_error& rhs)
+ TOML_MAY_THROW
+ {
+ impl::print_to_stream(rhs.description(), lhs);
+ impl::print_to_stream("\n\t(error occurred at "sv, lhs);
+ lhs << rhs.source();
+ impl::print_to_stream(")"sv, lhs);
+ return lhs;
+ }
}
TOML_END
diff --git a/include/toml++/toml_version.h b/include/toml++/toml_version.h
index 63f8d8d..202c65e 100644
--- a/include/toml++/toml_version.h
+++ b/include/toml++/toml_version.h
@@ -2,7 +2,7 @@
#define TOML_LIB_MAJOR 0
#define TOML_LIB_MINOR 2
-#define TOML_LIB_PATCH 0
+#define TOML_LIB_PATCH 1
#define TOML_LANG_MAJOR 0
#define TOML_LANG_MINOR 5
diff --git a/python/generate_documentation.py b/python/generate_documentation.py
index 3443608..896f126 100644
--- a/python/generate_documentation.py
+++ b/python/generate_documentation.py
@@ -517,9 +517,16 @@ class InlineNamespaceFix3(InlineNamespaceFixBase):
# adds some additional colouring to the syntax highlighting in code blocks.
class SyntaxHighlightingFix(object):
- __missing_keywords = [
+ __keywords = [
'constexpr',
- 'if'
+ 'if',
+ 'else',
+ 'true',
+ 'false',
+ 'const',
+ 'noexcept',
+ 'template',
+ 'typename'
]
def __call__(self, file, doc):
@@ -570,11 +577,12 @@ class SyntaxHighlightingFix(object):
changed = True
# misidentifed keywords
- nfs = code_block('span', class_='nf')
- for nf in nfs:
- if (nf.string is not None and nf.string in self.__missing_keywords):
- nf['class'] = 'k'
- changed = True
+ for keywordClass in ['nf', 'nb']:
+ kws = code_block('span', class_=keywordClass)
+ for kw in kws:
+ if (kw.string is not None and kw.string in self.__keywords):
+ kw['class'] = 'k'
+ changed = True
return changed
@@ -677,7 +685,7 @@ class ExtDocLinksFix(object):
# toml-specific
(r'toml::values?', 'classtoml_1_1value.html'),
(r'(toml::)?date_times?', 'structtoml_1_1date__time.html'),
- (r'(toml::)?times?', 'structtoml_1_1time.html'),
+ (r'(toml::)?time', 'structtoml_1_1time.html'),
(r'(toml::)?dates?', 'structtoml_1_1date.html')
]
__allowedNames = ['dd', 'p', 'dt', 'h3', 'td']
diff --git a/toml.hpp b/toml.hpp
index 1c2151e..12a44ee 100644
--- a/toml.hpp
+++ b/toml.hpp
@@ -1,6 +1,6 @@
//----------------------------------------------------------------------------------------------------------------------
//
-// toml++ v0.2.0
+// toml++ v0.2.1
// https://github.com/marzer/tomlplusplus
// SPDX-License-Identifier: MIT
//
@@ -295,7 +295,7 @@
#define TOML_LIB_MAJOR 0
#define TOML_LIB_MINOR 2
-#define TOML_LIB_PATCH 0
+#define TOML_LIB_PATCH 1
#define TOML_LANG_MAJOR 0
#define TOML_LANG_MINOR 5
@@ -532,6 +532,10 @@ TOML_START
{
return source_;
}
+
+ template
+ friend std::basic_ostream& operator << (std::basic_ostream& lhs, const parse_error& rhs)
+ TOML_MAY_THROW;
};
#else
@@ -571,6 +575,10 @@ TOML_START
{
return source_;
}
+
+ template
+ friend std::basic_ostream& operator << (std::basic_ostream& lhs, const parse_error& rhs)
+ TOML_MAY_THROW;
};
#endif
@@ -1308,7 +1316,7 @@ TOML_START
);
impl::print_to_stream("line "sv, lhs);
impl::print_to_stream(rhs.line, lhs);
- impl::print_to_stream(", column ", lhs);
+ impl::print_to_stream(", column "sv, lhs);
impl::print_to_stream(rhs.column, lhs);
return lhs;
}
@@ -1330,6 +1338,17 @@ TOML_START
}
return lhs;
}
+
+ template
+ std::basic_ostream& operator << (std::basic_ostream& lhs, const parse_error& rhs)
+ TOML_MAY_THROW
+ {
+ impl::print_to_stream(rhs.description(), lhs);
+ impl::print_to_stream("\n\t(error occurred at "sv, lhs);
+ lhs << rhs.source();
+ impl::print_to_stream(")"sv, lhs);
+ return lhs;
+ }
}
TOML_END
@@ -5590,6 +5609,7 @@ TOML_IMPL_START
TOML_ERROR_CHECK({});
TOML_ASSERT(cp && (*cp == U't' || *cp == U'f'));
+ start_recording(true);
auto result = *cp == U't';
if (!consume_expected_sequence(result ? U"true"sv : U"false"sv))
{
@@ -5598,9 +5618,10 @@ TOML_IMPL_START
else
abort_with_error(
"Encountered unexpected character while parsing "sv, node_type::boolean,
- "; expected 'true' or 'false', saw '"sv, *cp, '\''
+ "; expected '"sv, result ? "true"sv : "false"sv, "', saw '"sv, recording_buffer, '\''
);
}
+ stop_recording();
TOML_ERROR_CHECK({});
if (cp && !is_value_terminator(*cp))
@@ -5627,6 +5648,7 @@ TOML_IMPL_START
abort_with_error("Encountered EOF while parsing "sv, node_type::floating_point);
};
+ start_recording(true);
const int sign = *cp == U'-' ? -1 : 1;
if (*cp == U'+' || *cp == U'-')
{
@@ -5641,9 +5663,10 @@ TOML_IMPL_START
eof_check();
abort_with_error(
"Encountered unexpected character while parsing "sv, node_type::floating_point,
- "; expected '"sv, inf ? "inf"sv : "nan"sv, "', saw '"sv, *cp, '\''
+ "; expected '"sv, inf ? "inf"sv : "nan"sv, "', saw '"sv, recording_buffer, '\''
);
}
+ stop_recording();
TOML_ERROR_CHECK({});
if (cp && !is_value_terminator(*cp))
diff --git a/vs/toml++.vcxproj b/vs/toml++.vcxproj
index dc6be77..6360905 100644
--- a/vs/toml++.vcxproj
+++ b/vs/toml++.vcxproj
@@ -75,6 +75,7 @@
+
diff --git a/vs/toml++.vcxproj.filters b/vs/toml++.vcxproj.filters
index 087c99e..812176d 100644
--- a/vs/toml++.vcxproj.filters
+++ b/vs/toml++.vcxproj.filters
@@ -77,6 +77,7 @@
doc
+