Skip to content

Commit

Permalink
added missing operator<< for parse_error
Browse files Browse the repository at this point in the history
also:
- fixed printing bug in operator << for source_position
- improved quality of error messages for boolean and inf/nan parsing
- documentation fixes
  • Loading branch information
marzer committed Feb 25, 2020
1 parent 94f2f5a commit 44e5b1b
Show file tree
Hide file tree
Showing 15 changed files with 184 additions and 68 deletions.
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

<br>

Expand Down
1 change: 1 addition & 0 deletions docs/Doxyfile-mcss
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ HTML_EXTRA_FILES = tomlplusplus.js \
##! <a target="_blank" href="https://github.com/marzer/tomlplusplus/issues">Report an issue</a> \
##! <br><br>Documentation generated using <a href="https://mcss.mosra.cz/">m.css</a>
##! M_HTML_HEADER = <script src="tomlplusplus.js"></script>
##! M_FAVICON = favicon.ico
Binary file added docs/favicon.ico
Binary file not shown.
7 changes: 1 addition & 6 deletions examples/parse_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
13 changes: 3 additions & 10 deletions examples/toml_to_json_transcoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
75 changes: 59 additions & 16 deletions include/toml++/toml.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
///
///////////////////////////////////////////////////////////////////////
///
Expand All @@ -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.
///
/// <blockquote>
/// <h3>On Linkers and the One-Definition-Rule</h3>
/// <p>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.</p>
/// <p>`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.</p>
/// </blockquote>
/// 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
///
///////////////////////////////////////////////////////////////////////
///
Expand Down Expand Up @@ -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 <iostream>
/// #include <sstream>
/// #include <toml++/toml.h>
/// using namespace std::string_view_literals;
///
/// int main()
/// {
/// // parse error handling omitted for brevity.
/// static constexpr auto source = R"(
/// [library]
/// name = "toml++"
Expand All @@ -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
Expand All @@ -213,7 +251,10 @@
/// authors = ["Mark Gillard <[email protected]>"]
/// name = "toml++"
/// version = "0.1.0"
///
/// ... exactly as above, but twice
/// \eout
///
/// \see toml::parse()
///
///////////////////////////////////
Expand Down Expand Up @@ -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.
///
///////////////////////////////////////////////////////////////////////
///
Expand All @@ -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.
///
31 changes: 31 additions & 0 deletions include/toml++/toml_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename CHAR>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const parse_error& rhs)
TOML_MAY_THROW;
};

#else
Expand Down Expand Up @@ -633,6 +660,10 @@ TOML_START
{
return source_;
}

template <typename CHAR>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const parse_error& rhs)
TOML_MAY_THROW;
};

#endif
Expand Down
44 changes: 26 additions & 18 deletions include/toml++/toml_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <strong>This type only exists when exceptions are disabled.</strong>
/// Otherwise parse_result is just an alias for toml::table: \cpp
Expand All @@ -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:
Expand Down Expand Up @@ -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))
{
Expand All @@ -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))
Expand All @@ -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'-')
{
Expand All @@ -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))
Expand Down
13 changes: 12 additions & 1 deletion include/toml++/toml_print_to_stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -324,5 +324,16 @@ TOML_START
}
return lhs;
}

template <typename CHAR>
std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& 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
2 changes: 1 addition & 1 deletion include/toml++/toml_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 44e5b1b

Please sign in to comment.