parser performance improvements

also:
- updated msvc toolsets
- minor documentation updates
This commit is contained in:
Mark Gillard 2021-11-09 11:22:19 +02:00
parent 9783a94ed4
commit 6808825d3f
43 changed files with 382 additions and 329 deletions

View File

@ -8,7 +8,8 @@ template:
#### Fixes:
#### Additions:
#### Changes:
#### Removals and Deprecations:
#### Removals:
#### Build system:
-->
@ -20,12 +21,12 @@ This release will be a major version bump, so it's ABI breaks all around. Any AP
code changes at callsites or in build systems are indicated with ⚠️.
#### Fixes:
- ⚠️ fixed incorrect `noexcept` specifications on many functions
- fixed `json_formatter` not formatting inf and nan incorrectly
- fixed `table` init-list constructor requiring double-brackets
- fixed `TOML_API` + extern templates causing linker errors in some circumstances
- fixed an illegal table redefinition edge case (#112) (@python36)
- fixed documentation issues
- fixed incorrect `noexcept` specifications on many functions ⚠️
- fixed incorrect source position in redefinition error messages
- fixed missing `#include <initializer_list>`
- fixed missing `#include <utility>`
@ -34,9 +35,15 @@ code changes at callsites or in build systems are indicated with ⚠&#xFE0F;.
#### Additions:
- added `array::at()` and `table::at()`
- added `array::replace()` (#109) (#LebJe)
- added `default_init_flags` param to `array::resize()`
- added `formatter_flags::quote_infinities_and_nans`
- added `array::replace()` (#109) (@LebJe)
- added `array::resize()` param `default_init_flags`
- added `format_flags::allow_binary_integers`
- added `format_flags::allow_hexadecimal_integers`
- added `format_flags::allow_octal_integers`
- added `format_flags::allow_real_tabs_in_strings`
- added `format_flags::indent_array_elements`
- added `format_flags::indent_sub_tables`
- added `format_flags::quote_infinities_and_nans`
- added `operator->` to `value` for class types
- added `parse_benchmark` example
- added `TOML_ENABLE_FORMATTERS` option
@ -48,32 +55,34 @@ code changes at callsites or in build systems are indicated with ⚠&#xFE0F;.
- added value flags to array + table insert methods (#44) (@levicki)
#### Changes:
- `format_flags` is now backed by `uint64_t` (was previously `uint8_t`) ⚠&#xFE0F;
- `source_index` is now an alias for `uint32_t` unconditionally (was previously dependent on `TOML_LARGE_FILES`) ⚠&#xFE0F;
- `value_flags` is now backed by `uint16_t` (was previously `uint8_t`) ⚠&#xFE0F;
- ⚠&#xFE0F; `format_flags` is now backed by `uint64_t` (was previously `uint8_t`)
- ⚠&#xFE0F; `source_index` is now an alias for `uint32_t` unconditionally (was previously dependent on `TOML_LARGE_FILES`)
- ⚠&#xFE0F; `value_flags` is now backed by `uint16_t` (was previously `uint8_t`)
- ⚠&#xFE0F; made all overloaded operators 'hidden friends' where possible
- ⚠&#xFE0F; renamed `default_formatter` to `toml_formatter` (`default_formatter` is now an alias)
- ⚠&#xFE0F; renamed `TOML_PARSER` option to `TOML_ENABLE_PARSER` (`TOML_PARSER` will continue to work but is deprecated)
- ⚠&#xFE0F; renamed `TOML_UNRELEASED_FEATURES` to `TOML_ENABLE_UNRELEASED_FEATURES` (`TOML_UNRELEASED_FEATURES` will continue to work but is deprecated)
- ⚠&#xFE0F; renamed `TOML_WINDOWS_COMPAT` to `TOML_ENABLE_WINDOWS_COMPAT` (`TOML_WINDOWS_COMPAT` will continue to work but is deprecated)
- applied clang-format to all the things 🎉&#xFE0F;
- improved performance of parser's internal UTF-8 stream decoder
- made all overloaded operators 'hidden friends' where possible ⚠&#xFE0F;
- improved performance of parser
- made date/time constructors accept any integral types
- moved all implementation headers to `/impl`
- renamed `default_formatter` to `toml_formatter` (`default_formatter` is now an alias)
- renamed all implementation headers to `.h` and 'source' headers to `.inl`
- updated conformance tests
#### Removals and Deprecations:
- removed `TOML_LARGE_FILES` (it is now default - explicitly setting `TOML_LARGE_FILES` to `0` will invoke an `#error`) ⚠&#xFE0F;
#### Removals:
- ⚠&#xFE0F; removed `format_flags::allow_value_format_flags`
- ⚠&#xFE0F; removed `TOML_LARGE_FILES` (it is now default - explicitly setting `TOML_LARGE_FILES` to `0` will invoke an `#error`)
- removed unnecessary template machinery (esp. where ostreams were involved)
- removed unnecessary uses of `final`
- renamed `TOML_PARSER` option to `TOML_ENABLE_PARSER` (`TOML_PARSER` will continue to work but is deprecated) ⚠&#xFE0F;
- renamed `TOML_UNRELEASED_FEATURES` to `TOML_ENABLE_UNRELEASED_FEATURES` (`TOML_UNRELEASED_FEATURES` will continue to work but is deprecated) ⚠&#xFE0F;
- renamed `TOML_WINDOWS_COMPAT` to `TOML_ENABLE_WINDOWS_COMPAT` (`TOML_WINDOWS_COMPAT` will continue to work but is deprecated) ⚠&#xFE0F;
#### Build system:
- ⚠&#xFE0F; increased minimum required meson version to `0.54.0`
- disabled 'install' path when being used as a meson subproject (#114) (@Tachi107)
- fixed builds failing with meson 0.6.0 (#117) (@Tachi107)
- general meson improvements and fixes (#115) (@Tachi107)
- used `override_dependency` where supported (#116) (@Tachi107)
- fixed builds failing with meson 0.6.0 (#117) (@Tachi107)
- increased minimum required meson version to `0.54.0`&#xFE0F;
## [v2.5.0](https://github.com/osgenic/stim/releases/tag/v2.5.0) - 2021-07-11
@ -120,7 +129,7 @@ code changes at callsites or in build systems are indicated with ⚠&#xFE0F;.
- added proper cmake support (#85) (@ClausKlein)
- added cmake FetchContent information to documentation (#101) (@proydakov)
#### Removals and Deprecations:
#### Removals:
- removed explicit `#include <fstream>` requirement for `parse_file()`
@ -199,7 +208,7 @@ code changes at callsites or in build systems are indicated with ⚠&#xFE0F;.
## [v2.0.0](https://github.com/osgenic/stim/releases/tag/v2.0.0) - 2020-07-20
This release contains a fairly significant number of 'quality of life' improvements, yay! But also necessitates an ABI
break (hence the version number bump). Changes that might block a migration are annotated with '&#xFE0F;'.
break (hence the version number bump). Changes that might block a migration are annotated with ⚠&#xFE0F;.
#### Fixes:
- fixed infinity and NaN-related code breaking when using `-ffast-math` and friends
@ -228,14 +237,14 @@ break (hence the version number bump). Changes that might block a migration are
- added explicit instantiations of more template types when `!TOML_ALL_INLINE`
#### Changes:
- ⚠&#xFE0F; deprecated `parse_result::get()` in favour of `parse_result::table()`
- ⚠&#xFE0F; deprecated `node_view::get()` in favour of `node_view::node()`
- ⚠&#xFE0F; simplified internal ABI namespaces
- improved the quality of many static_assert error messages
- simplified internal ABI namespaces ⚠&#xFE0F;
#### Removals and Deprecations:
- deprecated `node_view::get()` in favour of `node_view::node()`&#xFE0F;
- deprecated `parse_result::get()` in favour of `parse_result::table()`&#xFE0F;
- removed `TOML_CHAR_8_STRINGS` since it no longer makes sense ⚠&#xFE0F;
- renamed `date_time::time_offset` to just 'offset' ⚠&#xFE0F;
#### Removals:
- ⚠&#xFE0F; renamed `date_time::time_offset` to just 'offset'
- ⚠&#xFE0F; removed `TOML_CHAR_8_STRINGS` since it no longer makes sense
@ -446,7 +455,7 @@ break (hence the version number bump). Changes that might block a migration are
- added `TOML_ALL_INLINE` and `TOML_IMPLEMENTATION` options
- added preliminary support for ICC
#### Removals and Deprecations:
#### Removals:
- removed `<cmath>` dependency

View File

@ -24,8 +24,8 @@
- Proper UTF-8 handling (incl. BOM)
- Works with or without exceptions
- Doesn't require RTTI
- First-class support for serializing to JSON and YAML
- Tested on Clang (6+), GCC (7+) and MSVC (VS2019)
- Support for serializing to JSON and YAML
- Tested on Clang (6+), GCC (7+) and MSVC (VS2019, VS2022)
- Tested on x64, x86 and ARM
<br>

View File

@ -19,13 +19,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
@ -58,4 +58,4 @@
<ClInclude Include="examples.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

View File

@ -19,13 +19,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
@ -59,4 +59,4 @@
<ClInclude Include="examples.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

View File

@ -19,13 +19,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
@ -59,4 +59,4 @@
<ClInclude Include="examples.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

View File

@ -20,13 +20,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
@ -59,4 +59,4 @@
<ClInclude Include="examples.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

View File

@ -20,13 +20,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
@ -59,4 +59,4 @@
<ClInclude Include="examples.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

View File

@ -932,16 +932,47 @@ TOML_ANON_NAMESPACE_START
}
};
struct parsed_key
struct parsed_key_buffer
{
source_position position;
std::vector<std::string> segments;
};
std::string buffer;
std::vector<std::pair<size_t, size_t>> segments;
source_region source;
struct parsed_key_value_pair
{
parsed_key key;
node_ptr value;
void reset(source_position pos) noexcept
{
buffer.clear();
segments.clear();
source.begin = pos;
}
void push_back(std::string_view segment)
{
segments.push_back({ buffer.length(), segment.length() });
buffer.append(segment);
}
void finish(source_position pos) noexcept
{
source.end = pos;
}
TOML_PURE_INLINE_GETTER
std::string_view operator[](size_t i) noexcept
{
return std::string_view{ buffer.c_str() + segments[i].first, segments[i].second };
}
TOML_PURE_INLINE_GETTER
std::string_view back() noexcept
{
return (*this)[segments.size() - 1u];
}
TOML_PURE_INLINE_GETTER
size_t size() noexcept
{
return segments.size();
}
};
struct parse_depth_counter
@ -967,7 +998,7 @@ TOML_ANON_NAMESPACE_START
struct parsed_string
{
std::string value;
std::string_view value;
bool was_multi_line;
};
}
@ -1052,7 +1083,7 @@ TOML_ANON_NAMESPACE_END;
#define set_error_and_return_if_eof(...) \
do \
{ \
if (is_eof()) \
if TOML_UNLIKELY(is_eof()) \
set_error_and_return(__VA_ARGS__, "encountered end-of-file"sv); \
} \
while (false)
@ -1094,6 +1125,8 @@ TOML_IMPL_NAMESPACE_START
std::vector<table*> implicit_tables;
std::vector<table*> dotted_key_tables;
std::vector<array*> table_arrays;
parsed_key_buffer key_buffer;
std::string string_buffer;
std::string recording_buffer; // for diagnostics
bool recording = false, recording_whitespace = true;
std::string_view current_scope;
@ -1343,7 +1376,7 @@ TOML_IMPL_NAMESPACE_START
}
TOML_NODISCARD
std::string parse_basic_string(bool multi_line)
std::string_view parse_basic_string(bool multi_line)
{
return_if_error({});
assert_not_eof();
@ -1361,7 +1394,8 @@ TOML_IMPL_NAMESPACE_START
set_error_and_return_if_eof({});
}
std::string str;
auto& str = string_buffer;
str.clear();
bool escaped = false;
bool skipping_whitespace = false;
do
@ -1567,7 +1601,7 @@ TOML_IMPL_NAMESPACE_START
}
TOML_NODISCARD
std::string parse_literal_string(bool multi_line)
std::string_view parse_literal_string(bool multi_line)
{
return_if_error({});
assert_not_eof();
@ -1585,7 +1619,8 @@ TOML_IMPL_NAMESPACE_START
set_error_and_return_if_eof({});
}
std::string str;
auto& str = string_buffer;
str.clear();
do
{
return_if_error({});
@ -1714,14 +1749,14 @@ TOML_IMPL_NAMESPACE_START
TOML_NODISCARD
TOML_NEVER_INLINE
std::string parse_bare_key_segment()
std::string_view parse_bare_key_segment()
{
return_if_error({});
assert_not_eof();
assert_or_assume(is_bare_key_character(*cp));
std::string segment;
segment.reserve(10u);
auto& segment = string_buffer;
segment.clear();
while (!is_eof())
{
@ -2485,7 +2520,7 @@ TOML_IMPL_NAMESPACE_START
// strings
case U'"': [[fallthrough]];
case U'\'':
return new value{ std::move(parse_string().value) };
return new value{ parse_string().value };
// bools
case U't': [[fallthrough]];
@ -2980,18 +3015,16 @@ TOML_IMPL_NAMESPACE_START
return val.release();
}
TOML_NODISCARD
parsed_key parse_key()
bool parse_key()
{
return_if_error({});
assert_not_eof();
assert_or_assume(is_bare_key_character(*cp) || is_string_delimiter(*cp));
push_parse_scope("key"sv);
parsed_key key;
key.position = current_position();
key_buffer.reset(current_position());
recording_whitespace = false;
std::string pending_key_segment;
std::string_view pending_key_segment;
while (!is_error())
{
@ -3018,12 +3051,12 @@ TOML_IMPL_NAMESPACE_START
{
set_error_at(begin_pos,
"multi-line strings are prohibited in "sv,
key.segments.empty() ? ""sv : "dotted "sv,
key_buffer.segments.empty() ? ""sv : "dotted "sv,
"keys"sv);
return_after_error({});
}
else
pending_key_segment = std::move(str.value);
pending_key_segment = str.value;
}
// ???
@ -3035,58 +3068,22 @@ TOML_IMPL_NAMESPACE_START
// whitespace following the key segment
consume_leading_whitespace();
// store segment
key_buffer.push_back(pending_key_segment);
// eof or no more key to come
if (is_eof() || *cp != U'.')
{
key.segments.push_back(std::move(pending_key_segment));
break;
}
// was a dotted key - reserve capacity for a few segments
if (!key.segments.capacity())
key.segments.reserve(3u);
key.segments.push_back(std::move(pending_key_segment));
// go around again to consume the next segment
// was a dotted key - go around again
advance_and_return_if_error_or_eof({});
consume_leading_whitespace();
set_error_and_return_if_eof({});
}
return_if_error({});
return key;
}
TOML_NODISCARD
parsed_key_value_pair parse_key_value_pair()
{
return_if_error({});
assert_not_eof();
assert_or_assume(is_string_delimiter(*cp) || is_bare_key_character(*cp));
push_parse_scope("key-value pair"sv);
// get the key
start_recording();
auto key = parse_key();
stop_recording(1u);
// skip past any whitespace that followed the key
consume_leading_whitespace();
set_error_and_return_if_eof({});
// '='
if (*cp != U'=')
set_error_and_return_default("expected '=', saw '"sv, to_sv(*cp), "'"sv);
advance_and_return_if_error_or_eof({});
// skip past any whitespace that followed the '='
consume_leading_whitespace();
return_if_error({});
set_error_and_return_if_eof({});
// get the value
if (is_value_terminator(*cp))
set_error_and_return_default("expected value, saw '"sv, to_sv(*cp), "'"sv);
return { std::move(key), node_ptr{ parse_value() } };
key_buffer.finish(current_position());
return true;
}
TOML_NODISCARD
@ -3099,7 +3096,6 @@ TOML_IMPL_NAMESPACE_START
const source_position header_begin_pos = cp->position;
source_position header_end_pos;
parsed_key key;
bool is_arr = false;
// parse header
@ -3132,7 +3128,7 @@ TOML_IMPL_NAMESPACE_START
// get the actual key
start_recording();
key = parse_key();
parse_key();
stop_recording(1u);
return_if_error({});
@ -3158,16 +3154,17 @@ TOML_IMPL_NAMESPACE_START
if (!is_eof() && !consume_comment() && !consume_line_break())
set_error_and_return_default("expected a comment or whitespace, saw '"sv, to_sv(cp), "'"sv);
}
TOML_ASSERT(!key.segments.empty());
TOML_ASSERT(!key_buffer.segments.empty());
// check if each parent is a table/table array, or can be created implicitly as a table.
auto parent = &root;
for (size_t i = 0; i < key.segments.size() - 1u; i++)
for (size_t i = 0, e = key_buffer.size() - 1u; i < e; i++)
{
auto child = parent->get(key.segments[i]);
const auto segment = key_buffer[i];
auto child = parent->get(segment);
if (!child)
{
child = parent->map_.emplace(key.segments[i], new table{}).first->second.get();
child = parent->map_.emplace(segment, new table{}).first->second.get();
implicit_tables.push_back(&child->ref_cast<table>());
child->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
parent = &child->ref_cast<table>();
@ -3204,14 +3201,15 @@ TOML_IMPL_NAMESPACE_START
// check the last parent table for a node matching the last key.
// if there was no matching node, then sweet;
// we can freely instantiate a new table/table array.
auto matching_node = parent->get(key.segments.back());
const auto last_segment = key_buffer.back();
auto matching_node = parent->get(last_segment);
if (!matching_node)
{
// if it's an array we need to make the array and it's first table element,
// set the starting regions, and return the table element
if (is_arr)
{
array& tbl_arr = parent->emplace<array>(key.segments.back()).first->second.ref_cast<array>();
array& tbl_arr = parent->emplace<array>(last_segment).first->second.ref_cast<array>();
table_arrays.push_back(&tbl_arr);
tbl_arr.source_ = { header_begin_pos, header_end_pos, reader.source_path() };
@ -3223,7 +3221,7 @@ TOML_IMPL_NAMESPACE_START
// otherwise we're just making a table
else
{
table& tbl = parent->emplace<table>(key.segments.back()).first->second.ref_cast<table>();
table& tbl = parent->emplace<table>(last_segment).first->second.ref_cast<table>();
tbl.source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tbl;
}
@ -3279,29 +3277,51 @@ TOML_IMPL_NAMESPACE_START
}
}
void parse_key_value_pair_and_insert(table* tab)
bool parse_key_value_pair_and_insert(table* tbl)
{
return_if_error();
return_if_error({});
assert_not_eof();
assert_or_assume(is_string_delimiter(*cp) || is_bare_key_character(*cp));
push_parse_scope("key-value pair"sv);
auto kvp = parse_key_value_pair();
return_if_error();
// read the key into the key buffer
start_recording();
parse_key();
stop_recording(1u);
return_if_error({});
TOML_ASSERT(key_buffer.size() >= 1u);
TOML_ASSERT(kvp.key.segments.size() >= 1u);
// skip past any whitespace that followed the key
consume_leading_whitespace();
set_error_and_return_if_eof({});
// '='
if (*cp != U'=')
set_error_and_return_default("expected '=', saw '"sv, to_sv(*cp), "'"sv);
advance_and_return_if_error_or_eof({});
// skip past any whitespace that followed the '='
consume_leading_whitespace();
return_if_error({});
set_error_and_return_if_eof({});
// check that the next character could actually be a value
if (is_value_terminator(*cp))
set_error_and_return_default("expected value, saw '"sv, to_sv(*cp), "'"sv);
// if it's a dotted kvp we need to spawn the sub-tables if necessary,
// and set the target table to the second-to-last one in the chain
if (kvp.key.segments.size() > 1u)
if (key_buffer.size() > 1u)
{
for (size_t i = 0; i < kvp.key.segments.size() - 1u; i++)
for (size_t i = 0; i < key_buffer.size() - 1u; i++)
{
auto child = tab->get(kvp.key.segments[i]);
const auto segment = key_buffer[i];
auto child = tbl->get(segment);
if (!child)
{
child = tab->map_.emplace(std::move(kvp.key.segments[i]), new table{}).first->second.get();
child = tbl->map_.emplace(std::string{ segment }, new table{}).first->second.get();
dotted_key_tables.push_back(&child->ref_cast<table>());
child->source_ = kvp.value->source_;
child->source_ = key_buffer.source;
}
else if (!child->is_table()
|| !(impl::find(dotted_key_tables.begin(),
@ -3310,37 +3330,38 @@ TOML_IMPL_NAMESPACE_START
|| impl::find(implicit_tables.begin(),
implicit_tables.end(),
&child->ref_cast<table>())))
set_error_at(kvp.key.position,
{
set_error_at(key_buffer.source.begin,
"cannot redefine existing "sv,
to_sv(child->type()),
" as dotted key-value pair"sv);
else
child->source_.end = kvp.value->source_.end;
return_after_error({});
}
return_if_error();
tab = &child->ref_cast<table>();
tbl = &child->ref_cast<table>();
}
}
if (auto conflicting_node = tab->get(kvp.key.segments.back()))
// ensure this isn't a redefinition
if (auto conflicting_node = tbl->get(key_buffer.back()))
{
if (conflicting_node->type() == kvp.value->type())
set_error("cannot redefine existing "sv,
to_sv(conflicting_node->type()),
" '"sv,
to_sv(recording_buffer),
"'"sv);
else
set_error("cannot redefine existing "sv,
to_sv(conflicting_node->type()),
" '"sv,
to_sv(recording_buffer),
"' as "sv,
to_sv(kvp.value->type()));
set_error("cannot redefine existing "sv,
to_sv(conflicting_node->type()),
" '"sv,
to_sv(recording_buffer),
"'"sv);
return_after_error({});
}
return_if_error();
tab->map_.emplace(std::move(kvp.key.segments.back()), std::unique_ptr<node>{ kvp.value.release() });
// cache the last segment since it might get overwritten by nested tables etc.
auto last_segment = std::string{ key_buffer.back() };
// now we can actually parse the value
auto val = node_ptr{ parse_value() };
return_if_error({});
tbl->map_.emplace(std::move(last_segment), std::unique_ptr<node>{ val.release() });
return true;
}
void parse_document()
@ -3432,7 +3453,8 @@ TOML_IMPL_NAMESPACE_START
parser(utf8_reader_interface&& reader_) //
: reader{ reader_ }
{
root.source_ = { prev_pos, prev_pos, reader.source_path() };
root.source_ = { prev_pos, prev_pos, reader.source_path() };
key_buffer.source.path = reader.source_path();
if (!reader.peek_eof())
{

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -16,13 +16,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -19,13 +19,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
@ -125,4 +125,4 @@
<Text Include="tools\requirements.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

238
toml.hpp
View File

@ -10587,16 +10587,47 @@ TOML_ANON_NAMESPACE_START
}
};
struct parsed_key
struct parsed_key_buffer
{
source_position position;
std::vector<std::string> segments;
};
std::string buffer;
std::vector<std::pair<size_t, size_t>> segments;
source_region source;
struct parsed_key_value_pair
{
parsed_key key;
node_ptr value;
void reset(source_position pos) noexcept
{
buffer.clear();
segments.clear();
source.begin = pos;
}
void push_back(std::string_view segment)
{
segments.push_back({ buffer.length(), segment.length() });
buffer.append(segment);
}
void finish(source_position pos) noexcept
{
source.end = pos;
}
TOML_PURE_INLINE_GETTER
std::string_view operator[](size_t i) noexcept
{
return std::string_view{ buffer.c_str() + segments[i].first, segments[i].second };
}
TOML_PURE_INLINE_GETTER
std::string_view back() noexcept
{
return (*this)[segments.size() - 1u];
}
TOML_PURE_INLINE_GETTER
size_t size() noexcept
{
return segments.size();
}
};
struct parse_depth_counter
@ -10622,7 +10653,7 @@ TOML_ANON_NAMESPACE_START
struct parsed_string
{
std::string value;
std::string_view value;
bool was_multi_line;
};
}
@ -10707,7 +10738,7 @@ TOML_ANON_NAMESPACE_END;
#define set_error_and_return_if_eof(...) \
do \
{ \
if (is_eof()) \
if TOML_UNLIKELY(is_eof()) \
set_error_and_return(__VA_ARGS__, "encountered end-of-file"sv); \
} \
while (false)
@ -10749,6 +10780,8 @@ TOML_IMPL_NAMESPACE_START
std::vector<table*> implicit_tables;
std::vector<table*> dotted_key_tables;
std::vector<array*> table_arrays;
parsed_key_buffer key_buffer;
std::string string_buffer;
std::string recording_buffer; // for diagnostics
bool recording = false, recording_whitespace = true;
std::string_view current_scope;
@ -10998,7 +11031,7 @@ TOML_IMPL_NAMESPACE_START
}
TOML_NODISCARD
std::string parse_basic_string(bool multi_line)
std::string_view parse_basic_string(bool multi_line)
{
return_if_error({});
assert_not_eof();
@ -11016,7 +11049,8 @@ TOML_IMPL_NAMESPACE_START
set_error_and_return_if_eof({});
}
std::string str;
auto& str = string_buffer;
str.clear();
bool escaped = false;
bool skipping_whitespace = false;
do
@ -11222,7 +11256,7 @@ TOML_IMPL_NAMESPACE_START
}
TOML_NODISCARD
std::string parse_literal_string(bool multi_line)
std::string_view parse_literal_string(bool multi_line)
{
return_if_error({});
assert_not_eof();
@ -11240,7 +11274,8 @@ TOML_IMPL_NAMESPACE_START
set_error_and_return_if_eof({});
}
std::string str;
auto& str = string_buffer;
str.clear();
do
{
return_if_error({});
@ -11369,14 +11404,14 @@ TOML_IMPL_NAMESPACE_START
TOML_NODISCARD
TOML_NEVER_INLINE
std::string parse_bare_key_segment()
std::string_view parse_bare_key_segment()
{
return_if_error({});
assert_not_eof();
assert_or_assume(is_bare_key_character(*cp));
std::string segment;
segment.reserve(10u);
auto& segment = string_buffer;
segment.clear();
while (!is_eof())
{
@ -12140,7 +12175,7 @@ TOML_IMPL_NAMESPACE_START
// strings
case U'"': [[fallthrough]];
case U'\'':
return new value{ std::move(parse_string().value) };
return new value{ parse_string().value };
// bools
case U't': [[fallthrough]];
@ -12634,18 +12669,16 @@ TOML_IMPL_NAMESPACE_START
return val.release();
}
TOML_NODISCARD
parsed_key parse_key()
bool parse_key()
{
return_if_error({});
assert_not_eof();
assert_or_assume(is_bare_key_character(*cp) || is_string_delimiter(*cp));
push_parse_scope("key"sv);
parsed_key key;
key.position = current_position();
key_buffer.reset(current_position());
recording_whitespace = false;
std::string pending_key_segment;
std::string_view pending_key_segment;
while (!is_error())
{
@ -12672,12 +12705,12 @@ TOML_IMPL_NAMESPACE_START
{
set_error_at(begin_pos,
"multi-line strings are prohibited in "sv,
key.segments.empty() ? ""sv : "dotted "sv,
key_buffer.segments.empty() ? ""sv : "dotted "sv,
"keys"sv);
return_after_error({});
}
else
pending_key_segment = std::move(str.value);
pending_key_segment = str.value;
}
// ???
@ -12689,58 +12722,22 @@ TOML_IMPL_NAMESPACE_START
// whitespace following the key segment
consume_leading_whitespace();
// store segment
key_buffer.push_back(pending_key_segment);
// eof or no more key to come
if (is_eof() || *cp != U'.')
{
key.segments.push_back(std::move(pending_key_segment));
break;
}
// was a dotted key - reserve capacity for a few segments
if (!key.segments.capacity())
key.segments.reserve(3u);
key.segments.push_back(std::move(pending_key_segment));
// go around again to consume the next segment
// was a dotted key - go around again
advance_and_return_if_error_or_eof({});
consume_leading_whitespace();
set_error_and_return_if_eof({});
}
return_if_error({});
return key;
}
TOML_NODISCARD
parsed_key_value_pair parse_key_value_pair()
{
return_if_error({});
assert_not_eof();
assert_or_assume(is_string_delimiter(*cp) || is_bare_key_character(*cp));
push_parse_scope("key-value pair"sv);
// get the key
start_recording();
auto key = parse_key();
stop_recording(1u);
// skip past any whitespace that followed the key
consume_leading_whitespace();
set_error_and_return_if_eof({});
// '='
if (*cp != U'=')
set_error_and_return_default("expected '=', saw '"sv, to_sv(*cp), "'"sv);
advance_and_return_if_error_or_eof({});
// skip past any whitespace that followed the '='
consume_leading_whitespace();
return_if_error({});
set_error_and_return_if_eof({});
// get the value
if (is_value_terminator(*cp))
set_error_and_return_default("expected value, saw '"sv, to_sv(*cp), "'"sv);
return { std::move(key), node_ptr{ parse_value() } };
key_buffer.finish(current_position());
return true;
}
TOML_NODISCARD
@ -12753,7 +12750,6 @@ TOML_IMPL_NAMESPACE_START
const source_position header_begin_pos = cp->position;
source_position header_end_pos;
parsed_key key;
bool is_arr = false;
// parse header
@ -12786,7 +12782,7 @@ TOML_IMPL_NAMESPACE_START
// get the actual key
start_recording();
key = parse_key();
parse_key();
stop_recording(1u);
return_if_error({});
@ -12812,16 +12808,17 @@ TOML_IMPL_NAMESPACE_START
if (!is_eof() && !consume_comment() && !consume_line_break())
set_error_and_return_default("expected a comment or whitespace, saw '"sv, to_sv(cp), "'"sv);
}
TOML_ASSERT(!key.segments.empty());
TOML_ASSERT(!key_buffer.segments.empty());
// check if each parent is a table/table array, or can be created implicitly as a table.
auto parent = &root;
for (size_t i = 0; i < key.segments.size() - 1u; i++)
for (size_t i = 0, e = key_buffer.size() - 1u; i < e; i++)
{
auto child = parent->get(key.segments[i]);
const auto segment = key_buffer[i];
auto child = parent->get(segment);
if (!child)
{
child = parent->map_.emplace(key.segments[i], new table{}).first->second.get();
child = parent->map_.emplace(segment, new table{}).first->second.get();
implicit_tables.push_back(&child->ref_cast<table>());
child->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
parent = &child->ref_cast<table>();
@ -12858,14 +12855,15 @@ TOML_IMPL_NAMESPACE_START
// check the last parent table for a node matching the last key.
// if there was no matching node, then sweet;
// we can freely instantiate a new table/table array.
auto matching_node = parent->get(key.segments.back());
const auto last_segment = key_buffer.back();
auto matching_node = parent->get(last_segment);
if (!matching_node)
{
// if it's an array we need to make the array and it's first table element,
// set the starting regions, and return the table element
if (is_arr)
{
array& tbl_arr = parent->emplace<array>(key.segments.back()).first->second.ref_cast<array>();
array& tbl_arr = parent->emplace<array>(last_segment).first->second.ref_cast<array>();
table_arrays.push_back(&tbl_arr);
tbl_arr.source_ = { header_begin_pos, header_end_pos, reader.source_path() };
@ -12877,7 +12875,7 @@ TOML_IMPL_NAMESPACE_START
// otherwise we're just making a table
else
{
table& tbl = parent->emplace<table>(key.segments.back()).first->second.ref_cast<table>();
table& tbl = parent->emplace<table>(last_segment).first->second.ref_cast<table>();
tbl.source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tbl;
}
@ -12933,29 +12931,51 @@ TOML_IMPL_NAMESPACE_START
}
}
void parse_key_value_pair_and_insert(table* tab)
bool parse_key_value_pair_and_insert(table* tbl)
{
return_if_error();
return_if_error({});
assert_not_eof();
assert_or_assume(is_string_delimiter(*cp) || is_bare_key_character(*cp));
push_parse_scope("key-value pair"sv);
auto kvp = parse_key_value_pair();
return_if_error();
// read the key into the key buffer
start_recording();
parse_key();
stop_recording(1u);
return_if_error({});
TOML_ASSERT(key_buffer.size() >= 1u);
TOML_ASSERT(kvp.key.segments.size() >= 1u);
// skip past any whitespace that followed the key
consume_leading_whitespace();
set_error_and_return_if_eof({});
// '='
if (*cp != U'=')
set_error_and_return_default("expected '=', saw '"sv, to_sv(*cp), "'"sv);
advance_and_return_if_error_or_eof({});
// skip past any whitespace that followed the '='
consume_leading_whitespace();
return_if_error({});
set_error_and_return_if_eof({});
// check that the next character could actually be a value
if (is_value_terminator(*cp))
set_error_and_return_default("expected value, saw '"sv, to_sv(*cp), "'"sv);
// if it's a dotted kvp we need to spawn the sub-tables if necessary,
// and set the target table to the second-to-last one in the chain
if (kvp.key.segments.size() > 1u)
if (key_buffer.size() > 1u)
{
for (size_t i = 0; i < kvp.key.segments.size() - 1u; i++)
for (size_t i = 0; i < key_buffer.size() - 1u; i++)
{
auto child = tab->get(kvp.key.segments[i]);
const auto segment = key_buffer[i];
auto child = tbl->get(segment);
if (!child)
{
child = tab->map_.emplace(std::move(kvp.key.segments[i]), new table{}).first->second.get();
child = tbl->map_.emplace(std::string{ segment }, new table{}).first->second.get();
dotted_key_tables.push_back(&child->ref_cast<table>());
child->source_ = kvp.value->source_;
child->source_ = key_buffer.source;
}
else if (!child->is_table()
|| !(impl::find(dotted_key_tables.begin(),
@ -12964,37 +12984,38 @@ TOML_IMPL_NAMESPACE_START
|| impl::find(implicit_tables.begin(),
implicit_tables.end(),
&child->ref_cast<table>())))
set_error_at(kvp.key.position,
{
set_error_at(key_buffer.source.begin,
"cannot redefine existing "sv,
to_sv(child->type()),
" as dotted key-value pair"sv);
else
child->source_.end = kvp.value->source_.end;
return_after_error({});
}
return_if_error();
tab = &child->ref_cast<table>();
tbl = &child->ref_cast<table>();
}
}
if (auto conflicting_node = tab->get(kvp.key.segments.back()))
// ensure this isn't a redefinition
if (auto conflicting_node = tbl->get(key_buffer.back()))
{
if (conflicting_node->type() == kvp.value->type())
set_error("cannot redefine existing "sv,
to_sv(conflicting_node->type()),
" '"sv,
to_sv(recording_buffer),
"'"sv);
else
set_error("cannot redefine existing "sv,
to_sv(conflicting_node->type()),
" '"sv,
to_sv(recording_buffer),
"' as "sv,
to_sv(kvp.value->type()));
set_error("cannot redefine existing "sv,
to_sv(conflicting_node->type()),
" '"sv,
to_sv(recording_buffer),
"'"sv);
return_after_error({});
}
return_if_error();
tab->map_.emplace(std::move(kvp.key.segments.back()), std::unique_ptr<node>{ kvp.value.release() });
// cache the last segment since it might get overwritten by nested tables etc.
auto last_segment = std::string{ key_buffer.back() };
// now we can actually parse the value
auto val = node_ptr{ parse_value() };
return_if_error({});
tbl->map_.emplace(std::move(last_segment), std::unique_ptr<node>{ val.release() });
return true;
}
void parse_document()
@ -13086,7 +13107,8 @@ TOML_IMPL_NAMESPACE_START
parser(utf8_reader_interface&& reader_) //
: reader{ reader_ }
{
root.source_ = { prev_pos, prev_pos, reader.source_path() };
root.source_ = { prev_pos, prev_pos, reader.source_path() };
key_buffer.source.path = reader.source_path();
if (!reader.peek_eof())
{

View File

@ -59,13 +59,13 @@ def main():
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|{platform}'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|{platform}'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>