mirror of
https://github.com/marzer/tomlplusplus.git
synced 2024-10-06 06:49:43 +00:00
added toml::yaml_formatter
also: - fixed parser not correctly round-tripping int format in some cases - added `TOML_ENABLE_FORMATTERS` option - added `operator->` to `toml::value` - refactoring
This commit is contained in:
parent
0ffd23d73f
commit
7b50df796f
41
README.md
41
README.md
@ -24,7 +24,7 @@
|
||||
- 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 and YAML
|
||||
- Tested on Clang (6+), GCC (7+) and MSVC (VS2019)
|
||||
- Tested on x64, x86 and ARM
|
||||
|
||||
@ -79,6 +79,8 @@ std::cout << config << "\n";
|
||||
// re-serialize as JSON
|
||||
std::cout << toml::json_formatter{ config } << "\n";
|
||||
|
||||
// re-serialize as YAML
|
||||
std::cout << toml::yaml_formatter{ config } << "\n";
|
||||
|
||||
```
|
||||
You'll find some more code examples in the `examples` directory, and plenty more as part of the [API documentation].
|
||||
@ -97,13 +99,13 @@ You'll find some more code examples in the `examples` directory, and plenty more
|
||||
2. `#include <toml++/toml.h>`
|
||||
|
||||
### Conan
|
||||
Add `tomlplusplus/2.5.0` to your conanfile.
|
||||
Add `tomlplusplus/3.0.0` to your conanfile.
|
||||
|
||||
### DDS
|
||||
Add `tomlpp` to your `package.json5`, e.g.:
|
||||
```
|
||||
depends: [
|
||||
'tomlpp^2.5.0',
|
||||
'tomlpp^3.0.0',
|
||||
]
|
||||
```
|
||||
> ℹ️ _[What is DDS?](https://dds.pizza/)_
|
||||
@ -119,7 +121,7 @@ include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
tomlplusplus
|
||||
GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git
|
||||
GIT_TAG v2.5.0
|
||||
GIT_TAG v3.0.0
|
||||
)
|
||||
FetchContent_MakeAvailable(tomlplusplus)
|
||||
```
|
||||
@ -136,22 +138,21 @@ assured that I fully support it being added, and welcome [pull requests](./CONTR
|
||||
A number of configurable options are exposed in the form of preprocessor `#defines` Most likely you
|
||||
won't need to mess with these at all, but if you do, set them before including toml++.
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|-----------------------------------|:--------------:|--------------------------|----------------------------------------------------------------------------------------------------------------------|
|
||||
| `TOML_API` | define | undefined | API annotation to add to public symbols (e.g. `__declspec(dllexport)` on Windows). |
|
||||
| `TOML_ASSERT(expr)` | function macro | `assert()` | Sets the assert function used by the library. |
|
||||
| `TOML_CONFIG_HEADER` | string literal | undefined | Includes the given header file before the rest of the library. |
|
||||
| `TOML_ENABLE_JSON_FORMATTER` | boolean | `1` | Enables the JSON formatter. Set to `0` if you don't need it to improve compile times and binary size. |
|
||||
| `TOML_ENABLE_TOML_FORMATTER` | boolean | `1` | Enables the TOML formatter. Set to `0` if you don't need it to improve compile times and binary size. |
|
||||
| `TOML_ENABLE_PARSER` | boolean | `1` | Enables the parser. Set to `0` if you don't need it to improve compile times and binary size. |
|
||||
| `TOML_ENABLE_UNRELEASED_FEATURES` | boolean | `0` | Enables support for [unreleased TOML language features. |
|
||||
| `TOML_ENABLE_WINDOWS_COMPAT` | boolean | `1` on Windows | Enables support for transparent conversion between wide and narrow strings. |
|
||||
| `TOML_EXCEPTIONS` | boolean | your compiler's settings | Sets whether the library uses exceptions. |
|
||||
| `TOML_HEADER_ONLY` | boolean | `1` | Disable this to explicitly control where toml++'s implementation is compiled (e.g. as part of a library). |
|
||||
| `TOML_IMPLEMENTATION` | define | undefined | Define this to enable compilation of the library's implementation when `TOML_HEADER_ONLY` == `0`. |
|
||||
| `TOML_OPTIONAL_TYPE` | type name | undefined | Overrides the `optional<T>` type used by the library if you need [something better than std::optional]. |
|
||||
| `TOML_SMALL_FLOAT_TYPE` | type name | undefined | If your codebase has an additional 'small' float type (e.g. half-precision), this tells toml++ about it. |
|
||||
| `TOML_SMALL_INT_TYPE` | type name | undefined | If your codebase has an additional 'small' integer type (e.g. 24-bits), this tells toml++ about it. |
|
||||
| Option | Type | Default | Description |
|
||||
|-----------------------------------|:--------------:|--------------------------|---------------------------------------------------------------------------------------------------------------|
|
||||
| `TOML_API` | define | undefined | API annotation to add to public symbols (e.g. `__declspec(dllexport)` on Windows). |
|
||||
| `TOML_ASSERT(expr)` | function macro | `assert()` | Sets the assert function used by the library. |
|
||||
| `TOML_CONFIG_HEADER` | string literal | undefined | Includes the given header file before the rest of the library. |
|
||||
| `TOML_ENABLE_FORMATTERS` | boolean | `1` | Enables the formatters. Set to `0` if you don't need them to improve compile times and binary size. |
|
||||
| `TOML_ENABLE_PARSER` | boolean | `1` | Enables the parser. Set to `0` if you don't need it to improve compile times and binary size. |
|
||||
| `TOML_ENABLE_UNRELEASED_FEATURES` | boolean | `0` | Enables support for [unreleased TOML language features. |
|
||||
| `TOML_ENABLE_WINDOWS_COMPAT` | boolean | `1` on Windows | Enables support for transparent conversion between wide and narrow strings. |
|
||||
| `TOML_EXCEPTIONS` | boolean | match compiler settings | Sets whether the library uses exceptions. |
|
||||
| `TOML_HEADER_ONLY` | boolean | `1` | Disable this to explicitly control where toml++'s implementation is compiled (e.g. as part of a library). |
|
||||
| `TOML_IMPLEMENTATION` | define | undefined | Define this to enable compilation of the library's implementation when `TOML_HEADER_ONLY` == `0`. |
|
||||
| `TOML_OPTIONAL_TYPE` | type name | undefined | Overrides the `optional<T>` type used by the library if you need [something better than std::optional]. |
|
||||
| `TOML_SMALL_FLOAT_TYPE` | type name | undefined | If your codebase has an additional 'small' float type (e.g. half-precision), this tells toml++ about it. |
|
||||
| `TOML_SMALL_INT_TYPE` | type name | undefined | If your codebase has an additional 'small' integer type (e.g. 24-bits), this tells toml++ about it. |
|
||||
|
||||
> ℹ️ _A number of these have ABI implications; the library uses inline namespaces to prevent you from accidentally
|
||||
linking incompatible combinations together._
|
||||
|
1
cpp.hint
1
cpp.hint
@ -9,6 +9,7 @@
|
||||
#define TOML_CONST_GETTER
|
||||
#define TOML_CONST_INLINE_GETTER inline
|
||||
#define TOML_CONSTRAINED_TEMPLATE(cond, ...) template <__VA_ARGS__>
|
||||
#define TOML_HIDDEN_CONSTRAINT(cond, ...) template <__VA_ARGS__>
|
||||
#define TOML_EMPTY_BASES
|
||||
#define TOML_EXTERN
|
||||
#define TOML_EXTERN_NOEXCEPT(...)
|
||||
|
@ -9,7 +9,7 @@
|
||||
\section mainpage-features Features
|
||||
- Supports the latest [TOML](https://toml.io/) release ([v1.0.0](https://toml.io/en/v1.0.0)), plus
|
||||
optional support for some unreleased TOML features
|
||||
- Supports serializing to JSON
|
||||
- Supports serializing to JSON and YAML
|
||||
- Proper UTF-8 handling (incl. BOM)
|
||||
- C++17 (plus some C++20 features where available, e.g. experimental support for char8_t strings)
|
||||
- Header-only (optional!)
|
||||
@ -130,7 +130,7 @@
|
||||
|
||||
\subsection mainpage-example-parsing-without-exceptions Handling errors without exceptions
|
||||
Can't (or won't) use exceptions? That's fine too. You can disable exceptions in your compiler flags and/or
|
||||
explicitly disable the library's use of them by setting the option \ref TOML_EXCEPTIONS to `0`. In either case,
|
||||
explicitly disable the library's use of them by setting the option #TOML_EXCEPTIONS to `0`. In either case,
|
||||
the parsing functions return a toml::parse_result instead of a toml::table:
|
||||
|
||||
\cpp
|
||||
@ -290,10 +290,10 @@
|
||||
|
||||
|
||||
|
||||
\subsection mainpage-example-serialization Serializing as TOML and JSON
|
||||
\subsection mainpage-example-serialization Serializing as TOML, JSON and YAML
|
||||
All toml++ data types have overloaded `operator<<` for ostreams, so 'serializing' a set of TOML data to actual
|
||||
TOML is done just by printing it to an ostream. Converting it to JSON is done in the same way,
|
||||
but via a toml::json_formatter.
|
||||
TOML is done just by printing it to an ostream. Converting it to JSON and YAML is done in much the same way,
|
||||
but via a toml::json_formatter and toml::yaml_formatter.
|
||||
|
||||
\godbolt{MMNoW4}
|
||||
|
||||
@ -323,6 +323,10 @@
|
||||
// serializing as JSON using toml::json_formatter:
|
||||
std::cout << "###### JSON ######" << "\n\n";
|
||||
std::cout << toml::json_formatter{ tbl } << "\n\n";
|
||||
|
||||
// serializing as YAML using toml::yaml_formatter:
|
||||
std::cout << "###### YAML ######" << "\n\n";
|
||||
std::cout << toml::yaml_formatter{ tbl } << "\n\n";
|
||||
return 0;
|
||||
}
|
||||
\ecpp
|
||||
@ -360,10 +364,14 @@
|
||||
"and beyond"
|
||||
]
|
||||
}
|
||||
|
||||
###### YAML ######
|
||||
|
||||
\eout
|
||||
\see
|
||||
- toml::toml_formatter
|
||||
- toml::json_formatter
|
||||
- toml::yaml_formatter
|
||||
|
||||
|
||||
|
||||
@ -373,7 +381,7 @@
|
||||
a large number of translation units. You can counter this by disabling header-only mode and explicitly controlling
|
||||
where the library's implementation is compiled.
|
||||
|
||||
<strong>Step 1: Set \ref TOML_HEADER_ONLY to [code]0[/code] before including toml++</strong>
|
||||
<strong>Step 1: Set #TOML_HEADER_ONLY to [code]0[/code] before including toml++</strong>
|
||||
|
||||
This must be the same everywhere, so either set it as a global `#define` in your build system, or
|
||||
do it manually before including toml++ in some global header that's used everywhere in your project:
|
||||
@ -384,7 +392,7 @@
|
||||
#include <toml.hpp>
|
||||
\ecpp
|
||||
|
||||
<strong>Step 2: Define \ref TOML_IMPLEMENTATION before including toml++ in one specific translation unit</strong>
|
||||
<strong>Step 2: Define #TOML_IMPLEMENTATION before including toml++ in one specific translation unit</strong>
|
||||
|
||||
\cpp
|
||||
// some_code_file.cpp
|
||||
@ -397,7 +405,7 @@
|
||||
|
||||
Some library features can be disabled wholesale so you can avoid paying their the compilation cost if you don't need them.
|
||||
For example, if all you need to do is serialize some code-generated TOML and don't actually need the parser at all you, can
|
||||
set \ref TOML_ENABLE_PARSER to `0` to disable the parser altogether. This can yield fairly significant compilation
|
||||
set #TOML_ENABLE_PARSER to `0` to disable the parser altogether. This can yield fairly significant compilation
|
||||
speedups since the parser accounts for a good chunk of the library's code.
|
||||
|
||||
|
||||
@ -428,7 +436,7 @@
|
||||
|
||||
|
||||
\subsection mainpage-adding-lib-conan Conan
|
||||
Add `tomlplusplus/2.5.0` to your conanfile.
|
||||
Add `tomlplusplus/3.0.0` to your conanfile.
|
||||
|
||||
|
||||
|
||||
@ -436,7 +444,7 @@
|
||||
Add `tomlpp` to your `package.json5`, e.g.:
|
||||
\bash
|
||||
depends: [
|
||||
'tomlpp^2.5.0',
|
||||
'tomlpp^3.0.0',
|
||||
]
|
||||
\ebash
|
||||
|
||||
@ -463,7 +471,7 @@
|
||||
FetchContent_Declare(
|
||||
tomlplusplus
|
||||
GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git
|
||||
GIT_TAG v2.5.0
|
||||
GIT_TAG v3.0.0
|
||||
)
|
||||
FetchContent_MakeAvailable(tomlplusplus)
|
||||
\endcode
|
||||
|
@ -1358,11 +1358,11 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// @}
|
||||
|
||||
#if TOML_ENABLE_TOML_FORMATTER
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
/// \brief Prints the array out to a stream as formatted TOML.
|
||||
///
|
||||
/// \availability This operator is only available when #TOML_ENABLE_TOML_FORMATTER is enabled.
|
||||
/// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled.
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const array& rhs)
|
||||
{
|
||||
impl::print_to_stream(lhs, rhs);
|
||||
|
@ -4,6 +4,9 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "forward_declarations.h"
|
||||
#include "print_to_stream.h"
|
||||
#include "header_start.h"
|
||||
@ -13,9 +16,15 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
struct formatter_constants
|
||||
{
|
||||
std::string_view pos_inf;
|
||||
std::string_view neg_inf;
|
||||
std::string_view nan;
|
||||
format_flags mandatory_flags;
|
||||
format_flags ignored_flags;
|
||||
|
||||
std::string_view float_pos_inf;
|
||||
std::string_view float_neg_inf;
|
||||
std::string_view float_nan;
|
||||
|
||||
std::string_view bool_true;
|
||||
std::string_view bool_false;
|
||||
};
|
||||
|
||||
struct formatter_config
|
||||
@ -34,6 +43,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
const formatter_constants* constants_;
|
||||
formatter_config config_;
|
||||
size_t indent_columns_;
|
||||
format_flags int_format_mask_;
|
||||
std::ostream* stream_; //
|
||||
int indent_; // these are set in attach()
|
||||
bool naked_newline_; //
|
||||
@ -90,47 +100,12 @@ TOML_IMPL_NAMESPACE_START
|
||||
return !!(config_.flags & format_flags::indent_sub_tables);
|
||||
}
|
||||
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool quote_dates_and_times() const noexcept
|
||||
{
|
||||
return !!(config_.flags & format_flags::quote_dates_and_times);
|
||||
}
|
||||
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool quote_infinities_and_nans() const noexcept
|
||||
{
|
||||
return !!(config_.flags & format_flags::quote_infinities_and_nans);
|
||||
}
|
||||
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool literal_strings_allowed() const noexcept
|
||||
{
|
||||
return !!(config_.flags & format_flags::allow_literal_strings);
|
||||
}
|
||||
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool multi_line_strings_allowed() const noexcept
|
||||
{
|
||||
return !!(config_.flags & format_flags::allow_multi_line_strings);
|
||||
}
|
||||
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool value_format_flags_allowed() const noexcept
|
||||
{
|
||||
return !!(config_.flags & format_flags::allow_value_format_flags);
|
||||
}
|
||||
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool naked_newline() const noexcept
|
||||
{
|
||||
return naked_newline_;
|
||||
}
|
||||
|
||||
void clear_naked_newline() noexcept
|
||||
{
|
||||
naked_newline_ = false;
|
||||
}
|
||||
|
||||
TOML_API
|
||||
void attach(std::ostream& stream) noexcept;
|
||||
|
||||
@ -143,6 +118,12 @@ TOML_IMPL_NAMESPACE_START
|
||||
TOML_API
|
||||
void print_indent();
|
||||
|
||||
TOML_API
|
||||
void print_unformatted(char);
|
||||
|
||||
TOML_API
|
||||
void print_unformatted(std::string_view);
|
||||
|
||||
TOML_API
|
||||
void print_string(std::string_view str, bool allow_multi_line = true, bool allow_bare = false);
|
||||
|
||||
@ -183,3 +164,4 @@ TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
/// \endcond
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
||||
|
@ -4,12 +4,13 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
//# {{
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "formatter.h"
|
||||
#include "print_to_stream.h"
|
||||
@ -38,9 +39,15 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_ASSERT(source_ != nullptr);
|
||||
|
||||
config_.flags = (config_.flags | constants_->mandatory_flags) & ~constants_->ignored_flags;
|
||||
|
||||
indent_columns_ = {};
|
||||
for (auto c : config_.indent)
|
||||
indent_columns_ += c == '\t' ? 4u : 1u;
|
||||
|
||||
int_format_mask_ = config_.flags
|
||||
& (format_flags::allow_binary_integers | format_flags::allow_octal_integers
|
||||
| format_flags::allow_hexadecimal_integers);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
@ -77,6 +84,20 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print_unformatted(char c)
|
||||
{
|
||||
print_to_stream(*stream_, c);
|
||||
naked_newline_ = false;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print_unformatted(std::string_view str)
|
||||
{
|
||||
print_to_stream(*stream_, str);
|
||||
naked_newline_ = false;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print_string(std::string_view str, bool allow_multi_line, bool allow_bare)
|
||||
{
|
||||
@ -88,7 +109,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
return;
|
||||
}
|
||||
|
||||
auto multi_line = allow_multi_line && multi_line_strings_allowed();
|
||||
auto multi_line = allow_multi_line && !!(config_.flags & format_flags::allow_multi_line_strings);
|
||||
if (multi_line || literals || allow_bare)
|
||||
{
|
||||
utf8_decoder decoder;
|
||||
@ -148,26 +169,49 @@ TOML_IMPL_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print(const value<int64_t>& val)
|
||||
{
|
||||
if (value_format_flags_allowed() && *val >= 0)
|
||||
{
|
||||
static constexpr auto value_format_flags =
|
||||
value_flags::format_as_binary | value_flags::format_as_octal | value_flags::format_as_hexadecimal;
|
||||
const auto fmt = val.flags() & value_format_flags;
|
||||
if (fmt != value_flags::none)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case value_flags::format_as_binary: print_to_stream(*stream_, "0b"sv); break;
|
||||
case value_flags::format_as_octal: print_to_stream(*stream_, "0o"sv); break;
|
||||
case value_flags::format_as_hexadecimal: print_to_stream(*stream_, "0x"sv); break;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
}
|
||||
print_to_stream(*stream_, *val, fmt);
|
||||
}
|
||||
else
|
||||
print_to_stream(*stream_, *val);
|
||||
naked_newline_ = false;
|
||||
|
||||
if (*val >= 0 && !!int_format_mask_)
|
||||
{
|
||||
static constexpr auto value_flags_mask =
|
||||
value_flags::format_as_binary | value_flags::format_as_octal | value_flags::format_as_hexadecimal;
|
||||
|
||||
const auto fmt = val.flags() & value_flags_mask;
|
||||
switch (fmt)
|
||||
{
|
||||
case value_flags::format_as_binary:
|
||||
if (!!(int_format_mask_ & format_flags::allow_binary_integers))
|
||||
{
|
||||
print_to_stream(*stream_, "0b"sv);
|
||||
print_to_stream(*stream_, *val, fmt);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case value_flags::format_as_octal:
|
||||
if (!!(int_format_mask_ & format_flags::allow_octal_integers))
|
||||
{
|
||||
print_to_stream(*stream_, "0o"sv);
|
||||
print_to_stream(*stream_, *val, fmt);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case value_flags::format_as_hexadecimal:
|
||||
if (!!(int_format_mask_ & format_flags::allow_hexadecimal_integers))
|
||||
{
|
||||
print_to_stream(*stream_, "0x"sv);
|
||||
print_to_stream(*stream_, *val, fmt);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to decimal
|
||||
print_to_stream(*stream_, *val);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
@ -176,16 +220,16 @@ TOML_IMPL_NAMESPACE_START
|
||||
const std::string_view* inf_nan = nullptr;
|
||||
switch (fpclassify(*val))
|
||||
{
|
||||
case fp_class::neg_inf: inf_nan = &constants_->neg_inf; break;
|
||||
case fp_class::pos_inf: inf_nan = &constants_->pos_inf; break;
|
||||
case fp_class::nan: inf_nan = &constants_->nan; break;
|
||||
case fp_class::neg_inf: inf_nan = &constants_->float_neg_inf; break;
|
||||
case fp_class::pos_inf: inf_nan = &constants_->float_pos_inf; break;
|
||||
case fp_class::nan: inf_nan = &constants_->float_nan; break;
|
||||
case fp_class::ok: print_to_stream(*stream_, *val); break;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
if (inf_nan)
|
||||
{
|
||||
if (quote_infinities_and_nans())
|
||||
if (!!(config_.flags & format_flags::quote_infinities_and_nans))
|
||||
print_to_stream_bookended(*stream_, *inf_nan, '"');
|
||||
else
|
||||
print_to_stream(*stream_, *inf_nan);
|
||||
@ -197,14 +241,13 @@ TOML_IMPL_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print(const value<bool>& val)
|
||||
{
|
||||
print_to_stream(*stream_, *val);
|
||||
naked_newline_ = false;
|
||||
print_unformatted(*val ? constants_->bool_true : constants_->bool_false);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print(const value<date>& val)
|
||||
{
|
||||
if (quote_dates_and_times())
|
||||
if (!!(config_.flags & format_flags::quote_dates_and_times))
|
||||
print_to_stream_bookended(*stream_, *val, literal_strings_allowed() ? '\'' : '"');
|
||||
else
|
||||
print_to_stream(*stream_, *val);
|
||||
@ -214,7 +257,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print(const value<time>& val)
|
||||
{
|
||||
if (quote_dates_and_times())
|
||||
if (!!(config_.flags & format_flags::quote_dates_and_times))
|
||||
print_to_stream_bookended(*stream_, *val, literal_strings_allowed() ? '\'' : '"');
|
||||
else
|
||||
print_to_stream(*stream_, *val);
|
||||
@ -224,7 +267,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print(const value<date_time>& val)
|
||||
{
|
||||
if (quote_dates_and_times())
|
||||
if (!!(config_.flags & format_flags::quote_dates_and_times))
|
||||
print_to_stream_bookended(*stream_, *val, literal_strings_allowed() ? '\'' : '"');
|
||||
else
|
||||
print_to_stream(*stream_, *val);
|
||||
@ -275,3 +318,4 @@ TOML_IMPL_NAMESPACE_START
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
||||
|
@ -102,6 +102,8 @@ TOML_NAMESPACE_START
|
||||
|
||||
class toml_formatter;
|
||||
class json_formatter;
|
||||
class yaml_formatter;
|
||||
class xml_formatter;
|
||||
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex);
|
||||
#if TOML_EXCEPTIONS
|
||||
@ -297,7 +299,7 @@ TOML_NAMESPACE_START // abi namespace
|
||||
none,
|
||||
|
||||
/// \brief Dates and times will be emitted as quoted strings.
|
||||
quote_dates_and_times = 1ull,
|
||||
quote_dates_and_times = (1ull << 0),
|
||||
|
||||
/// \brief Infinities and NaNs will be emitted as quoted strings.
|
||||
quote_infinities_and_nans = (1ull << 1),
|
||||
@ -308,14 +310,20 @@ TOML_NAMESPACE_START // abi namespace
|
||||
/// \brief Strings containing newlines will be emitted as triple-quoted 'multi-line' strings where possible.
|
||||
allow_multi_line_strings = (1ull << 3),
|
||||
|
||||
/// \brief Values with special format flags will be formatted accordingly.
|
||||
allow_value_format_flags = (1ull << 4),
|
||||
/// \brief Allow integers with #value_flags::format_as_binary to be emitted as binary.
|
||||
allow_binary_integers = (1ull << 4),
|
||||
|
||||
/// \brief Allow integers with #value_flags::format_as_octal to be emitted as octal.
|
||||
allow_octal_integers = (1ull << 5),
|
||||
|
||||
/// \brief Allow integers with #value_flags::format_as_hexadecimal to be emitted as hexadecimal.
|
||||
allow_hexadecimal_integers = (1ull << 6),
|
||||
|
||||
/// \brief Apply indentation to tables nested within other tables/arrays.
|
||||
indent_sub_tables = (1ull << 5),
|
||||
indent_sub_tables = (1ull << 7),
|
||||
|
||||
/// \brief Apply indentation to array elements when the array is forced to wrap over multiple lines.
|
||||
indent_array_elements = (1ull << 6),
|
||||
indent_array_elements = (1ull << 8),
|
||||
|
||||
/// \brief Combination mask of all indentation-enabling flags.
|
||||
indentation = indent_sub_tables | indent_array_elements,
|
||||
|
@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
#if TOML_ENABLE_JSON_FORMATTER
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "formatter.h"
|
||||
#include "header_start.h"
|
||||
@ -14,7 +14,7 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A wrapper for printing TOML objects out to a stream as formatted JSON.
|
||||
///
|
||||
/// \availability This class is only available when #TOML_ENABLE_TOML_FORMATTER is enabled.
|
||||
/// \availability This class is only available when #TOML_ENABLE_FORMATTERS is enabled.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto some_toml = toml::parse(R"(
|
||||
@ -26,7 +26,6 @@ TOML_NAMESPACE_START
|
||||
/// smooth = true
|
||||
/// )"sv);
|
||||
/// std::cout << toml::json_formatter{ some_toml } << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -60,16 +59,21 @@ TOML_NAMESPACE_START
|
||||
TOML_API
|
||||
void print();
|
||||
|
||||
static constexpr impl::formatter_constants constants = { "Infinity"sv, "-Infinity"sv, "NaN"sv };
|
||||
static constexpr format_flags mandatory_flags = format_flags::quote_dates_and_times;
|
||||
static constexpr format_flags ignored_flags =
|
||||
format_flags::allow_literal_strings | format_flags::allow_multi_line_strings;
|
||||
static constexpr impl::formatter_constants constants = {
|
||||
format_flags::quote_dates_and_times, // mandatory
|
||||
format_flags::allow_literal_strings | format_flags::allow_multi_line_strings, // ignored
|
||||
"Infinity"sv,
|
||||
"-Infinity"sv,
|
||||
"NaN"sv,
|
||||
"true"sv,
|
||||
"false"sv
|
||||
};
|
||||
|
||||
/// \endcond
|
||||
|
||||
public:
|
||||
/// \brief The default flags for a json_formatter.
|
||||
static constexpr format_flags default_flags = format_flags::quote_dates_and_times //
|
||||
static constexpr format_flags default_flags = constants.mandatory_flags //
|
||||
| format_flags::quote_infinities_and_nans //
|
||||
| format_flags::indentation;
|
||||
|
||||
@ -79,7 +83,7 @@ TOML_NAMESPACE_START
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit json_formatter(const toml::node& source, format_flags flags = default_flags) noexcept
|
||||
: base{ &source, nullptr, constants, { (flags | mandatory_flags) & ~ignored_flags, " "sv } }
|
||||
: base{ &source, nullptr, constants, { flags, " "sv } }
|
||||
{}
|
||||
|
||||
#if defined(DOXYGEN) || (TOML_ENABLE_PARSER && !TOML_EXCEPTIONS)
|
||||
@ -110,7 +114,7 @@ TOML_NAMESPACE_START
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit json_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
|
||||
: base{ nullptr, &result, constants, { (flags | mandatory_flags) & ~ignored_flags, " "sv } }
|
||||
: base{ nullptr, &result, constants, { flags, " "sv } }
|
||||
{}
|
||||
|
||||
#endif
|
||||
@ -134,4 +138,4 @@ TOML_NAMESPACE_START
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_JSON_FORMATTER
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
||||
|
@ -10,7 +10,7 @@
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
#if TOML_ENABLE_JSON_FORMATTER
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "json_formatter.h"
|
||||
#include "print_to_stream.h"
|
||||
@ -24,76 +24,78 @@ TOML_NAMESPACE_START
|
||||
void json_formatter::print(const toml::table& tbl)
|
||||
{
|
||||
if (tbl.empty())
|
||||
impl::print_to_stream(base::stream(), "{}"sv);
|
||||
else
|
||||
{
|
||||
impl::print_to_stream(base::stream(), '{');
|
||||
if (base::indent_sub_tables())
|
||||
base::increase_indent();
|
||||
bool first = false;
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
if (first)
|
||||
impl::print_to_stream(base::stream(), ',');
|
||||
first = true;
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
base::print_unformatted("{}"sv);
|
||||
return;
|
||||
}
|
||||
|
||||
base::print_string(k, false);
|
||||
impl::print_to_stream(base::stream(), " : "sv);
|
||||
base::print_unformatted('{');
|
||||
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
if (base::indent_sub_tables())
|
||||
base::decrease_indent();
|
||||
if (base::indent_sub_tables())
|
||||
base::increase_indent();
|
||||
bool first = false;
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
if (first)
|
||||
base::print_unformatted(',');
|
||||
first = true;
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
impl::print_to_stream(base::stream(), '}');
|
||||
|
||||
base::print_string(k, false);
|
||||
base::print_unformatted(" : "sv);
|
||||
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
if (base::indent_sub_tables())
|
||||
base::decrease_indent();
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
|
||||
base::print_unformatted('}');
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void json_formatter::print(const toml::array& arr)
|
||||
{
|
||||
if (arr.empty())
|
||||
impl::print_to_stream(base::stream(), "[]"sv);
|
||||
else
|
||||
{
|
||||
impl::print_to_stream(base::stream(), '[');
|
||||
if (base::indent_array_elements())
|
||||
base::increase_indent();
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
if (i > 0u)
|
||||
impl::print_to_stream(base::stream(), ',');
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
base::print_unformatted("[]"sv);
|
||||
return;
|
||||
}
|
||||
|
||||
auto& v = arr[i];
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
if (base::indent_array_elements())
|
||||
base::decrease_indent();
|
||||
base::print_unformatted('[');
|
||||
if (base::indent_array_elements())
|
||||
base::increase_indent();
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
if (i > 0u)
|
||||
base::print_unformatted(',');
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
impl::print_to_stream(base::stream(), ']');
|
||||
|
||||
auto& v = arr[i];
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
if (base::indent_array_elements())
|
||||
base::decrease_indent();
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
base::print_unformatted(']');
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
@ -113,4 +115,4 @@ TOML_NAMESPACE_START
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_JSON_FORMATTER
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
||||
|
@ -718,11 +718,11 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// @}
|
||||
|
||||
#if TOML_ENABLE_TOML_FORMATTER
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
/// \brief Prints the viewed node out to a stream.
|
||||
///
|
||||
/// \availability This operator is only available when #TOML_ENABLE_TOML_FORMATTER is enabled.
|
||||
/// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled.
|
||||
friend std::ostream& operator<<(std::ostream& os, const node_view& nv)
|
||||
{
|
||||
if (nv.node_)
|
||||
|
@ -269,7 +269,7 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \see toml::node_view
|
||||
TOML_NODISCARD
|
||||
node_view<node> operator[](string_view key) noexcept
|
||||
node_view<node> operator[](std::string_view key) noexcept
|
||||
{
|
||||
return err_ ? node_view<node>{} : table()[key];
|
||||
}
|
||||
@ -283,7 +283,7 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \see toml::node_view
|
||||
TOML_NODISCARD
|
||||
node_view<const node> operator[](string_view key) const noexcept
|
||||
node_view<const node> operator[](std::string_view key) const noexcept
|
||||
{
|
||||
return err_ ? node_view<const node>{} : table()[key];
|
||||
}
|
||||
@ -372,11 +372,17 @@ TOML_NAMESPACE_START
|
||||
return err_ ? const_table_iterator{} : table().cend();
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
/// \brief Prints the held error or table object out to a text stream.
|
||||
///
|
||||
/// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled.
|
||||
friend std::ostream& operator<<(std::ostream& os, const parse_result& result)
|
||||
{
|
||||
return result.err_ ? (os << result.error()) : (os << result.table());
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
TOML_ABI_NAMESPACE_END;
|
||||
|
@ -742,17 +742,13 @@ TOML_ANON_NAMESPACE_START
|
||||
node_ptr(node_ptr&&) = delete;
|
||||
node_ptr& operator=(node_ptr&&) = delete;
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
TOML_ALWAYS_INLINE
|
||||
TOML_PURE_INLINE_GETTER
|
||||
operator bool() const noexcept
|
||||
{
|
||||
return node_ != nullptr;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
TOML_ALWAYS_INLINE
|
||||
TOML_PURE_INLINE_GETTER
|
||||
node* get() const noexcept
|
||||
{
|
||||
return node_;
|
||||
@ -818,7 +814,7 @@ TOML_ANON_NAMESPACE_END;
|
||||
// They're all #undef'd at the bottom of the parser's implementation so they should be harmless outside
|
||||
// of toml++.
|
||||
|
||||
#if defined(NDEBUG) || !defined(_DEBUG)
|
||||
#ifdef NDEBUG
|
||||
#define assert_or_assume(cond) TOML_ASSUME(cond)
|
||||
#else
|
||||
#define assert_or_assume(cond) TOML_ASSERT(cond)
|
||||
@ -2576,16 +2572,26 @@ TOML_IMPL_NAMESPACE_START
|
||||
else if (has_any(has_x | has_o | has_b))
|
||||
{
|
||||
int64_t i;
|
||||
value_flags flags;
|
||||
if (has_any(has_x))
|
||||
i = parse_integer<16>();
|
||||
{
|
||||
i = parse_integer<16>();
|
||||
flags = value_flags::format_as_hexadecimal;
|
||||
}
|
||||
else if (has_any(has_o))
|
||||
i = parse_integer<8>();
|
||||
{
|
||||
i = parse_integer<8>();
|
||||
flags = value_flags::format_as_octal;
|
||||
}
|
||||
else // has_b
|
||||
i = parse_integer<2>();
|
||||
{
|
||||
i = parse_integer<2>();
|
||||
flags = value_flags::format_as_binary;
|
||||
}
|
||||
return_if_error({});
|
||||
|
||||
val = new value{ i };
|
||||
reinterpret_cast<value<int64_t>*>(val.get())->flags(value_flags::format_as_hexadecimal);
|
||||
reinterpret_cast<value<int64_t>*>(val.get())->flags(flags);
|
||||
}
|
||||
else if (has_any(has_e) || (has_any(begins_zero | begins_digit) && chars[1] == U'.'))
|
||||
val = new value{ parse_float() };
|
||||
|
@ -390,20 +390,12 @@
|
||||
#define TOML_ENABLE_PARSER 1
|
||||
#endif
|
||||
|
||||
// toml formatter
|
||||
#if !defined(TOML_ENABLE_TOML_FORMATTER) \
|
||||
|| (defined(TOML_ENABLE_TOML_FORMATTER) && TOML_ENABLE_TOML_FORMATTER) \
|
||||
// formatters
|
||||
#if !defined(TOML_ENABLE_FORMATTERS) \
|
||||
|| (defined(TOML_ENABLE_FORMATTERS) && TOML_ENABLE_FORMATTERS) \
|
||||
|| TOML_INTELLISENSE
|
||||
#undef TOML_ENABLE_TOML_FORMATTER
|
||||
#define TOML_ENABLE_TOML_FORMATTER 1
|
||||
#endif
|
||||
|
||||
// json formatter
|
||||
#if !defined(TOML_ENABLE_JSON_FORMATTER) \
|
||||
|| (defined(TOML_ENABLE_JSON_FORMATTER) && TOML_ENABLE_JSON_FORMATTER) \
|
||||
|| TOML_INTELLISENSE
|
||||
#undef TOML_ENABLE_JSON_FORMATTER
|
||||
#define TOML_ENABLE_JSON_FORMATTER 1
|
||||
#undef TOML_ENABLE_FORMATTERS
|
||||
#define TOML_ENABLE_FORMATTERS 1
|
||||
#endif
|
||||
|
||||
// windows compat
|
||||
@ -691,23 +683,17 @@
|
||||
#define TOML_EXTERN_NOEXCEPT(...) noexcept(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define TOML_PURE_GETTER \
|
||||
TOML_NODISCARD \
|
||||
TOML_ATTR(pure)
|
||||
|
||||
#define TOML_PURE_INLINE_GETTER \
|
||||
TOML_NODISCARD \
|
||||
TOML_ALWAYS_INLINE \
|
||||
TOML_ATTR(pure)
|
||||
|
||||
#define TOML_CONST_GETTER \
|
||||
TOML_NODISCARD \
|
||||
TOML_ATTR(const)
|
||||
|
||||
#define TOML_CONST_INLINE_GETTER \
|
||||
TOML_NODISCARD \
|
||||
TOML_ALWAYS_INLINE \
|
||||
TOML_ATTR(const)
|
||||
#ifdef NDEBUG
|
||||
#define TOML_PURE_GETTER TOML_NODISCARD TOML_ATTR(pure)
|
||||
#define TOML_CONST_GETTER TOML_NODISCARD TOML_ATTR(const)
|
||||
#define TOML_PURE_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE TOML_ATTR(pure)
|
||||
#define TOML_CONST_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE TOML_ATTR(const)
|
||||
#else
|
||||
#define TOML_PURE_GETTER TOML_NODISCARD
|
||||
#define TOML_CONST_GETTER TOML_NODISCARD
|
||||
#define TOML_PURE_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE
|
||||
#define TOML_CONST_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
//======================================================================================================================
|
||||
// SFINAE
|
||||
@ -721,10 +707,16 @@
|
||||
#endif
|
||||
#define TOML_ENABLE_IF(...) , typename std::enable_if<(__VA_ARGS__), int>::type = 0
|
||||
#define TOML_CONSTRAINED_TEMPLATE(condition, ...) template <__VA_ARGS__ TOML_ENABLE_IF(condition)> TOML_REQUIRES(condition)
|
||||
#define TOML_HIDDEN_CONSTRAINT(condition, ...) TOML_CONSTRAINED_TEMPLATE(condition, __VA_ARGS__)
|
||||
/// \endcond
|
||||
//# {{
|
||||
#ifndef TOML_CONSTRAINED_TEMPLATE
|
||||
#define TOML_CONSTRAINED_TEMPLATE(condition, ...) template <__VA_ARGS__>
|
||||
#endif
|
||||
#ifndef TOML_HIDDEN_CONSTRAINT
|
||||
#define TOML_HIDDEN_CONSTRAINT(condition, ...)
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
//#====================================================================================================================
|
||||
//# EXTENDED INT AND FLOAT TYPES
|
||||
@ -833,7 +825,7 @@
|
||||
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#ifndef TOML_ASSERT
|
||||
#if defined(NDEBUG) || !defined(_DEBUG)
|
||||
#ifdef NDEBUG
|
||||
#define TOML_ASSERT(expr) static_cast<void>(0)
|
||||
#else
|
||||
#ifndef assert
|
||||
@ -976,17 +968,15 @@ TOML_ENABLE_WARNINGS;
|
||||
/// to `0` can improve compilation speed and reduce binary size.
|
||||
|
||||
|
||||
/// \def TOML_ENABLE_TOML_FORMATTER
|
||||
/// \brief Sets whether the #toml::toml_formatter is enabled.
|
||||
/// \def TOML_ENABLE_FORMATTERS
|
||||
/// \brief Sets whether the various formatter classes are enabled.
|
||||
/// \detail Defaults to `1`.
|
||||
/// \remarks If you don't need to re-serialize TOML data, setting `TOML_ENABLE_TOML_FORMATTER`
|
||||
/// to `0` can improve compilation speed and reduce binary size.
|
||||
|
||||
/// \def TOML_ENABLE_JSON_FORMATTER
|
||||
/// \brief Sets whether the #toml::json_formatter is enabled.
|
||||
/// \detail Defaults to `1`.
|
||||
/// \remarks If you don't need to re-serialize TOML data as JSON, setting `TOML_ENABLE_JSON_FORMATTER`
|
||||
/// \remarks If you don't need to re-serialize TOML data, setting `TOML_ENABLE_FORMATTERS`
|
||||
/// to `0` can improve compilation speed and reduce binary size.
|
||||
/// \see
|
||||
/// - toml::toml_formatter
|
||||
/// - toml::json_formatter
|
||||
/// - toml::yaml_formatter
|
||||
|
||||
|
||||
#define TOML_SMALL_FLOAT_TYPE
|
||||
|
@ -80,7 +80,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const source_region&);
|
||||
|
||||
#if TOML_ENABLE_TOML_FORMATTER
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const array&);
|
||||
|
@ -77,6 +77,10 @@ TOML_ANON_NAMESPACE_START
|
||||
return;
|
||||
}
|
||||
|
||||
static constexpr auto value_flags_mask =
|
||||
value_flags::format_as_binary | value_flags::format_as_octal | value_flags::format_as_hexadecimal;
|
||||
format &= value_flags_mask;
|
||||
|
||||
int base = 10;
|
||||
if (format != value_flags::none && val >= T{})
|
||||
{
|
||||
@ -403,7 +407,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_TOML_FORMATTER
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const array& arr)
|
||||
|
@ -24,11 +24,6 @@ namespace toml // non-abi namespace; this is not an error
|
||||
{
|
||||
using namespace std::string_literals;
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
// legacy typedefs
|
||||
using string_char = char;
|
||||
using string = std::string;
|
||||
using string_view = std::string_view;
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
@ -1516,11 +1516,11 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// @}
|
||||
|
||||
#if TOML_ENABLE_TOML_FORMATTER
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
/// \brief Prints the table out to a stream as formatted TOML.
|
||||
///
|
||||
/// \availability This operator is only available when #TOML_ENABLE_TOML_FORMATTER is enabled.
|
||||
/// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled.
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const table& rhs)
|
||||
{
|
||||
impl::print_to_stream(lhs, rhs);
|
||||
|
@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
#if TOML_ENABLE_TOML_FORMATTER
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "formatter.h"
|
||||
#include "std_vector.h"
|
||||
@ -15,7 +15,7 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A wrapper for printing TOML objects out to a stream as formatted TOML.
|
||||
///
|
||||
/// \availability This class is only available when #TOML_ENABLE_TOML_FORMATTER is enabled.
|
||||
/// \availability This class is only available when #TOML_ENABLE_FORMATTERS is enabled.
|
||||
///
|
||||
/// \remarks You generally don't need to create an instance of this class explicitly; the stream
|
||||
/// operators of the TOML node types already print themselves out using this formatter.
|
||||
@ -31,7 +31,6 @@ TOML_NAMESPACE_START
|
||||
/// // these two lines are equivalent:
|
||||
/// std::cout << toml::toml_formatter{ tbl } << "\n";
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -51,16 +50,6 @@ TOML_NAMESPACE_START
|
||||
std::vector<std::string_view> key_path_;
|
||||
bool pending_table_separator_ = false;
|
||||
|
||||
static constexpr size_t line_wrap_cols = 120;
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
static size_t count_inline_columns(const node&) noexcept;
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
static bool forces_multiline(const node&, size_t = 0) noexcept;
|
||||
|
||||
TOML_API
|
||||
void print_pending_table_separator();
|
||||
|
||||
@ -82,17 +71,24 @@ TOML_NAMESPACE_START
|
||||
TOML_API
|
||||
void print();
|
||||
|
||||
static constexpr impl::formatter_constants constants = { "inf"sv, "-inf"sv, "nan"sv };
|
||||
static constexpr format_flags mandatory_flags = format_flags::none;
|
||||
static constexpr format_flags ignored_flags = format_flags::none;
|
||||
static constexpr impl::formatter_constants constants = { format_flags::none, // mandatory flags
|
||||
format_flags::none, // ignored flags
|
||||
"inf"sv,
|
||||
"-inf"sv,
|
||||
"nan"sv,
|
||||
"true"sv,
|
||||
"false"sv };
|
||||
|
||||
/// \endcond
|
||||
|
||||
public:
|
||||
/// \brief The default flags for a toml_formatter.
|
||||
static constexpr format_flags default_flags = format_flags::allow_literal_strings //
|
||||
| format_flags::allow_multi_line_strings //
|
||||
| format_flags::allow_value_format_flags //
|
||||
static constexpr format_flags default_flags = constants.mandatory_flags //
|
||||
| format_flags::allow_literal_strings //
|
||||
| format_flags::allow_multi_line_strings //
|
||||
| format_flags::allow_binary_integers //
|
||||
| format_flags::allow_octal_integers //
|
||||
| format_flags::allow_hexadecimal_integers //
|
||||
| format_flags::indentation;
|
||||
|
||||
/// \brief Constructs a TOML formatter and binds it to a TOML object.
|
||||
@ -101,7 +97,7 @@ TOML_NAMESPACE_START
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit toml_formatter(const toml::node& source, format_flags flags = default_flags) noexcept
|
||||
: base{ &source, nullptr, constants, { (flags | mandatory_flags) & ~ignored_flags, " "sv } }
|
||||
: base{ &source, nullptr, constants, { flags, " "sv } }
|
||||
{}
|
||||
|
||||
#if defined(DOXYGEN) || (TOML_ENABLE_PARSER && !TOML_EXCEPTIONS)
|
||||
@ -130,7 +126,7 @@ TOML_NAMESPACE_START
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit toml_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
|
||||
: base{ nullptr, &result, constants, { (flags | mandatory_flags) & ~ignored_flags, " "sv } }
|
||||
: base{ nullptr, &result, constants, { flags, " "sv } }
|
||||
{}
|
||||
|
||||
#endif
|
||||
@ -155,4 +151,4 @@ TOML_NAMESPACE_START
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_TOML_FORMATTER
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
||||
|
@ -10,7 +10,7 @@
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
#if TOML_ENABLE_TOML_FORMATTER
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "toml_formatter.h"
|
||||
#include "print_to_stream.h"
|
||||
@ -21,10 +21,10 @@
|
||||
#include "header_start.h"
|
||||
TOML_DISABLE_ARITHMETIC_WARNINGS;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
TOML_ANON_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
size_t toml_formatter::count_inline_columns(const node& node) noexcept
|
||||
TOML_INTERNAL_LINKAGE
|
||||
size_t toml_formatter_count_inline_columns(const node& node, size_t line_wrap_cols) noexcept
|
||||
{
|
||||
switch (node.type())
|
||||
{
|
||||
@ -36,7 +36,7 @@ TOML_NAMESPACE_START
|
||||
size_t weight = 3u; // "{ }"
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
weight += k.length() + count_inline_columns(v) + 2u; // + ", "
|
||||
weight += k.length() + toml_formatter_count_inline_columns(v, line_wrap_cols) + 2u; // + ", "
|
||||
if (weight >= line_wrap_cols)
|
||||
break;
|
||||
}
|
||||
@ -51,7 +51,7 @@ TOML_NAMESPACE_START
|
||||
size_t weight = 3u; // "[ ]"
|
||||
for (auto& elem : arr)
|
||||
{
|
||||
weight += count_inline_columns(elem) + 2u; // + ", "
|
||||
weight += toml_formatter_count_inline_columns(elem, line_wrap_cols) + 2u; // + ", "
|
||||
if (weight >= line_wrap_cols)
|
||||
break;
|
||||
}
|
||||
@ -106,12 +106,16 @@ TOML_NAMESPACE_START
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool toml_formatter::forces_multiline(const node& node, size_t starting_column_bias) noexcept
|
||||
TOML_INTERNAL_LINKAGE
|
||||
bool toml_formatter_forces_multiline(const node& node, size_t line_wrap_cols, size_t starting_column_bias) noexcept
|
||||
{
|
||||
return (count_inline_columns(node) + starting_column_bias) >= line_wrap_cols;
|
||||
return (toml_formatter_count_inline_columns(node, line_wrap_cols) + starting_column_bias) >= line_wrap_cols;
|
||||
}
|
||||
}
|
||||
TOML_ANON_NAMESPACE_END;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void toml_formatter::print_pending_table_separator()
|
||||
{
|
||||
@ -135,104 +139,107 @@ TOML_NAMESPACE_START
|
||||
for (const auto& segment : key_path_)
|
||||
{
|
||||
if (std::addressof(segment) > key_path_.data())
|
||||
impl::print_to_stream(base::stream(), '.');
|
||||
base::print_unformatted('.');
|
||||
print_key_segment(segment);
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void toml_formatter::print_inline(const table& tbl)
|
||||
{
|
||||
if (tbl.empty())
|
||||
impl::print_to_stream(base::stream(), "{}"sv);
|
||||
else
|
||||
{
|
||||
impl::print_to_stream(base::stream(), "{ "sv);
|
||||
|
||||
bool first = false;
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
if (first)
|
||||
impl::print_to_stream(base::stream(), ", "sv);
|
||||
first = true;
|
||||
|
||||
print_key_segment(k);
|
||||
impl::print_to_stream(base::stream(), " = "sv);
|
||||
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
|
||||
impl::print_to_stream(base::stream(), " }"sv);
|
||||
base::print_unformatted("{}"sv);
|
||||
return;
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
|
||||
base::print_unformatted("{ "sv);
|
||||
|
||||
bool first = false;
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
if (first)
|
||||
base::print_unformatted(", "sv);
|
||||
first = true;
|
||||
|
||||
print_key_segment(k);
|
||||
base::print_unformatted(" = "sv);
|
||||
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
|
||||
base::print_unformatted(" }"sv);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void toml_formatter::print(const array& arr)
|
||||
{
|
||||
if (arr.empty())
|
||||
impl::print_to_stream(base::stream(), "[]"sv);
|
||||
else
|
||||
{
|
||||
const auto original_indent = base::indent();
|
||||
const auto multiline = forces_multiline(
|
||||
arr,
|
||||
base::indent_columns() * static_cast<size_t>(original_indent < 0 ? 0 : original_indent));
|
||||
impl::print_to_stream(base::stream(), "["sv);
|
||||
base::print_unformatted("[]"sv);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto original_indent = base::indent();
|
||||
const auto multiline = TOML_ANON_NAMESPACE::toml_formatter_forces_multiline(
|
||||
arr,
|
||||
120u,
|
||||
base::indent_columns() * static_cast<size_t>(original_indent < 0 ? 0 : original_indent));
|
||||
|
||||
base::print_unformatted("["sv);
|
||||
|
||||
if (multiline)
|
||||
{
|
||||
if (original_indent < 0)
|
||||
base::indent(0);
|
||||
if (base::indent_array_elements())
|
||||
base::increase_indent();
|
||||
}
|
||||
else
|
||||
base::print_unformatted(' ');
|
||||
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
if (i > 0u)
|
||||
{
|
||||
base::print_unformatted(',');
|
||||
if (!multiline)
|
||||
base::print_unformatted(' ');
|
||||
}
|
||||
|
||||
if (multiline)
|
||||
{
|
||||
if (original_indent < 0)
|
||||
base::indent(0);
|
||||
if (base::indent_array_elements())
|
||||
base::increase_indent();
|
||||
}
|
||||
else
|
||||
impl::print_to_stream(base::stream(), ' ');
|
||||
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
if (i > 0u)
|
||||
{
|
||||
impl::print_to_stream(base::stream(), ',');
|
||||
if (!multiline)
|
||||
impl::print_to_stream(base::stream(), ' ');
|
||||
}
|
||||
|
||||
if (multiline)
|
||||
{
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
}
|
||||
|
||||
auto& v = arr[i];
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
if (multiline)
|
||||
{
|
||||
base::indent(original_indent);
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
}
|
||||
else
|
||||
impl::print_to_stream(base::stream(), ' ');
|
||||
impl::print_to_stream(base::stream(), "]"sv);
|
||||
|
||||
auto& v = arr[i];
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
if (multiline)
|
||||
{
|
||||
base::indent(original_indent);
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
}
|
||||
else
|
||||
base::print_unformatted(' ');
|
||||
|
||||
base::print_unformatted("]"sv);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
@ -256,7 +263,7 @@ TOML_NAMESPACE_START
|
||||
base::print_newline();
|
||||
base::print_indent();
|
||||
print_key_segment(k);
|
||||
impl::print_to_stream(base::stream(), " = "sv);
|
||||
base::print_unformatted(" = "sv);
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
@ -315,9 +322,9 @@ TOML_NAMESPACE_START
|
||||
if (base::indent_sub_tables())
|
||||
base::increase_indent();
|
||||
base::print_indent();
|
||||
impl::print_to_stream(base::stream(), "["sv);
|
||||
base::print_unformatted("["sv);
|
||||
print_key_path();
|
||||
impl::print_to_stream(base::stream(), "]"sv);
|
||||
base::print_unformatted("]"sv);
|
||||
pending_table_separator_ = true;
|
||||
}
|
||||
|
||||
@ -343,9 +350,9 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
print_pending_table_separator();
|
||||
base::print_indent();
|
||||
impl::print_to_stream(base::stream(), "[["sv);
|
||||
base::print_unformatted("[["sv);
|
||||
print_key_path();
|
||||
impl::print_to_stream(base::stream(), "]]"sv);
|
||||
base::print_unformatted("]]"sv);
|
||||
pending_table_separator_ = true;
|
||||
print(*reinterpret_cast<const table*>(&arr[i]));
|
||||
}
|
||||
@ -386,4 +393,4 @@ TOML_NAMESPACE_START
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_TOML_FORMATTER
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
||||
|
@ -2,12 +2,12 @@
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
#include "header_start.h"
|
||||
|
||||
/// \cond
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_CONST_GETTER
|
||||
@ -935,6 +935,6 @@ TOML_IMPL_NAMESPACE_START
|
||||
};
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
/// \endcond
|
||||
|
||||
/// \endcond
|
||||
#include "header_end.h"
|
||||
|
@ -154,8 +154,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
#endif // TOML_HAS_CHAR8 || TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
TOML_CONST_GETTER
|
||||
inline optional<T> node_integer_cast(int64_t val) noexcept
|
||||
{
|
||||
static_assert(node_type_of<T> == node_type::integer);
|
||||
@ -595,68 +594,88 @@ TOML_NAMESPACE_START
|
||||
/// @{
|
||||
|
||||
/// \brief Returns a reference to the underlying value.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
value_type& get() & noexcept
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
value_type&& get() && noexcept
|
||||
{
|
||||
return static_cast<value_type&&>(val_);
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (const overload).
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const value_type& get() const& noexcept
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
value_type& operator*() & noexcept
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
value_type&& operator*() && noexcept
|
||||
{
|
||||
return static_cast<value_type&&>(val_);
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (const overload).
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const value_type& operator*() const& noexcept
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
explicit operator value_type&() & noexcept
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
explicit operator value_type&&() && noexcept
|
||||
{
|
||||
return static_cast<value_type&&>(val_);
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (const overload).
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
explicit operator const value_type&() const& noexcept
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the underlying value.
|
||||
///
|
||||
/// \availability This operator is only available when #value_type is a class/struct.
|
||||
TOML_HIDDEN_CONSTRAINT(std::is_class_v<T>, typename T = value_type)
|
||||
TOML_PURE_INLINE_GETTER
|
||||
value_type* operator->() noexcept
|
||||
{
|
||||
return &val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the underlying value (const overload).
|
||||
///
|
||||
/// \availability This operator is only available when #value_type is a class/struct.
|
||||
TOML_HIDDEN_CONSTRAINT(std::is_class_v<T>, typename T = value_type)
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const value_type* operator->() const noexcept
|
||||
{
|
||||
return &val_;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Metadata
|
||||
@ -879,11 +898,11 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// @}
|
||||
|
||||
#if TOML_ENABLE_TOML_FORMATTER
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
/// \brief Prints the value out to a stream as formatted TOML.
|
||||
///
|
||||
/// \availability This operator is only available when #TOML_ENABLE_TOML_FORMATTER is enabled.
|
||||
/// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled.
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const value& rhs)
|
||||
{
|
||||
impl::print_to_stream(lhs, rhs);
|
||||
|
138
include/toml++/impl/yaml_formatter.h
Normal file
138
include/toml++/impl/yaml_formatter.h
Normal file
@ -0,0 +1,138 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "formatter.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A wrapper for printing TOML objects out to a stream as formatted YAML.
|
||||
///
|
||||
/// \availability This class is only available when #TOML_ENABLE_FORMATTERS is enabled.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto some_toml = toml::parse(R"(
|
||||
/// [fruit]
|
||||
/// apple.color = "red"
|
||||
/// apple.taste.sweet = true
|
||||
///
|
||||
/// [fruit.apple.texture]
|
||||
/// smooth = true
|
||||
/// )"sv);
|
||||
/// std::cout << toml::yaml_formatter{ some_toml } << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// fruit:
|
||||
/// apple:
|
||||
/// color: red
|
||||
/// taste:
|
||||
/// sweet: true
|
||||
/// texture:
|
||||
/// smooth: true
|
||||
/// \eout
|
||||
class yaml_formatter : impl::formatter
|
||||
{
|
||||
private:
|
||||
/// \cond
|
||||
|
||||
using base = impl::formatter;
|
||||
|
||||
TOML_API
|
||||
void print_yaml_string(const value<std::string>&);
|
||||
|
||||
TOML_API
|
||||
void print(const toml::table&, bool = false);
|
||||
|
||||
TOML_API
|
||||
void print(const toml::array&, bool = false);
|
||||
|
||||
TOML_API
|
||||
void print();
|
||||
|
||||
static constexpr impl::formatter_constants constants = {
|
||||
//
|
||||
format_flags::quote_dates_and_times | format_flags::indentation, // mandatory
|
||||
format_flags::allow_multi_line_strings, // ignored
|
||||
".inf"sv,
|
||||
"-.inf"sv,
|
||||
".NAN"sv,
|
||||
"true"sv,
|
||||
"false"sv
|
||||
};
|
||||
|
||||
/// \endcond
|
||||
|
||||
public:
|
||||
/// \brief The default flags for a yaml_formatter.
|
||||
static constexpr format_flags default_flags = constants.mandatory_flags //
|
||||
| format_flags::allow_literal_strings //
|
||||
| format_flags::allow_octal_integers //
|
||||
| format_flags::allow_hexadecimal_integers;
|
||||
|
||||
/// \brief Constructs a YAML formatter and binds it to a TOML object.
|
||||
///
|
||||
/// \param source The source TOML object.
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit yaml_formatter(const toml::node& source, format_flags flags = default_flags) noexcept
|
||||
: base{ &source, nullptr, constants, { flags, " "sv } }
|
||||
{}
|
||||
|
||||
#if defined(DOXYGEN) || (TOML_ENABLE_PARSER && !TOML_EXCEPTIONS)
|
||||
|
||||
/// \brief Constructs a YAML formatter and binds it to a toml::parse_result.
|
||||
///
|
||||
/// \availability This constructor is only available when exceptions are disabled.
|
||||
///
|
||||
/// \attention Formatting a failed parse result will simply dump the error message out as-is.
|
||||
/// This will not be valid YAML, but at least gives you something to log or show up in diagnostics:
|
||||
/// \cpp
|
||||
/// std::cout << toml::yaml_formatter{ toml::parse("a = 'b'"sv) } // ok
|
||||
/// << "\n\n"
|
||||
/// << toml::yaml_formatter{ toml::parse("a = "sv) } // malformed
|
||||
/// << "\n";
|
||||
/// \ecpp
|
||||
/// \out
|
||||
/// a: b
|
||||
///
|
||||
/// Error while parsing key-value pair: encountered end-of-file
|
||||
/// (error occurred at line 1, column 5)
|
||||
/// \eout
|
||||
/// Use the library with exceptions if you want to avoid this scenario.
|
||||
///
|
||||
/// \param result The parse result.
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit yaml_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
|
||||
: base{ nullptr, &result, constants, { flags, " "sv } }
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as YAML.
|
||||
friend std::ostream& operator<<(std::ostream& lhs, yaml_formatter& rhs)
|
||||
{
|
||||
rhs.attach(lhs);
|
||||
rhs.print();
|
||||
rhs.detach();
|
||||
return lhs;
|
||||
}
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as YAML (rvalue overload).
|
||||
friend std::ostream& operator<<(std::ostream& lhs, yaml_formatter&& rhs)
|
||||
{
|
||||
return lhs << rhs; // as lvalue
|
||||
}
|
||||
};
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
166
include/toml++/impl/yaml_formatter.inl
Normal file
166
include/toml++/impl/yaml_formatter.inl
Normal file
@ -0,0 +1,166 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
//# {{
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "yaml_formatter.h"
|
||||
#include "print_to_stream.h"
|
||||
#include "table.h"
|
||||
#include "array.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void yaml_formatter::print_yaml_string(const value<std::string>& str)
|
||||
{
|
||||
if (str->empty())
|
||||
{
|
||||
base::print(str);
|
||||
return;
|
||||
}
|
||||
|
||||
bool contains_newline = false;
|
||||
for (auto c = str->c_str(), e = str->c_str() + str->length(); c < e && !contains_newline; c++)
|
||||
contains_newline = *c == '\n';
|
||||
|
||||
if (contains_newline)
|
||||
{
|
||||
base::print_unformatted("|-"sv);
|
||||
|
||||
base::increase_indent();
|
||||
|
||||
auto line_end = str->c_str() - 1u;
|
||||
const auto end = str->c_str() + str->length();
|
||||
while (line_end != end)
|
||||
{
|
||||
auto line_start = line_end + 1u;
|
||||
line_end = line_start;
|
||||
for (; line_end != end && *line_end != '\n'; line_end++)
|
||||
;
|
||||
|
||||
if TOML_LIKELY(line_start != line_end || line_end != end)
|
||||
{
|
||||
base::print_newline();
|
||||
base::print_indent();
|
||||
base::print_unformatted(std::string_view{ line_start, static_cast<size_t>(line_end - line_start) });
|
||||
}
|
||||
}
|
||||
|
||||
base::decrease_indent();
|
||||
}
|
||||
else
|
||||
base::print_string(*str, false, true);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void yaml_formatter::print(const toml::table& tbl, bool parent_is_array)
|
||||
{
|
||||
if (tbl.empty())
|
||||
{
|
||||
base::print_unformatted("{}"sv);
|
||||
return;
|
||||
}
|
||||
|
||||
base::increase_indent();
|
||||
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
if (!parent_is_array)
|
||||
{
|
||||
base::print_newline();
|
||||
base::print_indent();
|
||||
}
|
||||
parent_is_array = false;
|
||||
|
||||
base::print_string(k, false, true);
|
||||
base::print_unformatted(": "sv);
|
||||
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
case node_type::string: print_yaml_string(*reinterpret_cast<const value<std::string>*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
|
||||
base::decrease_indent();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void yaml_formatter::print(const toml::array& arr, bool parent_is_array)
|
||||
{
|
||||
if (arr.empty())
|
||||
{
|
||||
base::print_unformatted("[]"sv);
|
||||
return;
|
||||
}
|
||||
|
||||
base::increase_indent();
|
||||
|
||||
for (auto&& v : arr)
|
||||
{
|
||||
if (!parent_is_array)
|
||||
{
|
||||
base::print_newline();
|
||||
base::print_indent();
|
||||
}
|
||||
parent_is_array = false;
|
||||
|
||||
base::print_unformatted("- "sv);
|
||||
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v), true); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v), true); break;
|
||||
case node_type::string: print_yaml_string(*reinterpret_cast<const value<std::string>*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
|
||||
base::print_newline();
|
||||
}
|
||||
|
||||
base::decrease_indent();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void yaml_formatter::print()
|
||||
{
|
||||
if (base::dump_failed_parse_result())
|
||||
return;
|
||||
|
||||
switch (auto source_type = base::source().type())
|
||||
{
|
||||
case node_type::table:
|
||||
base::decrease_indent(); // so root kvps and tables have the same indent
|
||||
print(*reinterpret_cast<const table*>(&base::source()));
|
||||
break;
|
||||
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&base::source())); break;
|
||||
|
||||
case node_type::string:
|
||||
print_yaml_string(*reinterpret_cast<const value<std::string>*>(&base::source()));
|
||||
break;
|
||||
|
||||
default: base::print_value(base::source(), source_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
@ -41,6 +41,7 @@ TOML_DISABLE_SWITCH_WARNINGS;
|
||||
#include "impl/formatter.h"
|
||||
#include "impl/toml_formatter.h"
|
||||
#include "impl/json_formatter.h"
|
||||
#include "impl/yaml_formatter.h"
|
||||
|
||||
#if TOML_IMPLEMENTATION
|
||||
|
||||
@ -55,6 +56,7 @@ TOML_DISABLE_SWITCH_WARNINGS;
|
||||
#include "impl/formatter.inl"
|
||||
#include "impl/toml_formatter.inl"
|
||||
#include "impl/json_formatter.inl"
|
||||
#include "impl/yaml_formatter.inl"
|
||||
|
||||
#endif // TOML_IMPLEMENTATION
|
||||
|
||||
@ -107,6 +109,7 @@ TOML_POP_WARNINGS;
|
||||
#undef TOML_HAS_CHAR8
|
||||
#undef TOML_HAS_CUSTOM_OPTIONAL_TYPE
|
||||
#undef TOML_HAS_INCLUDE
|
||||
#undef TOML_HIDDEN_CONSTRAINT
|
||||
#undef TOML_ICC
|
||||
#undef TOML_ICC_CL
|
||||
#undef TOML_IMPL_NAMESPACE_END
|
||||
|
@ -122,14 +122,14 @@ if is_gcc
|
||||
'-Wvariadic-macros',
|
||||
'-Wwrite-strings',
|
||||
'-Wmissing-noreturn',
|
||||
'-Wsuggest-attribute=const',
|
||||
'-Wsuggest-attribute=pure',
|
||||
language: 'cpp'
|
||||
)
|
||||
endif
|
||||
if is_release
|
||||
add_project_arguments(
|
||||
'-fmerge-constants',
|
||||
'-Wsuggest-attribute=const',
|
||||
'-Wsuggest-attribute=pure',
|
||||
language: 'cpp'
|
||||
)
|
||||
endif
|
||||
|
@ -102,55 +102,59 @@ namespace
|
||||
|
||||
TEST_CASE("formatters")
|
||||
{
|
||||
const auto data = toml::table{
|
||||
{ "integers"sv,
|
||||
toml::table{ { "zero"sv, 0 },
|
||||
{ "one"sv, 1 },
|
||||
{ "dec"sv, 10 },
|
||||
{ "bin"sv, 10, toml::value_flags::format_as_binary },
|
||||
{ "oct"sv, 10, toml::value_flags::format_as_octal },
|
||||
{ "hex"sv, 10, toml::value_flags::format_as_hexadecimal } } },
|
||||
{ "floats"sv,
|
||||
toml::table{ { "pos_zero"sv, +0.0 },
|
||||
{ "neg_zero"sv, -0.0 },
|
||||
{ "one"sv, 1.0 },
|
||||
{ "pos_inf"sv, +std::numeric_limits<double>::infinity() },
|
||||
{ "neg_inf"sv, -std::numeric_limits<double>::infinity() },
|
||||
{ "pos_nan"sv, +std::numeric_limits<double>::quiet_NaN() },
|
||||
{ "neg_nan"sv, -std::numeric_limits<double>::quiet_NaN() }
|
||||
const auto data_date = toml::date{ 2021, 11, 2 };
|
||||
const auto data_time = toml::time{ 20, 33, 0 };
|
||||
const auto data = toml::table{
|
||||
{ "integers"sv,
|
||||
toml::table{ { "zero"sv, 0 },
|
||||
{ "one"sv, 1 },
|
||||
{ "dec"sv, 10 },
|
||||
{ "bin"sv, 10, toml::value_flags::format_as_binary },
|
||||
{ "oct"sv, 10, toml::value_flags::format_as_octal },
|
||||
{ "hex"sv, 10, toml::value_flags::format_as_hexadecimal } } },
|
||||
{ "floats"sv,
|
||||
toml::table{ { "pos_zero"sv, +0.0 },
|
||||
{ "neg_zero"sv, -0.0 },
|
||||
{ "one"sv, 1.0 },
|
||||
{ "pos_inf"sv, +std::numeric_limits<double>::infinity() },
|
||||
{ "neg_inf"sv, -std::numeric_limits<double>::infinity() },
|
||||
{ "pos_nan"sv, +std::numeric_limits<double>::quiet_NaN() },
|
||||
{ "neg_nan"sv, -std::numeric_limits<double>::quiet_NaN() }
|
||||
|
||||
} },
|
||||
} },
|
||||
|
||||
{ "dates and times"sv,
|
||||
toml::table{
|
||||
{ "dates and times"sv,
|
||||
toml::table{
|
||||
|
||||
{ "dates"sv, toml::table{ { "zero"sv, toml::date{} } } },
|
||||
{ "dates"sv, toml::table{ { "val"sv, data_date } } },
|
||||
|
||||
{ "times"sv, toml::table{ { "zero"sv, toml::time{} } } },
|
||||
{ "times"sv, toml::table{ { "val"sv, data_time } } },
|
||||
|
||||
{ "date-times"sv,
|
||||
toml::table{
|
||||
{ "date-times"sv,
|
||||
toml::table{
|
||||
|
||||
{ "local"sv, toml::table{ { "zero"sv, toml::date_time{} } } },
|
||||
{ "offset"sv, toml::table{ { "zero"sv, toml::date_time{ {}, {}, toml::time_offset{} } } } } } } } },
|
||||
{ "local"sv, toml::table{ { "val"sv, toml::date_time{ data_date, data_time } } } },
|
||||
{ "offset"sv,
|
||||
toml::table{
|
||||
{ "val"sv, toml::date_time{ data_date, data_time, toml::time_offset{} } } } } } } } },
|
||||
|
||||
{ "bools"sv,
|
||||
toml::table{ { "true"sv, true }, //
|
||||
{ "false"sv, false } } },
|
||||
{ "bools"sv,
|
||||
toml::table{ { "true"sv, true }, //
|
||||
{ "false"sv, false } } },
|
||||
|
||||
{
|
||||
"strings"sv,
|
||||
toml::array{ R"()"sv,
|
||||
R"(string)"sv,
|
||||
R"(string with a single quote in it: ')"sv,
|
||||
R"(string with a double quote in it: ")"sv,
|
||||
"string with a tab: \t"sv,
|
||||
R"(a long string to force the array over multiple lines)"sv },
|
||||
},
|
||||
{
|
||||
"strings"sv,
|
||||
toml::array{ R"()"sv,
|
||||
R"(string)"sv,
|
||||
R"(string with a single quote in it: ')"sv,
|
||||
R"(string with a double quote in it: ")"sv,
|
||||
"string with a tab: \t"sv,
|
||||
R"(a long string to force the array over multiple lines)"sv },
|
||||
},
|
||||
|
||||
{ "a"sv,
|
||||
toml::table{ { "val", true },
|
||||
{ "b"sv, toml::table{ { "val", true }, { "c"sv, toml::table{ { "val", true } } } } } } }
|
||||
{ "a"sv,
|
||||
toml::table{ { "val", true },
|
||||
{ "b"sv, toml::table{ { "val", true }, { "c"sv, toml::table{ { "val", true } } } } } } }
|
||||
|
||||
};
|
||||
|
||||
@ -180,16 +184,16 @@ false = false
|
||||
true = true
|
||||
|
||||
['dates and times'.date-times.local]
|
||||
zero = 0000-00-00T00:00:00
|
||||
val = 2021-11-02T20:33:00
|
||||
|
||||
['dates and times'.date-times.offset]
|
||||
zero = 0000-00-00T00:00:00Z
|
||||
val = 2021-11-02T20:33:00Z
|
||||
|
||||
['dates and times'.dates]
|
||||
zero = 0000-00-00
|
||||
val = 2021-11-02
|
||||
|
||||
['dates and times'.times]
|
||||
zero = 00:00:00
|
||||
val = 20:33:00
|
||||
|
||||
[floats]
|
||||
neg_inf = -inf
|
||||
@ -232,17 +236,17 @@ zero = 0
|
||||
"dates and times" : {
|
||||
"date-times" : {
|
||||
"local" : {
|
||||
"zero" : "0000-00-00T00:00:00"
|
||||
"val" : "2021-11-02T20:33:00"
|
||||
},
|
||||
"offset" : {
|
||||
"zero" : "0000-00-00T00:00:00Z"
|
||||
"val" : "2021-11-02T20:33:00Z"
|
||||
}
|
||||
},
|
||||
"dates" : {
|
||||
"zero" : "0000-00-00"
|
||||
"val" : "2021-11-02"
|
||||
},
|
||||
"times" : {
|
||||
"zero" : "00:00:00"
|
||||
"val" : "20:33:00"
|
||||
}
|
||||
},
|
||||
"floats" : {
|
||||
|
@ -75,6 +75,7 @@
|
||||
<ClInclude Include="include\toml++\impl\value_extern.inl" />
|
||||
<ClInclude Include="include\toml++\impl\version.h" />
|
||||
<ClInclude Include="include\toml++\impl\std_string.inl" />
|
||||
<ClInclude Include="include\toml++\impl\yaml_formatter.h" />
|
||||
<ClInclude Include="include\toml++\toml.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -91,6 +92,7 @@
|
||||
<None Include="CODE_OF_CONDUCT.md" />
|
||||
<None Include="CONTRIBUTING.md" />
|
||||
<None Include="include\toml++\impl\node_view_extern.inl" />
|
||||
<None Include="include\toml++\impl\yaml_formatter.inl" />
|
||||
<None Include="LICENSE" />
|
||||
<None Include="README.md" />
|
||||
<None Include="cmake\install-rules.cmake" />
|
||||
|
@ -124,6 +124,9 @@
|
||||
<ClInclude Include="include\toml++\impl\value_extern.inl">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\impl\yaml_formatter.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="toml++.props" />
|
||||
@ -195,6 +198,9 @@
|
||||
<None Include=".github\ISSUE_TEMPLATE\feature_request.md">
|
||||
<Filter>.github</Filter>
|
||||
</None>
|
||||
<None Include="include\toml++\impl\yaml_formatter.inl">
|
||||
<Filter>include\impl</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include=".circleci">
|
||||
|
@ -203,8 +203,7 @@ def main():
|
||||
r'TOML_MAX_NESTED_VALUES',
|
||||
r'TOML_OPTIONAL_TYPE',
|
||||
r'TOML_ENABLE_PARSER',
|
||||
r'TOML_ENABLE_TOML_FORMATTER',
|
||||
r'TOML_ENABLE_JSON_FORMATTER',
|
||||
r'TOML_ENABLE_FORMATTERS',
|
||||
r'TOML_SMALL_FLOAT_TYPE',
|
||||
r'TOML_SMALL_INT_TYPE',
|
||||
r'TOML_UNDEF_MACROS',
|
||||
|
Loading…
Reference in New Issue
Block a user