fixed some multi-line string parsing issues

also:
- fixed pedantic warnings on gcc 10 and clang 11
This commit is contained in:
Mark Gillard 2020-04-13 23:23:11 +03:00
parent 42af364887
commit cd9b3d2198
30 changed files with 673 additions and 232 deletions

43
.gitattributes vendored
View File

@ -1,21 +1,22 @@
* text=auto encoding=UTF-8
*.c text encoding=UTF-8 eol=lf
*.cpp text encoding=UTF-8 eol=lf
*.cxx text encoding=UTF-8 eol=lf
*.h text encoding=UTF-8 eol=lf
*.hpp text encoding=UTF-8 eol=lf
*.hxx text encoding=UTF-8 eol=lf
*.inl text encoding=UTF-8 eol=lf
*.toml text=auto encoding=UTF-8
*.xml text=auto encoding=UTF-8
*.py text encoding=UTF-8 eol=lf
*.natvis text encoding=UTF-8 eol=crlf
*.props text encoding=UTF-8 eol=crlf
*.vcxproj text encoding=UTF-8 eol=crlf
*.sln text encoding=UTF-8-BOM eol=crlf
*.runsettings text encoding=UTF-8 eol=crlf
*.md text encoding=UTF-8 eol=lf
*.css text encoding=UTF-8 eol=lf
meson.build text encoding=UTF-8 eol=lf
Doxyfile text encoding=UTF-8 eol=lf
Doxyfile-mcss text encoding=UTF-8 eol=lf
* text=auto encoding=UTF-8
*.c text encoding=UTF-8 eol=lf
*.cpp text encoding=UTF-8 eol=lf
*.cxx text encoding=UTF-8 eol=lf
*.h text encoding=UTF-8 eol=lf
*.hpp text encoding=UTF-8 eol=lf
*.hxx text encoding=UTF-8 eol=lf
*.inl text encoding=UTF-8 eol=lf
*.toml text=auto encoding=UTF-8
*.xml text=auto encoding=UTF-8
*.py text encoding=UTF-8 eol=lf
*.natvis text encoding=UTF-8 eol=crlf
*.props text encoding=UTF-8 eol=crlf
*.vcxproj text encoding=UTF-8 eol=crlf
*.sln text encoding=UTF-8-BOM eol=crlf
*.runsettings text encoding=UTF-8 eol=crlf
*.md text encoding=UTF-8 eol=lf
*.css text encoding=UTF-8 eol=lf
meson.build text encoding=UTF-8 eol=lf
meson_options.txt text encoding=UTF-8 eol=lf
Doxyfile text encoding=UTF-8 eol=lf
Doxyfile-mcss text encoding=UTF-8 eol=lf

View File

@ -360,6 +360,9 @@ PREDEFINED = TOML_DOXYGEN=1 \
TOML_DISABLE_SWITCH_WARNINGS= \
TOML_DISABLE_INIT_WARNINGS= \
TOML_DISABLE_VTABLE_WARNINGS= \
TOML_DISABLE_PADDING_WARNINGS= \
TOML_DISABLE_FLOAT_WARNINGS= \
TOML_DISABLE_SHADOW_WARNINGS= \
TOML_DISABLE_ALL_WARNINGS= \
TOML_POP_WARNINGS= \
__has_include(x)=0 \

View File

@ -55,6 +55,8 @@
#undef TOML_DISABLE_SWITCH_WARNINGS
#undef TOML_DISABLE_INIT_WARNINGS
#undef TOML_DISABLE_VTABLE_WARNINGS
#undef TOML_DISABLE_PADDING_WARNINGS
#undef TOML_DISABLE_FLOAT_WARNINGS
#undef TOML_DISABLE_ALL_WARNINGS
#undef TOML_POP_WARNINGS
#undef TOML_ALWAYS_INLINE

View File

@ -80,6 +80,10 @@ namespace toml
#endif
TOML_PUSH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
TOML_DISABLE_SHADOW_WARNINGS // false positive on gcc
#if !TOML_DOXYGEN
// foward declarations are hidden from doxygen
@ -122,6 +126,8 @@ namespace toml
date_time ///< The node is a toml::value<date_time>.
};
TOML_POP_WARNINGS // TOML_DISABLE_PADDING_WARNINGS, TOML_DISABLE_SHADOW_WARNINGS
#ifdef TOML_OPTIONAL_TYPE
template <typename T>

View File

@ -6,6 +6,9 @@
#pragma once
#include "toml_common.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml
{
/// \brief A local date.
@ -431,3 +434,4 @@ namespace toml
#endif
}
TOML_POP_WARNINGS // TOML_DISABLE_PADDING_WARNINGS

View File

@ -9,6 +9,10 @@
#include "toml_array.h"
#include "toml_utf8.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml::impl
{
[[nodiscard]] TOML_API
@ -21,7 +25,6 @@ namespace toml::impl
bool default_formatter_forces_multiline(const node& node, size_t starting_column_bias = 0) noexcept;
}
namespace toml
{
template <typename T, typename U>
@ -143,12 +146,13 @@ namespace toml
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(v, type);
base::print_value(v, type);
}
}
@ -187,12 +191,13 @@ namespace toml
base::print_indent();
print_key_segment(k);
impl::print_to_stream(" = "sv, base::stream());
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(v, type);
base::print_value(v, type);
}
}
@ -213,6 +218,7 @@ namespace toml
{
(void)child_k;
const auto child_type = child_v.type();
TOML_ASSUME(child_type != node_type::none);
switch (child_type)
{
case node_type::table:
@ -308,7 +314,7 @@ namespace toml
break;
default:
base::print(base::source(), source_type);
base::print_value(base::source(), source_type);
}
}
@ -357,12 +363,13 @@ namespace toml
impl::print_to_stream(" = "sv, base::stream());
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(v, type);
base::print_value(v, type);
}
}
@ -413,3 +420,4 @@ namespace toml
#endif
}
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_PADDING_WARNINGS

View File

@ -12,6 +12,10 @@
#endif
//# }}
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_FLOAT_WARNINGS
namespace toml::impl
{
TOML_PUSH_WARNINGS
@ -133,6 +137,7 @@ namespace toml::impl
case node_type::date: [[fallthrough]];
case node_type::time: return 10_sz;
case node_type::date_time: return 30_sz;
case node_type::none: TOML_UNREACHABLE;
TOML_NO_DEFAULT_CASE;
}
@ -147,6 +152,8 @@ namespace toml::impl
}
}
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_FLOAT_WARNINGS
//# {{
#endif // !TOML_DOXYGEN
//# }}

View File

@ -6,6 +6,10 @@
#pragma once
#include "toml_print_to_stream.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml
{
/// \brief Format flags for modifying how TOML data is printed to streams.
@ -14,17 +18,24 @@ namespace toml
none,
quote_dates_and_times = 1
};
[[nodiscard]] constexpr format_flags operator & (format_flags lhs, format_flags rhs) noexcept
[[nodiscard]]
TOML_GNU_ATTR(const)
TOML_ALWAYS_INLINE
constexpr format_flags operator & (format_flags lhs, format_flags rhs) noexcept
{
return static_cast<format_flags>(impl::unbox_enum(lhs) & impl::unbox_enum(rhs));
}
[[nodiscard]] constexpr format_flags operator | (format_flags lhs, format_flags rhs) noexcept
[[nodiscard]]
TOML_GNU_ATTR(const)
TOML_ALWAYS_INLINE
constexpr format_flags operator | (format_flags lhs, format_flags rhs) noexcept
{
return static_cast<format_flags>( impl::unbox_enum(lhs) | impl::unbox_enum(rhs) );
}
}
namespace toml::impl
{
template <typename Char = char>
@ -127,8 +138,9 @@ namespace toml::impl
}
}
void print(const node& val_node, node_type type)
void print_value(const node& val_node, node_type type)
{
TOML_ASSUME(type > node_type::array);
switch (type)
{
case node_type::string: print(*reinterpret_cast<const value<string>*>(&val_node)); break;
@ -153,3 +165,4 @@ namespace toml::impl
#endif
}
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_PADDING_WARNINGS

View File

@ -6,6 +6,10 @@
#pragma once
#include "toml_formatter.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml
{
template <typename T, typename U>
@ -70,12 +74,13 @@ namespace toml
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(v, type);
base::print_value(v, type);
}
}
@ -93,7 +98,7 @@ namespace toml
{
case node_type::table: print(*reinterpret_cast<const table*>(&base::source())); break;
case node_type::array: print(*reinterpret_cast<const array*>(&base::source())); break;
default: base::print(base::source(), source_type);
default: base::print_value(base::source(), source_type);
}
}
@ -144,12 +149,13 @@ namespace toml
impl::print_to_stream(" : "sv, base::stream());
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(v, type);
base::print_value(v, type);
}
}
@ -186,3 +192,4 @@ namespace toml
#endif
}
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_PADDING_WARNINGS

View File

@ -385,6 +385,7 @@ namespace toml
return std::forward<Func>(visitor)(std::forward<N>(n).template ref_cast<date_time>());
break;
case node_type::none: TOML_UNREACHABLE;
TOML_NO_DEFAULT_CASE;
}

View File

@ -10,6 +10,9 @@
namespace toml
{
TOML_PUSH_WARNINGS
TOML_DISABLE_FLOAT_WARNINGS
template <typename Char, typename T>
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>&, const node_view<T>&);
@ -373,5 +376,7 @@ namespace toml
extern template TOML_API std::ostream& operator << (std::ostream&, const node_view<node>&);
extern template TOML_API std::ostream& operator << (std::ostream&, const node_view<const node>&);
#endif
TOML_POP_WARNINGS // TOML_DISABLE_FLOAT_WARNINGS
}

View File

@ -13,6 +13,9 @@
#include "toml_table.h"
#include "toml_utf8_streams.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml
{
#if TOML_DOXYGEN || !TOML_EXCEPTIONS
@ -607,3 +610,4 @@ namespace toml
}
}
TOML_POP_WARNINGS // TOML_DISABLE_PADDING_WARNINGS

View File

@ -25,6 +25,10 @@ TOML_DISABLE_ALL_WARNINGS
#endif
TOML_POP_WARNINGS
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace TOML_INTERNAL_NAMESPACE
{
template <uint64_t> struct parse_integer_traits;
@ -160,6 +164,17 @@ namespace TOML_INTERNAL_NAMESPACE
#define push_parse_scope_2(desc, line) scope_stack.push_back(desc); parse_scope ps_##line{ scope_stack }
#define push_parse_scope_1(desc, line) push_parse_scope_2(desc, line)
#define push_parse_scope(desc) push_parse_scope_1(desc, __LINE__)
struct parsed_key final
{
std::vector<toml::string> segments;
};
struct parsed_key_value_pair final
{
parsed_key key;
std::unique_ptr<toml::node> value;
};
}
namespace toml::impl
@ -498,10 +513,18 @@ namespace toml::impl
// skip the '"'
advance_and_return_if_error_or_eof({});
// multiline strings ignore a single line ending right at the beginning
if constexpr (MultiLine)
{
consume_line_break();
return_if_error({});
set_error_and_return_if_eof({});
}
string str;
bool escaped = false;
[[maybe_unused]] bool skipping_whitespace = false;
while (!is_eof())
do
{
if (escaped)
{
@ -601,32 +624,49 @@ namespace toml::impl
{
if constexpr (MultiLine)
{
advance_and_return_if_error_or_eof({});
const auto second = cp->value;
advance_and_return_if_error_or_eof({});
const auto third = cp->value;
if (second == U'"' && third == U'"')
size_t lookaheads = {};
size_t consecutive_delimiters = 1_sz;
do
{
advance_and_return_if_error({}); // skip the third closing delimiter
//multi-line basic strings are allowed one additional terminating '"'
//so that things like this work: """this is a "quote""""
advance_and_return_if_error({});
lookaheads++;
if (!is_eof() && *cp == U'"')
{
str += TOML_STRING_PREFIX('"');
advance_and_return_if_error({}); // skip the final closing delimiter
}
return str;
consecutive_delimiters++;
else
break;
}
else
while (lookaheads < 4_sz);
switch (consecutive_delimiters)
{
str += TOML_STRING_PREFIX('"');
go_back(1_sz);
skipping_whitespace = false;
continue;
// """ " (one quote somewhere in a ML string)
case 1_sz:
str += TOML_STRING_PREFIX('"');
skipping_whitespace = false;
continue;
// """ "" (two quotes somewhere in a ML string)
case 2_sz:
str.append(TOML_STRING_PREFIX("\"\""sv));
skipping_whitespace = false;
continue;
// """ """ (the end of the string)
case 3_sz:
return str;
// """ """" (one at the end of the string)
case 4_sz:
str += TOML_STRING_PREFIX('"');
return str;
// """ """"" (two quotes at the end of the string)
case 5_sz:
str.append(TOML_STRING_PREFIX("\"\""sv));
advance_and_return_if_error({}); // skip the last '"'
return str;
TOML_NO_DEFAULT_CASE;
}
}
else
@ -652,7 +692,7 @@ namespace toml::impl
{
consume_line_break();
return_if_error({});
if (!str.empty() && !skipping_whitespace)
if (!skipping_whitespace)
str += TOML_STRING_PREFIX('\n');
continue;
}
@ -687,6 +727,7 @@ namespace toml::impl
advance_and_return_if_error({});
}
}
while (!is_eof());
set_error_and_return_default("encountered end-of-file"sv);
}
@ -703,8 +744,16 @@ namespace toml::impl
// skip the delimiter
advance_and_return_if_error_or_eof({});
// multiline strings ignore a single line ending right at the beginning
if constexpr (MultiLine)
{
consume_line_break();
return_if_error({});
set_error_and_return_if_eof({});
}
string str;
while (!is_eof())
do
{
assert_not_error();
@ -713,22 +762,47 @@ namespace toml::impl
{
if constexpr (MultiLine)
{
advance_and_return_if_error_or_eof({});
const auto second = cp->value;
advance_and_return_if_error_or_eof({});
const auto third = cp->value;
if (second == U'\'' && third == U'\'')
size_t lookaheads = {};
size_t consecutive_delimiters = 1_sz;
do
{
advance_and_return_if_error({}); // skip the third closing delimiter
return str;
advance_and_return_if_error({});
lookaheads++;
if (!is_eof() && *cp == U'\'')
consecutive_delimiters++;
else
break;
}
else
while (lookaheads < 4_sz);
switch (consecutive_delimiters)
{
str += TOML_STRING_PREFIX('\'');
go_back(1_sz);
continue;
// ''' ' (one quote somewhere in a ML string)
case 1_sz:
str += TOML_STRING_PREFIX('\'');
continue;
// ''' '' (two quotes somewhere in a ML string)
case 2_sz:
str.append(TOML_STRING_PREFIX("''"sv));
continue;
// ''' ''' (the end of the string)
case 3_sz:
return str;
// ''' '''' (one at the end of the string)
case 4_sz:
str += TOML_STRING_PREFIX('\'');
return str;
// ''' ''''' (two quotes at the end of the string)
case 5_sz:
str.append(TOML_STRING_PREFIX("''"sv));
advance_and_return_if_error({}); // skip the last '
return str;
TOML_NO_DEFAULT_CASE;
}
}
else
@ -744,8 +818,7 @@ namespace toml::impl
if (is_line_break(*cp))
{
consume_line_break();
if (!str.empty())
str += TOML_STRING_PREFIX('\n');
str += TOML_STRING_PREFIX('\n');
continue;
}
}
@ -768,6 +841,7 @@ namespace toml::impl
str.append(cp->as_view());
advance_and_return_if_error({});
}
while (!is_eof());
set_error_and_return_default("encountered end-of-file"sv);
}
@ -2041,20 +2115,15 @@ namespace toml::impl
return val;
}
struct key final
{
std::vector<string> segments;
};
[[nodiscard]]
key parse_key() TOML_MAY_THROW
parsed_key parse_key() TOML_MAY_THROW
{
return_if_error({});
assert_not_eof();
assert_or_assume(is_bare_key_character(*cp) || is_string_delimiter(*cp));
push_parse_scope("key"sv);
key key;
parsed_key key;
while (!is_error())
{
@ -2100,14 +2169,8 @@ namespace toml::impl
return key;
}
struct key_value_pair final
{
parser::key key;
std::unique_ptr<node> value;
};
[[nodiscard]]
key_value_pair parse_key_value_pair() TOML_MAY_THROW
parsed_key_value_pair parse_key_value_pair() TOML_MAY_THROW
{
return_if_error({});
assert_not_eof();
@ -2148,7 +2211,7 @@ namespace toml::impl
const auto header_begin_pos = cp->position;
source_position header_end_pos;
key key;
parsed_key key;
bool is_arr = false;
//parse header
@ -2749,6 +2812,8 @@ namespace toml
}
}
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_PADDING_WARNINGS
//# {{
#endif // !TOML_DOXYGEN
//# }}

View File

@ -63,6 +63,10 @@
#define TOML_DISABLE_INIT_WARNINGS _Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"")
#define TOML_DISABLE_VTABLE_WARNINGS _Pragma("clang diagnostic ignored \"-Weverything\"") \
_Pragma("clang diagnostic ignored \"-Wweak-vtables\"")
#define TOML_DISABLE_PADDING_WARNINGS _Pragma("clang diagnostic ignored \"-Wpadded\"")
#define TOML_DISABLE_FLOAT_WARNINGS _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \
_Pragma("clang diagnostic ignored \"-Wdouble-promotion\"")
#define TOML_DISABLE_SHADOW_WARNINGS _Pragma("clang diagnostic ignored \"-Wshadow\"")
#define TOML_DISABLE_ALL_WARNINGS _Pragma("clang diagnostic ignored \"-Weverything\"")
#define TOML_POP_WARNINGS _Pragma("clang diagnostic pop")
#define TOML_ASSUME(cond) __builtin_assume(cond)
@ -123,14 +127,25 @@
#elif defined(__GNUC__)
#define TOML_PUSH_WARNINGS _Pragma("GCC diagnostic push")
#define TOML_DISABLE_SWITCH_WARNINGS _Pragma("GCC diagnostic ignored \"-Wswitch\"")
#define TOML_DISABLE_SWITCH_WARNINGS _Pragma("GCC diagnostic ignored \"-Wswitch\"") \
_Pragma("GCC diagnostic ignored \"-Wswitch-enum\"") \
_Pragma("GCC diagnostic ignored \"-Wswitch-default\"")
#define TOML_DISABLE_INIT_WARNINGS _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") \
_Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") \
_Pragma("GCC diagnostic ignored \"-Wuninitialized\"")
#define TOML_DISABLE_PADDING_WARNINGS _Pragma("GCC diagnostic ignored \"-Wpadded\"")
#define TOML_DISABLE_FLOAT_WARNINGS _Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
#define TOML_DISABLE_SHADOW_WARNINGS _Pragma("GCC diagnostic ignored \"-Wshadow\"")
#define TOML_DISABLE_ALL_WARNINGS _Pragma("GCC diagnostic ignored \"-Wall\"") \
_Pragma("GCC diagnostic ignored \"-Wextra\"") \
_Pragma("GCC diagnostic ignored \"-Wchar-subscripts\"") \
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"")
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"") \
TOML_DISABLE_SWITCH_WARNINGS \
TOML_DISABLE_INIT_WARNINGS \
TOML_DISABLE_PADDING_WARNINGS \
TOML_DISABLE_FLOAT_WARNINGS \
TOML_DISABLE_SHADOW_WARNINGS
#define TOML_POP_WARNINGS _Pragma("GCC diagnostic pop")
#define TOML_GNU_ATTR(...) __attribute__((__VA_ARGS__))
#define TOML_ALWAYS_INLINE __attribute__((__always_inline__)) inline
@ -219,6 +234,15 @@
#ifndef TOML_DISABLE_VTABLE_WARNINGS
#define TOML_DISABLE_VTABLE_WARNINGS
#endif
#ifndef TOML_DISABLE_PADDING_WARNINGS
#define TOML_DISABLE_PADDING_WARNINGS
#endif
#ifndef TOML_DISABLE_FLOAT_WARNINGS
#define TOML_DISABLE_FLOAT_WARNINGS
#endif
#ifndef TOML_DISABLE_SHADOW_WARNINGS
#define TOML_DISABLE_SHADOW_WARNINGS
#endif
#ifndef TOML_DISABLE_ALL_WARNINGS
#define TOML_DISABLE_ALL_WARNINGS
#endif
@ -354,10 +378,6 @@ TOML_DISABLE_ALL_WARNINGS
TOML_POP_WARNINGS
#if TOML_CHAR_8_STRINGS
#ifndef __cpp_lib_char8_t
#error toml++ requires implementation support to use char8_t strings, but yours does not provide it.
#endif
#define TOML_STRING_PREFIX_1(S) u8##S
#define TOML_STRING_PREFIX(S) TOML_STRING_PREFIX_1(S)
#else

View File

@ -253,7 +253,7 @@ namespace toml::impl
std::ostringstream ss;
ss.imbue(std::locale::classic());
using cast_type = std::conditional_t<std::is_signed_v<T>, int64_t, uint64_t>;
ss << std::setfill('0') << std::setw(zero_pad_to_digits) << static_cast<cast_type>(val);
ss << std::setfill('0') << std::setw(static_cast<int>(zero_pad_to_digits)) << static_cast<cast_type>(val);
const auto str = std::move(ss).str();
print_to_stream(str, stream);

View File

@ -8,6 +8,7 @@
TOML_PUSH_WARNINGS
TOML_DISABLE_VTABLE_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml::impl
{
@ -118,7 +119,6 @@ namespace toml::impl
};
}
namespace toml
{
[[nodiscard]] TOML_API bool operator == (const table& lhs, const table& rhs) noexcept;
@ -742,4 +742,4 @@ namespace toml
};
}
TOML_POP_WARNINGS //TOML_DISABLE_VTABLE_WARNINGS
TOML_POP_WARNINGS // TOML_DISABLE_VTABLE_WARNINGS, TOML_DISABLE_PADDING_WARNINGS

View File

@ -13,6 +13,9 @@
#include "toml_utf8.h"
#include "toml_parse_error.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml::impl
{
template <typename T>
@ -445,3 +448,5 @@ namespace toml::impl
TOML_ABI_NAMESPACE_END // TOML_EXCEPTIONS
TOML_POP_WARNINGS
}
TOML_POP_WARNINGS // TOML_DISABLE_PADDING_WARNINGS

View File

@ -7,6 +7,10 @@
#include "toml_node.h"
#include "toml_print_to_stream.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_FLOAT_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml
{
template <typename Char, typename T>
@ -480,3 +484,4 @@ namespace toml
}
}
TOML_POP_WARNINGS // TOML_DISABLE_FLOAT_WARNINGS, TOML_DISABLE_PADDING_WARNINGS

View File

@ -7,7 +7,7 @@
#define TOML_LIB_MAJOR 1
#define TOML_LIB_MINOR 2
#define TOML_LIB_PATCH 3
#define TOML_LIB_PATCH 4
#define TOML_LANG_MAJOR 1
#define TOML_LANG_MINOR 0

View File

@ -1,15 +1,14 @@
project(
'tomlplusplus',
'cpp',
version : '1.2.3',
version : '1.2.4',
license : 'MIT',
default_options : [
'cpp_std=c++17',
'warning_level=3',
'werror=true',
'cpp_eh=default',
'b_ndebug=if-release',
'b_lto=true'
'b_ndebug=if-release'
]
)
@ -26,50 +25,105 @@ if build_tests or build_examples
compiler = meson.get_compiler('cpp')
message(['compiler ID: ', compiler.get_id()])
message(['compiler version: ', compiler.version()])
# GCC or Clang
if compiler.get_id() == 'gcc' or compiler.get_id() == 'clang'
add_project_arguments([
'-Wno-unused-command-line-argument',
'-march=native',
'-fno-rtti',
[ '-fdata-sections', '-ffunction-sections', '-Wl,--gc-sections' ]
],
language : 'cpp'
)
)
if get_option('SMALL_BINARIES')
add_project_arguments([ '-fdata-sections', '-ffunction-sections', '-Wl,--gc-sections', '-Wl,-s' ], language : 'cpp')
endif
endif
# GCC
if compiler.get_id() == 'gcc'
add_project_arguments([
'-fmax-errors=5',
'-Wno-init-list-lifetime',
'-fmerge-constants'
'-Wno-init-list-lifetime'
],
language : 'cpp'
)
if get_option('ALL_WARNINGS')
add_project_arguments([
'-Wcast-align',
'-Wcast-qual',
'-Wctor-dtor-privacy',
'-Wdisabled-optimization',
'-Wextra',
'-Wfloat-equal',
'-Wimport',
'-Winit-self',
'-Winline',
'-Wlogical-op',
'-Wmissing-declarations',
'-Wmissing-field-initializers',
'-Wmissing-format-attribute',
'-Wmissing-include-dirs',
'-Wmissing-noreturn',
'-Wnoexcept',
'-Wold-style-cast',
'-Woverloaded-virtual',
'-Wpacked',
'-Wpadded',
'-Wpedantic',
'-Wpointer-arith',
'-Wredundant-decls',
'-Wshadow',
'-Wsign-conversion',
'-Wsign-promo',
'-Wstack-protector',
'-Wstrict-null-sentinel',
'-Wswitch-default',
'-Wswitch-enum',
'-Wundef',
'-Wunreachable-code',
'-Wunused',
'-Wunused-parameter',
'-Wvariadic-macros',
'-Wwrite-strings',
],
language : 'cpp'
)
endif
if get_option('SMALL_BINARIES')
add_project_arguments([ '-fmerge-constants' ], language : 'cpp')
endif
endif
# Clang
if compiler.get_id() == 'clang'
if get_option('ALL_WARNINGS')
add_project_arguments([ '-Weverything' ], language : 'cpp')
endif
add_project_arguments([
'-ferror-limit=5',
'-fchar8_t',
'-fmerge-all-constants',
#'-Weverything',
'-fchar8_t',
'-Wno-unused-command-line-argument',
# flags from here down are disabling stupidly pedantic warnings that only appear with -Weverything
'-Wno-c++98-compat',
'-Wno-c++98-compat-pedantic',
'-Wno-float-equal',
'-Wno-switch-enum',
'-Wno-documentation',
'-Wno-documentation-unknown-command',
'-Wno-padded',
'-Wno-double-promotion',
'-Wno-covered-switch-default',
#'-ftime-trace'
'-Wno-switch-enum',
'-Wno-covered-switch-default'
],
language : 'cpp'
)
if get_option('TIME_TRACE')
add_project_arguments([ '-ftime-trace' ], language : 'cpp')
endif
if get_option('SMALL_BINARIES')
add_project_arguments([ '-Oz', '-fmerge-all-constants' ], language : 'cpp')
endif
endif
# ICC's visual studio frontend, ICL
if compiler.get_id() == 'intel-cl'
add_project_arguments([
'/Qoption,cpp,--unicode_source_kind,UTF-8',

View File

@ -1,3 +1,6 @@
option('BUILD_TESTS', type : 'feature', value : 'auto', description : 'Whether to build tests (default: auto - only if not a subproject)')
option('BUILD_EXAMPLES', type : 'feature', value : 'auto', description : 'Whether to build examples (default: auto - only if not a subproject)')
option('GENERATE_CMAKE_CONFIG', type : 'feature', value : 'auto', description : 'Whether to generate a cmake package config file (default: auto - only if not a subproject)')
option('BUILD_TESTS', type : 'feature', value : 'auto', description : 'Build tests (default: auto - only if not a subproject)')
option('BUILD_EXAMPLES', type : 'feature', value : 'auto', description : 'Build examples (default: auto - only if not a subproject)')
option('GENERATE_CMAKE_CONFIG', type : 'feature', value : 'auto', description : 'Generate a cmake package config file (default: auto - only if not a subproject)')
option('ALL_WARNINGS', type : 'boolean', value : false, description : 'Enable all the extra super-extremely-pedantic compiler warnings')
option('TIME_TRACE', type : 'boolean', value : false, description : 'Enable the -ftime-trace option (Clang only)')
option('SMALL_BINARIES', type : 'boolean', value : false, description : 'Add some flags to try to generate the smallest binary possible')

View File

@ -116,23 +116,27 @@ def main():
source_text = source_text.strip()
# extract library version
library_version = [0,0,0]
library_version = {
'major': 0,
'minor': 0,
'patch': 0
}
match = re.search(r'^\s*#\s*define\s+TOML_LIB_MAJOR\s+([0-9]+)\s*$', source_text, re.I | re.M)
if match is not None:
library_version[0] = match.group(1)
library_version['major'] = match.group(1)
match = re.search(r'^\s*#\s*define\s+TOML_LIB_MINOR\s+([0-9]+)\s*$', source_text, re.I | re.M)
if match is not None:
library_version[1] = match.group(1)
library_version['minor'] = match.group(1)
match = re.search(r'^\s*#\s*define\s+TOML_LIB_(?:REVISION|PATCH)\s+([0-9]+)\s*$', source_text, re.I | re.M)
if match is not None:
library_version[2] = match.group(1)
library_version['patch'] = match.group(1)
# build the preamble (license etc)
preamble = []
preamble.append('''
toml++ v{}
toml++ v{major}.{minor}.{patch}
https://github.com/marzer/tomlplusplus
SPDX-License-Identifier: MIT'''.format('.'.join(str(x) for x in library_version)))
SPDX-License-Identifier: MIT'''.format(**library_version))
preamble.append('''
- THIS FILE WAS ASSEMBLED FROM MULTIPLE HEADER FILES BY A SCRIPT - PLEASE DON'T EDIT IT DIRECTLY -
@ -165,7 +169,8 @@ v0.5.0: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5
print('//', file=output_file)
print(make_divider(), file=output_file)
print('''// clang-format off
#pragma once
#ifndef TOMLPLUSPLUS_SINGLE_HEADER_H
#define TOMLPLUSPLUS_SINGLE_HEADER_H
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
@ -177,6 +182,7 @@ v0.5.0: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#endif // TOMLPLUSPLUS_SINGLE_HEADER_H
// clang-format on''', file=output_file)

View File

@ -1,6 +1,11 @@
#include "../include/toml++/toml_preprocessor.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_ALL_WARNINGS
#define CATCH_CONFIG_RUNNER
#include "catch2.h"
#include <clocale>
TOML_POP_WARNINGS
int main(int argc, char* argv[])
{

View File

@ -1,3 +1,11 @@
#if !defined(_MSC_VER) || !defined(_M_IX86)
#define TOML_ALL_INLINE 0
#define TOML_IMPLEMENTATION
#endif
#include "../include/toml++/toml_preprocessor.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_ALL_WARNINGS
#ifdef TARTANLLAMA_OPTIONAL
#if __has_include(<tloptional/include/tl/optional.hpp>)
#include <tloptional/include/tl/optional.hpp>
@ -7,10 +15,8 @@
#define TOML_OPTIONAL_TYPE tl::optional
#endif
#include <ostream>
#if !defined(_MSC_VER) || !defined(_M_IX86)
#define TOML_ALL_INLINE 0
#define TOML_IMPLEMENTATION
#endif
TOML_POP_WARNINGS
#include "../include/toml++/toml.h"
namespace toml

View File

@ -175,7 +175,7 @@ TEST_CASE("tables - insertion and erasure")
static constexpr const string_char* a = S("a");
res = tbl.insert_or_assign(a, 69);
CHECK(res.first == tbl.begin());
CHECK(res.second == false); //should assign
CHECK(res.second == false); // should assign
CHECK(tbl.size() == 1_sz);
REQUIRE(tbl.get_as<int64_t>(S("a")));
CHECK(*tbl.get_as<int64_t>(S("a")) == 69);
@ -183,7 +183,7 @@ TEST_CASE("tables - insertion and erasure")
res = tbl.insert_or_assign(S("b"), S("kek"));
CHECK(res.first == advance(tbl.begin(), 1));
CHECK(res.second == true); //should insert
CHECK(res.second == true); // should insert
CHECK(tbl.size() == 2_sz);
REQUIRE(tbl.get_as<string>(S("b")));
CHECK(*tbl.get_as<string>(S("b")) == S("kek"sv));
@ -212,7 +212,7 @@ TEST_CASE("tables - insertion and erasure")
res = tbl.insert_or_assign(S("a"sv), 69);
CHECK(res.first == tbl.begin());
CHECK(res.second == true); //should insert
CHECK(res.second == true); // should insert
CHECK(tbl.size() == 3_sz);
REQUIRE(tbl.get_as<int64_t>(S("a")));
CHECK(*tbl.get_as<int64_t>(S("a")) == 69);

View File

@ -41,7 +41,7 @@ lt2 = 00:32:00.999999
}
);
//value tests
// value tests
parse_expected_value(FILE_LINE_ARGS, "1987-03-16"sv, date{ 1987, 3, 16 } );
parse_expected_value(FILE_LINE_ARGS, "10:20:30"sv, toml::time{ 10, 20, 30 } );
parse_expected_value(FILE_LINE_ARGS, "10:20:30.04"sv, toml::time{ 10, 20, 30, 40000000 } );

View File

@ -1,5 +1,7 @@
#include "tests.h"
TOML_DISABLE_FLOAT_WARNINGS
TEST_CASE("parsing - floats")
{
parsing_should_succeed(
@ -49,7 +51,7 @@ flt8 = 224_617.445_991_228
}
);
//value tests
// value tests
parse_expected_value( FILE_LINE_ARGS, "1e1"sv, 1e1);
parse_expected_value( FILE_LINE_ARGS, "1e+1"sv, 1e+1);
parse_expected_value( FILE_LINE_ARGS, "1e-1"sv, 1e-1);
@ -128,7 +130,7 @@ flt8 = 224_617.445_991_228
parse_expected_value( FILE_LINE_ARGS, "6.02e+23"sv, 6.02e+23);
parse_expected_value( FILE_LINE_ARGS, "1.112_650_06e-17"sv, 1.11265006e-17);
//toml/issues/562 (hexfloats)
// toml/issues/562 (hexfloats)
#if TOML_LANG_UNRELEASED
parse_expected_value(FILE_LINE_ARGS, " 0x1.2p3"sv, 0x1.2p3);
parse_expected_value(FILE_LINE_ARGS, " 0x10p1"sv, 0x10p1);

View File

@ -8,6 +8,11 @@ TEST_CASE("parsing - strings")
str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
str1 = """
Roses are red
Violets are blue"""
str2 = """
Roses are red
Violets are blue"""
)"sv),
@ -15,6 +20,7 @@ Violets are blue"""
{
CHECK(tbl[S("str")] == S("I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."sv));
CHECK(tbl[S("str1")] == S("Roses are red\nViolets are blue"sv));
CHECK(tbl[S("str2")] == S("\nRoses are red\nViolets are blue"sv));
}
);
@ -70,6 +76,13 @@ quoted = 'Tom "Dubs" Preston-Werner'
regex = '<\i\c*\s*>'
regex2 = '''I [dw]on't need \d{2} apples'''
lines = '''
The first newline is
trimmed in raw strings.
All other whitespace
is preserved.
'''
lines2 = '''
The first newline is
trimmed in raw strings.
All other whitespace
@ -84,6 +97,12 @@ trimmed in raw strings.
CHECK(tbl[S("regex")] == S(R"(<\i\c*\s*>)"sv));
CHECK(tbl[S("regex2")] == S(R"(I [dw]on't need \d{2} apples)"sv));
CHECK(tbl[S("lines")] == S(R"(The first newline is
trimmed in raw strings.
All other whitespace
is preserved.
)"sv));
CHECK(tbl[S("lines2")] == S(R"(
The first newline is
trimmed in raw strings.
All other whitespace
is preserved.
@ -112,7 +131,7 @@ str = ''''That's still pointless', she said.'''
parsing_should_fail(FILE_LINE_ARGS, S(R"(apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID)"sv));
//value tests
// value tests
parse_expected_value(
FILE_LINE_ARGS,
R"("The quick brown fox jumps over the lazy dog")"sv,
@ -156,7 +175,7 @@ str = ''''That's still pointless', she said.'''
parsing_should_fail(FILE_LINE_ARGS, R"(str = "\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90\x11\xFF\xEE")"sv);
#endif
//check 8-digit \U scalars with insufficient digits
// check 8-digit \U scalars with insufficient digits
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\U1234567")"sv);
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\U123456")"sv);
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\U12345")"sv);
@ -165,11 +184,31 @@ str = ''''That's still pointless', she said.'''
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\U12")"sv);
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\U1")"sv);
//check 4-digit \u scalars with insufficient digits
// check 4-digit \u scalars with insufficient digits
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\u123")"sv);
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\u12")"sv);
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\u1")"sv);
//check 2-digit \x scalars with insufficient digits
// check 2-digit \x scalars with insufficient digits
parsing_should_fail(FILE_LINE_ARGS, R"(str = "\x1")"sv);
// ML string examples from https://github.com/toml-lang/toml/issues/725
parse_expected_value(FILE_LINE_ARGS, R"( """ """ )"sv, S(R"( )"sv));
parse_expected_value(FILE_LINE_ARGS, R"( """ """" )"sv, S(R"( ")"sv));
parse_expected_value(FILE_LINE_ARGS, R"( """ """"" )"sv, S(R"( "")"sv));
parsing_should_fail(FILE_LINE_ARGS, R"(v= """ """""" )"sv);
parse_expected_value(FILE_LINE_ARGS, R"( ''' ''' )"sv, S(R"( )"sv));
parse_expected_value(FILE_LINE_ARGS, R"( ''' '''' )"sv, S(R"( ')"sv));
parse_expected_value(FILE_LINE_ARGS, R"( ''' ''''' )"sv, S(R"( '')"sv));
parsing_should_fail(FILE_LINE_ARGS, R"(v= ''' '''''' )"sv);
parse_expected_value(FILE_LINE_ARGS, R"( """""" )"sv, S(R"()"sv));
parse_expected_value(FILE_LINE_ARGS, R"( """" """ )"sv, S(R"(" )"sv));
parse_expected_value(FILE_LINE_ARGS, R"( """"" """ )"sv, S(R"("" )"sv));
parsing_should_fail(FILE_LINE_ARGS, R"(v= """""" """ )"sv);
parse_expected_value(FILE_LINE_ARGS, R"( '''''' )"sv, S(R"()"sv));
parse_expected_value(FILE_LINE_ARGS, R"( '''' ''' )"sv, S(R"(' )"sv));
parse_expected_value(FILE_LINE_ARGS, R"( ''''' ''' )"sv, S(R"('' )"sv));
parsing_should_fail(FILE_LINE_ARGS, R"(v= '''''' ''' )"sv);
parse_expected_value(FILE_LINE_ARGS, R"( """""\"""""" )"sv, S(R"(""""")"sv));
parse_expected_value(FILE_LINE_ARGS, R"( """""\"""\"""""" )"sv, S(R"("""""""")"sv));
}

View File

@ -1,19 +1,9 @@
#pragma once
#ifdef TARTANLLAMA_OPTIONAL
#if __has_include(<tloptional/include/tl/optional.hpp>)
#include <tloptional/include/tl/optional.hpp>
#else
#error TartanLlama/optional is missing! You probably need to fetch submodules ("git submodule update --init extern/tloptional")
#endif
#define TOML_OPTIONAL_TYPE tl::optional
#endif
#include "catch2.h"
#include <sstream>
#define TOML_UNDEF_MACROS 0
#if !defined(_MSC_VER) || !defined(_M_IX86)
#define TOML_ALL_INLINE 0
#endif
#include "../include/toml++/toml.h"
#include "../include/toml++/toml_preprocessor.h"
#if TOML_COMPILER_EXCEPTIONS
#if !TOML_EXCEPTIONS
@ -25,15 +15,30 @@
#endif
#endif
#define FILE_LINE_ARGS std::string_view{ __FILE__ }, __LINE__
TOML_PUSH_WARNINGS
TOML_DISABLE_ALL_WARNINGS
using namespace toml;
#ifdef TARTANLLAMA_OPTIONAL
#if __has_include(<tloptional/include/tl/optional.hpp>)
#include <tloptional/include/tl/optional.hpp>
#else
#error TartanLlama/optional is missing! You probably need to fetch submodules ("git submodule update --init extern/tloptional")
#endif
#define TOML_OPTIONAL_TYPE tl::optional
#endif
#include "catch2.h"
#include <sstream>
namespace toml {}
using namespace Catch::literals;
using namespace toml;
TOML_POP_WARNINGS
#define S(str) TOML_STRING_PREFIX(str)
#include "../include/toml++/toml.h"
#define FILE_LINE_ARGS std::string_view{ __FILE__ }, __LINE__
#define S(str) TOML_STRING_PREFIX(str)
TOML_PUSH_WARNINGS
TOML_DISABLE_FLOAT_WARNINGS
template <typename Char, typename Func = std::false_type>
inline void parsing_should_succeed(
@ -385,3 +390,5 @@ namespace Catch
extern template std::string stringify(const node_view<const node>&);
}
}
TOML_POP_WARNINGS // TOML_DISABLE_FLOAT_WARNINGS

315
toml.hpp
View File

@ -1,6 +1,6 @@
//----------------------------------------------------------------------------------------------------------------------
//
// toml++ v1.2.3
// toml++ v1.2.4
// https://github.com/marzer/tomlplusplus
// SPDX-License-Identifier: MIT
//
@ -42,7 +42,8 @@
//
//----------------------------------------------------------------------------------------------------------------------
// clang-format off
#pragma once
#ifndef TOMLPLUSPLUS_SINGLE_HEADER_H
#define TOMLPLUSPLUS_SINGLE_HEADER_H
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
@ -96,6 +97,10 @@
#define TOML_DISABLE_INIT_WARNINGS _Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"")
#define TOML_DISABLE_VTABLE_WARNINGS _Pragma("clang diagnostic ignored \"-Weverything\"") \
_Pragma("clang diagnostic ignored \"-Wweak-vtables\"")
#define TOML_DISABLE_PADDING_WARNINGS _Pragma("clang diagnostic ignored \"-Wpadded\"")
#define TOML_DISABLE_FLOAT_WARNINGS _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \
_Pragma("clang diagnostic ignored \"-Wdouble-promotion\"")
#define TOML_DISABLE_SHADOW_WARNINGS _Pragma("clang diagnostic ignored \"-Wshadow\"")
#define TOML_DISABLE_ALL_WARNINGS _Pragma("clang diagnostic ignored \"-Weverything\"")
#define TOML_POP_WARNINGS _Pragma("clang diagnostic pop")
#define TOML_ASSUME(cond) __builtin_assume(cond)
@ -156,14 +161,25 @@
#elif defined(__GNUC__)
#define TOML_PUSH_WARNINGS _Pragma("GCC diagnostic push")
#define TOML_DISABLE_SWITCH_WARNINGS _Pragma("GCC diagnostic ignored \"-Wswitch\"")
#define TOML_DISABLE_SWITCH_WARNINGS _Pragma("GCC diagnostic ignored \"-Wswitch\"") \
_Pragma("GCC diagnostic ignored \"-Wswitch-enum\"") \
_Pragma("GCC diagnostic ignored \"-Wswitch-default\"")
#define TOML_DISABLE_INIT_WARNINGS _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") \
_Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") \
_Pragma("GCC diagnostic ignored \"-Wuninitialized\"")
#define TOML_DISABLE_PADDING_WARNINGS _Pragma("GCC diagnostic ignored \"-Wpadded\"")
#define TOML_DISABLE_FLOAT_WARNINGS _Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
#define TOML_DISABLE_SHADOW_WARNINGS _Pragma("GCC diagnostic ignored \"-Wshadow\"")
#define TOML_DISABLE_ALL_WARNINGS _Pragma("GCC diagnostic ignored \"-Wall\"") \
_Pragma("GCC diagnostic ignored \"-Wextra\"") \
_Pragma("GCC diagnostic ignored \"-Wchar-subscripts\"") \
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"")
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"") \
TOML_DISABLE_SWITCH_WARNINGS \
TOML_DISABLE_INIT_WARNINGS \
TOML_DISABLE_PADDING_WARNINGS \
TOML_DISABLE_FLOAT_WARNINGS \
TOML_DISABLE_SHADOW_WARNINGS
#define TOML_POP_WARNINGS _Pragma("GCC diagnostic pop")
#define TOML_GNU_ATTR(...) __attribute__((__VA_ARGS__))
#define TOML_ALWAYS_INLINE __attribute__((__always_inline__)) inline
@ -246,6 +262,15 @@
#ifndef TOML_DISABLE_VTABLE_WARNINGS
#define TOML_DISABLE_VTABLE_WARNINGS
#endif
#ifndef TOML_DISABLE_PADDING_WARNINGS
#define TOML_DISABLE_PADDING_WARNINGS
#endif
#ifndef TOML_DISABLE_FLOAT_WARNINGS
#define TOML_DISABLE_FLOAT_WARNINGS
#endif
#ifndef TOML_DISABLE_SHADOW_WARNINGS
#define TOML_DISABLE_SHADOW_WARNINGS
#endif
#ifndef TOML_DISABLE_ALL_WARNINGS
#define TOML_DISABLE_ALL_WARNINGS
#endif
@ -322,7 +347,7 @@
#endif
#define TOML_LIB_MAJOR 1
#define TOML_LIB_MINOR 2
#define TOML_LIB_PATCH 3
#define TOML_LIB_PATCH 4
#define TOML_LANG_MAJOR 1
#define TOML_LANG_MINOR 0
@ -370,10 +395,6 @@ TOML_DISABLE_ALL_WARNINGS
TOML_POP_WARNINGS
#if TOML_CHAR_8_STRINGS
#ifndef __cpp_lib_char8_t
#error toml++ requires implementation support to use char8_t strings, but yours does not provide it.
#endif
#define TOML_STRING_PREFIX_1(S) u8##S
#define TOML_STRING_PREFIX(S) TOML_STRING_PREFIX_1(S)
#else
@ -447,6 +468,10 @@ namespace toml
#endif
TOML_PUSH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
TOML_DISABLE_SHADOW_WARNINGS // false positive on gcc
#if !TOML_DOXYGEN
// foward declarations are hidden from doxygen
@ -488,6 +513,8 @@ namespace toml
date_time
};
TOML_POP_WARNINGS // TOML_DISABLE_PADDING_WARNINGS, TOML_DISABLE_SHADOW_WARNINGS
#ifdef TOML_OPTIONAL_TYPE
template <typename T>
@ -838,6 +865,9 @@ namespace toml
//----------------------------------------------------------------- ↓ toml_date_time.h -------------------------------
#pragma region
TOML_PUSH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml
{
struct TOML_TRIVIAL_ABI date
@ -1145,6 +1175,8 @@ namespace toml
#endif
}
TOML_POP_WARNINGS // TOML_DISABLE_PADDING_WARNINGS
#pragma endregion
//----------------------------------------------------------------- ↑ toml_date_time.h -------------------------------
@ -1399,7 +1431,7 @@ namespace toml::impl
std::ostringstream ss;
ss.imbue(std::locale::classic());
using cast_type = std::conditional_t<std::is_signed_v<T>, int64_t, uint64_t>;
ss << std::setfill('0') << std::setw(zero_pad_to_digits) << static_cast<cast_type>(val);
ss << std::setfill('0') << std::setw(static_cast<int>(zero_pad_to_digits)) << static_cast<cast_type>(val);
const auto str = std::move(ss).str();
print_to_stream(str, stream);
@ -1820,6 +1852,7 @@ namespace toml
return std::forward<Func>(visitor)(std::forward<N>(n).template ref_cast<date_time>());
break;
case node_type::none: TOML_UNREACHABLE;
TOML_NO_DEFAULT_CASE;
}
@ -1916,6 +1949,10 @@ TOML_POP_WARNINGS //TOML_DISABLE_VTABLE_WARNINGS
//------------------------------------------ ↓ toml_value.h ----------------------------------------------------------
#pragma region
TOML_PUSH_WARNINGS
TOML_DISABLE_FLOAT_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml
{
template <typename Char, typename T>
@ -2269,6 +2306,8 @@ namespace toml
}
}
TOML_POP_WARNINGS // TOML_DISABLE_FLOAT_WARNINGS, TOML_DISABLE_PADDING_WARNINGS
#pragma endregion
//------------------------------------------ ↑ toml_value.h ----------------------------------------------------------
@ -2748,6 +2787,7 @@ TOML_POP_WARNINGS //TOML_DISABLE_VTABLE_WARNINGS
TOML_PUSH_WARNINGS
TOML_DISABLE_VTABLE_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml::impl
{
@ -3055,7 +3095,7 @@ namespace toml
};
}
TOML_POP_WARNINGS //TOML_DISABLE_VTABLE_WARNINGS
TOML_POP_WARNINGS // TOML_DISABLE_VTABLE_WARNINGS, TOML_DISABLE_PADDING_WARNINGS
#pragma endregion
//-------------------------------------------------------------------------------------------- ↑ toml_table.h --------
@ -3065,6 +3105,9 @@ TOML_POP_WARNINGS //TOML_DISABLE_VTABLE_WARNINGS
namespace toml
{
TOML_PUSH_WARNINGS
TOML_DISABLE_FLOAT_WARNINGS
template <typename Char, typename T>
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>&, const node_view<T>&);
@ -3280,6 +3323,8 @@ namespace toml
extern template TOML_API std::ostream& operator << (std::ostream&, const node_view<node>&);
extern template TOML_API std::ostream& operator << (std::ostream&, const node_view<const node>&);
#endif
TOML_POP_WARNINGS // TOML_DISABLE_FLOAT_WARNINGS
}
#pragma endregion
@ -4423,6 +4468,10 @@ namespace toml::impl
//------------------------------------------------------------------------------------------ ↓ toml_formatter.h ------
#pragma region
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml
{
enum class format_flags : uint8_t
@ -4430,11 +4479,19 @@ namespace toml
none,
quote_dates_and_times = 1
};
[[nodiscard]] constexpr format_flags operator & (format_flags lhs, format_flags rhs) noexcept
[[nodiscard]]
TOML_GNU_ATTR(const)
TOML_ALWAYS_INLINE
constexpr format_flags operator & (format_flags lhs, format_flags rhs) noexcept
{
return static_cast<format_flags>(impl::unbox_enum(lhs) & impl::unbox_enum(rhs));
}
[[nodiscard]] constexpr format_flags operator | (format_flags lhs, format_flags rhs) noexcept
[[nodiscard]]
TOML_GNU_ATTR(const)
TOML_ALWAYS_INLINE
constexpr format_flags operator | (format_flags lhs, format_flags rhs) noexcept
{
return static_cast<format_flags>( impl::unbox_enum(lhs) | impl::unbox_enum(rhs) );
}
@ -4540,8 +4597,9 @@ namespace toml::impl
}
}
void print(const node& val_node, node_type type)
void print_value(const node& val_node, node_type type)
{
TOML_ASSUME(type > node_type::array);
switch (type)
{
case node_type::string: print(*reinterpret_cast<const value<string>*>(&val_node)); break;
@ -4566,12 +4624,18 @@ namespace toml::impl
#endif
}
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_PADDING_WARNINGS
#pragma endregion
//------------------------------------------------------------------------------------------ ↑ toml_formatter.h ------
//----------- ↓ toml_default_formatter.h -----------------------------------------------------------------------------
#pragma region
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml::impl
{
[[nodiscard]] TOML_API
@ -4675,12 +4739,13 @@ namespace toml
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(v, type);
base::print_value(v, type);
}
}
@ -4719,12 +4784,13 @@ namespace toml
base::print_indent();
print_key_segment(k);
impl::print_to_stream(" = "sv, base::stream());
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(v, type);
base::print_value(v, type);
}
}
@ -4745,6 +4811,7 @@ namespace toml
{
(void)child_k;
const auto child_type = child_v.type();
TOML_ASSUME(child_type != node_type::none);
switch (child_type)
{
case node_type::table:
@ -4840,7 +4907,7 @@ namespace toml
break;
default:
base::print(base::source(), source_type);
base::print_value(base::source(), source_type);
}
}
@ -4885,12 +4952,13 @@ namespace toml
impl::print_to_stream(" = "sv, base::stream());
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(v, type);
base::print_value(v, type);
}
}
@ -4939,12 +5007,18 @@ namespace toml
#endif
}
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_PADDING_WARNINGS
#pragma endregion
//----------- ↑ toml_default_formatter.h -----------------------------------------------------------------------------
//-------------------------------------- ↓ toml_json_formatter.h -----------------------------------------------------
#pragma region
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml
{
template <typename T, typename U>
@ -4976,12 +5050,13 @@ namespace toml
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(v, type);
base::print_value(v, type);
}
}
@ -4999,7 +5074,7 @@ namespace toml
{
case node_type::table: print(*reinterpret_cast<const table*>(&base::source())); break;
case node_type::array: print(*reinterpret_cast<const array*>(&base::source())); break;
default: base::print(base::source(), source_type);
default: base::print_value(base::source(), source_type);
}
}
@ -5046,12 +5121,13 @@ namespace toml
impl::print_to_stream(" : "sv, base::stream());
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(v, type);
base::print_value(v, type);
}
}
@ -5086,6 +5162,8 @@ namespace toml
#endif
}
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_PADDING_WARNINGS
#pragma endregion
//-------------------------------------- ↑ toml_json_formatter.h -----------------------------------------------------
@ -5227,6 +5305,9 @@ TOML_POP_WARNINGS
//----------------------------------------------------------------------------------------- ↓ toml_utf8_streams.h ----
#pragma region
TOML_PUSH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml::impl
{
template <typename T>
@ -5659,12 +5740,17 @@ namespace toml::impl
TOML_POP_WARNINGS
}
TOML_POP_WARNINGS // TOML_DISABLE_PADDING_WARNINGS
#pragma endregion
//----------------------------------------------------------------------------------------- ↑ toml_utf8_streams.h ----
//----------------- ↓ toml_parser.h ----------------------------------------------------------------------------------
#pragma region
TOML_PUSH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml
{
#if TOML_DOXYGEN || !TOML_EXCEPTIONS
@ -5979,6 +6065,8 @@ namespace toml
}
}
TOML_POP_WARNINGS // TOML_DISABLE_PADDING_WARNINGS
#pragma endregion
//----------------- ↑ toml_parser.h ----------------------------------------------------------------------------------
@ -6420,6 +6508,10 @@ namespace toml
//---------- ↓ toml_default_formatter.hpp ----------------------------------------------------------------------------
#pragma region
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_FLOAT_WARNINGS
namespace toml::impl
{
TOML_PUSH_WARNINGS
@ -6541,6 +6633,7 @@ namespace toml::impl
case node_type::date: [[fallthrough]];
case node_type::time: return 10_sz;
case node_type::date_time: return 30_sz;
case node_type::none: TOML_UNREACHABLE;
TOML_NO_DEFAULT_CASE;
}
@ -6555,6 +6648,8 @@ namespace toml::impl
}
}
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_FLOAT_WARNINGS
#pragma endregion
//---------- ↑ toml_default_formatter.hpp ----------------------------------------------------------------------------
@ -6577,6 +6672,10 @@ TOML_DISABLE_ALL_WARNINGS
#endif
TOML_POP_WARNINGS
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace TOML_INTERNAL_NAMESPACE
{
template <uint64_t> struct parse_integer_traits;
@ -6712,6 +6811,17 @@ namespace TOML_INTERNAL_NAMESPACE
#define push_parse_scope_2(desc, line) scope_stack.push_back(desc); parse_scope ps_##line{ scope_stack }
#define push_parse_scope_1(desc, line) push_parse_scope_2(desc, line)
#define push_parse_scope(desc) push_parse_scope_1(desc, __LINE__)
struct parsed_key final
{
std::vector<toml::string> segments;
};
struct parsed_key_value_pair final
{
parsed_key key;
std::unique_ptr<toml::node> value;
};
}
namespace toml::impl
@ -7050,10 +7160,18 @@ namespace toml::impl
// skip the '"'
advance_and_return_if_error_or_eof({});
// multiline strings ignore a single line ending right at the beginning
if constexpr (MultiLine)
{
consume_line_break();
return_if_error({});
set_error_and_return_if_eof({});
}
string str;
bool escaped = false;
[[maybe_unused]] bool skipping_whitespace = false;
while (!is_eof())
do
{
if (escaped)
{
@ -7153,32 +7271,49 @@ namespace toml::impl
{
if constexpr (MultiLine)
{
advance_and_return_if_error_or_eof({});
const auto second = cp->value;
advance_and_return_if_error_or_eof({});
const auto third = cp->value;
if (second == U'"' && third == U'"')
size_t lookaheads = {};
size_t consecutive_delimiters = 1_sz;
do
{
advance_and_return_if_error({}); // skip the third closing delimiter
//multi-line basic strings are allowed one additional terminating '"'
//so that things like this work: """this is a "quote""""
advance_and_return_if_error({});
lookaheads++;
if (!is_eof() && *cp == U'"')
{
str += TOML_STRING_PREFIX('"');
advance_and_return_if_error({}); // skip the final closing delimiter
}
return str;
consecutive_delimiters++;
else
break;
}
else
while (lookaheads < 4_sz);
switch (consecutive_delimiters)
{
str += TOML_STRING_PREFIX('"');
go_back(1_sz);
skipping_whitespace = false;
continue;
// """ " (one quote somewhere in a ML string)
case 1_sz:
str += TOML_STRING_PREFIX('"');
skipping_whitespace = false;
continue;
// """ "" (two quotes somewhere in a ML string)
case 2_sz:
str.append(TOML_STRING_PREFIX("\"\""sv));
skipping_whitespace = false;
continue;
// """ """ (the end of the string)
case 3_sz:
return str;
// """ """" (one at the end of the string)
case 4_sz:
str += TOML_STRING_PREFIX('"');
return str;
// """ """"" (two quotes at the end of the string)
case 5_sz:
str.append(TOML_STRING_PREFIX("\"\""sv));
advance_and_return_if_error({}); // skip the last '"'
return str;
TOML_NO_DEFAULT_CASE;
}
}
else
@ -7204,7 +7339,7 @@ namespace toml::impl
{
consume_line_break();
return_if_error({});
if (!str.empty() && !skipping_whitespace)
if (!skipping_whitespace)
str += TOML_STRING_PREFIX('\n');
continue;
}
@ -7239,6 +7374,7 @@ namespace toml::impl
advance_and_return_if_error({});
}
}
while (!is_eof());
set_error_and_return_default("encountered end-of-file"sv);
}
@ -7255,8 +7391,16 @@ namespace toml::impl
// skip the delimiter
advance_and_return_if_error_or_eof({});
// multiline strings ignore a single line ending right at the beginning
if constexpr (MultiLine)
{
consume_line_break();
return_if_error({});
set_error_and_return_if_eof({});
}
string str;
while (!is_eof())
do
{
assert_not_error();
@ -7265,22 +7409,47 @@ namespace toml::impl
{
if constexpr (MultiLine)
{
advance_and_return_if_error_or_eof({});
const auto second = cp->value;
advance_and_return_if_error_or_eof({});
const auto third = cp->value;
if (second == U'\'' && third == U'\'')
size_t lookaheads = {};
size_t consecutive_delimiters = 1_sz;
do
{
advance_and_return_if_error({}); // skip the third closing delimiter
return str;
advance_and_return_if_error({});
lookaheads++;
if (!is_eof() && *cp == U'\'')
consecutive_delimiters++;
else
break;
}
else
while (lookaheads < 4_sz);
switch (consecutive_delimiters)
{
str += TOML_STRING_PREFIX('\'');
go_back(1_sz);
continue;
// ''' ' (one quote somewhere in a ML string)
case 1_sz:
str += TOML_STRING_PREFIX('\'');
continue;
// ''' '' (two quotes somewhere in a ML string)
case 2_sz:
str.append(TOML_STRING_PREFIX("''"sv));
continue;
// ''' ''' (the end of the string)
case 3_sz:
return str;
// ''' '''' (one at the end of the string)
case 4_sz:
str += TOML_STRING_PREFIX('\'');
return str;
// ''' ''''' (two quotes at the end of the string)
case 5_sz:
str.append(TOML_STRING_PREFIX("''"sv));
advance_and_return_if_error({}); // skip the last '
return str;
TOML_NO_DEFAULT_CASE;
}
}
else
@ -7296,8 +7465,7 @@ namespace toml::impl
if (is_line_break(*cp))
{
consume_line_break();
if (!str.empty())
str += TOML_STRING_PREFIX('\n');
str += TOML_STRING_PREFIX('\n');
continue;
}
}
@ -7320,6 +7488,7 @@ namespace toml::impl
str.append(cp->as_view());
advance_and_return_if_error({});
}
while (!is_eof());
set_error_and_return_default("encountered end-of-file"sv);
}
@ -8591,20 +8760,15 @@ namespace toml::impl
return val;
}
struct key final
{
std::vector<string> segments;
};
[[nodiscard]]
key parse_key() TOML_MAY_THROW
parsed_key parse_key() TOML_MAY_THROW
{
return_if_error({});
assert_not_eof();
assert_or_assume(is_bare_key_character(*cp) || is_string_delimiter(*cp));
push_parse_scope("key"sv);
key key;
parsed_key key;
while (!is_error())
{
@ -8650,14 +8814,8 @@ namespace toml::impl
return key;
}
struct key_value_pair final
{
parser::key key;
std::unique_ptr<node> value;
};
[[nodiscard]]
key_value_pair parse_key_value_pair() TOML_MAY_THROW
parsed_key_value_pair parse_key_value_pair() TOML_MAY_THROW
{
return_if_error({});
assert_not_eof();
@ -8698,7 +8856,7 @@ namespace toml::impl
const auto header_begin_pos = cp->position;
source_position header_end_pos;
key key;
parsed_key key;
bool is_arr = false;
//parse header
@ -9296,6 +9454,8 @@ namespace toml
}
}
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_PADDING_WARNINGS
#pragma endregion
//----------------------------------------- ↑ toml_parser.hpp --------------------------------------------------------
@ -9404,6 +9564,8 @@ namespace toml
#undef TOML_DISABLE_SWITCH_WARNINGS
#undef TOML_DISABLE_INIT_WARNINGS
#undef TOML_DISABLE_VTABLE_WARNINGS
#undef TOML_DISABLE_PADDING_WARNINGS
#undef TOML_DISABLE_FLOAT_WARNINGS
#undef TOML_DISABLE_ALL_WARNINGS
#undef TOML_POP_WARNINGS
#undef TOML_ALWAYS_INLINE
@ -9445,4 +9607,5 @@ namespace toml
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#endif // TOMLPLUSPLUS_SINGLE_HEADER_H
// clang-format on