From ff6f184d301a756e056d043ab56cfe9f7a2831a5 Mon Sep 17 00:00:00 2001 From: Mark Gillard Date: Thu, 4 Nov 2021 11:56:03 +0200 Subject: [PATCH] added `parse_benchmark` example also: - internal parser refactoring --- examples/CMakeLists.txt | 1 + examples/benchmark_data.toml | 94 +++++ examples/examples.h | 1 + examples/meson.build | 3 +- examples/parse_benchmark.cpp | 92 +++++ examples/parse_benchmark.vcxproj | 62 ++++ include/toml++/impl/forward_declarations.h | 21 +- include/toml++/impl/header_end.h | 4 + include/toml++/impl/header_start.h | 6 + include/toml++/impl/parser.inl | 52 ++- include/toml++/impl/std_string.inl | 3 +- include/toml++/impl/utf8.h | 10 + tests/meson.build | 3 - tests/settings.h | 4 +- toml++.sln | 7 + toml.hpp | 385 ++++++++++++++++++++- 16 files changed, 700 insertions(+), 48 deletions(-) create mode 100644 examples/benchmark_data.toml create mode 100644 examples/parse_benchmark.cpp create mode 100644 examples/parse_benchmark.vcxproj diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c4e7946..f5d85fd 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -20,6 +20,7 @@ function(add_example name) endfunction() add_example(error_printer) +add_example(parse_benchmark) add_example(simple_parser ARGS "${PROJECT_SOURCE_DIR}/example.toml") add_example(toml_generator ARGS 100) add_example(toml_to_json_transcoder ARGS "${PROJECT_SOURCE_DIR}/example.toml") diff --git a/examples/benchmark_data.toml b/examples/benchmark_data.toml new file mode 100644 index 0000000..f036c6e --- /dev/null +++ b/examples/benchmark_data.toml @@ -0,0 +1,94 @@ +addition-used = false +afraid-boiling-draconian = 1916-12-15T11:26:42+11:26 +boiling-whip = 12:23:17.000000129 +charming = 16771 +close-unbecoming = 14:49:02 +contain-terrible-neck = 1928-11-07T06:30:56 +creature = 0.4857 +crowded-profuse-capable = 1932-05-28 +deserted-cross-creature = 1931-12-26T04:31:04 +deserted-heavy = [ 2014-02-08, 1984-03-16, 1910-08-05 ] +fabulous = 0.3388 +ghost-birds-legal = 1989-09-02 +grandfather-weary = 10216 +haircut-dreary-broken = 'unadvised rejoice lewd crime grandfather rice imperfect' +harm-snow = 0.6724 +leather-aromatic-rabbit = false +license-harm = 1987-08-15T15:30:51+03:24 +naughty-self-close = 1916-09-21T01:53:27-02:59 +neck = 29653 +neck-crime-wistful = 1998-12-07 +rest-afraid = [ + 1912-06-23T07:00:07-07:46, + 1910-11-17T13:10:34, + 2014-08-03T04:37:12-06:36, + 1966-11-22T18:08:23+06:10, + 1985-03-01T08:11:38, + 1976-09-04T20:46:46+00:29, + 1964-05-18T20:13:27-01:25, + 1961-10-14T11:03:51.000011555+06:23, + 2005-07-13T02:57:15-01:46, + 2007-02-01T17:09:54-08:45, + 1952-03-06T09:15:04+01:44, + 1962-12-25T23:00:11+04:28 +] +rotten-best = 0.0325 +run-curious = true +run-meaty = 04:40:20.000003312 +scintillating-cream = 0.2604 +sisters-playground = 'week spiritual pause insidious uptight' +spiritual-borrow-messy = 16:49:32 +surprise-jail-babies = 2008-01-01 +title-unbiased = 1958-10-08 +unbecoming-scene-lewd = true +worried-spicy = 23:03:54 + +[contain] +ghost = 0.2471 +tank-lackadaisical = 1945-02-18T22:22:27+01:41 + + [contain.righteous-imperfect-remarkable] + ticket = 0.2412 + voyage = 'prefer silky night draconian three dreary decisive' + wilderness-draconian = 04:58:17 + + [contain.righteous-imperfect-remarkable.deeply-night-gold] + legal = 1981-07-04 + righteous = [ false, true, false, false, true ] + wilderness = 1900-12-24 + +[crime] +boiling-excuse-incandescent = 31173 +flat-rejoice = 0.8682 +furtive = 6866 +heavy-memory = 5545 +lackadaisical-terrible-overjoyed = [ 'harm acceptable naughty pause', 'page anxious threatening lewd' ] +reject-aromatic = [ false, true, true, true, false, true ] +reject-naughty = 11229 +scintillating-bake-harm = 0.8258 + +[license-bat] +adorable-blind-string = 1961-08-14 +bat = 1939-10-28 +blind-wilderness = 2004-07-14 + +[rapid] +borrow = true +jail-weary-furtive = 'room' +protective-sulky = 4737 +room-decisive-unbiased = 1998-11-01T12:23:58 +soap = 1985-05-06 +sprout-rich = 0.6026 + + [rapid.clean-leather] + blood-snow-mark = true + equable = 0.2923 + fabulous = 1979-07-24T00:53:39+06:22 + glorious-threatening = true + lewd-dull = 02:40:53.000027288 + +[run-overjoyed] +creature-cheerful = 11071 +respect-history-anxious = 0.4637 +vessel = 'curious' + diff --git a/examples/examples.h b/examples/examples.h index f4efbee..34a6bc3 100644 --- a/examples/examples.h +++ b/examples/examples.h @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef _WIN32 #ifdef _MSC_VER extern "C" __declspec(dllimport) int __stdcall SetConsoleOutputCP(unsigned int); diff --git a/examples/meson.build b/examples/meson.build index 17199db..71bb25e 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -8,7 +8,8 @@ examples = [ 'simple_parser', 'toml_to_json_transcoder', 'toml_generator', - 'error_printer' + 'error_printer', + 'parse_benchmark', ] foreach example : examples diff --git a/examples/parse_benchmark.cpp b/examples/parse_benchmark.cpp new file mode 100644 index 0000000..c306bda --- /dev/null +++ b/examples/parse_benchmark.cpp @@ -0,0 +1,92 @@ +// This file is a part of toml++ and is subject to the the terms of the MIT license. +// Copyright (c) Mark Gillard +// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT + +// This example is just a short-n-shiny benchmark. + +#include "examples.h" + +#define TOML_ENABLE_UNRELEASED_FEATURES 0 +#include + +namespace +{ + using namespace std::string_view_literals; + using namespace std::chrono_literals; + using clock = std::chrono::steady_clock; + using std::chrono::nanoseconds; + using std::chrono::duration; + + static constexpr size_t iterations = 10000; +} + +int main(int argc, char** argv) +{ + const auto file_path = std::string(argc > 1 ? std::string_view{ argv[1] } : "benchmark_data.toml"sv); + + // read the file into a string first to remove file I/O from the benchmark + std::string file_content; + { + std::ifstream file(file_path, std::ifstream::in | std::ifstream::binary | std::ifstream::ate); + if (!file) + { + std::cerr << "File '"sv << file_path << "'could not be opened for reading\n"sv; + return -1; + } + + const auto file_size = file.tellg(); + if (file_size == -1) + { + std::cerr << "File '"sv << file_path << "' could not be opened for reading\n"sv; + return -1; + } + file.seekg(0, std::ifstream::beg); + + file_content.resize(static_cast(file_size)); + file.read(file_content.data(), static_cast(file_size)); + if (!file.eof() && !file) + { + std::cerr << "Failed to read contents of file '"sv << file_path << "'\n"sv; + return -1; + } + } + + // parse once to make sure it isn't garbage + { +#if TOML_EXCEPTIONS + try + { + const auto result = toml::parse(file_content); + } + catch (const toml::parse_error& err) + { + std::cerr << err << "\n"; + return 1; + } +#else + const auto result = toml::parse(file_content); + if (!result) + std::cerr << result.error() << "\n"; + return 1; +#endif + } + + // run the benchmark + std::cout << "Parsing '"sv << file_path << "' "sv << iterations << " times...\n"sv; + nanoseconds cumulative; + for (size_t i = 0; i < iterations; i++) + { + { + const auto start = clock::now(); + const auto result = toml::parse(file_content); + cumulative += clock::now() - start; + } + } + const auto cumulative_sec = std::chrono::duration_cast>(cumulative).count(); + const auto mean_sec = cumulative_sec / static_cast(iterations); + std::cout << " total: "sv << cumulative_sec << " s\n"sv + << " mean: "sv << mean_sec << " s\n"sv; + + return 0; +} diff --git a/examples/parse_benchmark.vcxproj b/examples/parse_benchmark.vcxproj new file mode 100644 index 0000000..ea3c25a --- /dev/null +++ b/examples/parse_benchmark.vcxproj @@ -0,0 +1,62 @@ + + + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {407FCAA8-FC2C-424D-B44B-C6A1AFAD757A} + 10.0 + + + + Application + true + v142 + MultiByte + + + Application + false + v142 + true + MultiByte + + + + + + + + + Console + + + + ..\examples + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/include/toml++/impl/forward_declarations.h b/include/toml++/impl/forward_declarations.h index 34671bb..1394e0a 100644 --- a/include/toml++/impl/forward_declarations.h +++ b/include/toml++/impl/forward_declarations.h @@ -7,12 +7,6 @@ #include "preprocessor.h" #include "std_string.h" #include "std_new.h" -#include "header_start.h" - -//#--------------------------------------------------------------------------------------------------------------------- -//# INCLUDES -//#--------------------------------------------------------------------------------------------------------------------- - TOML_DISABLE_WARNINGS; #include #include @@ -25,6 +19,7 @@ TOML_DISABLE_WARNINGS; #include #include TOML_ENABLE_WARNINGS; +#include "header_start.h" //#--------------------------------------------------------------------------------------------------------------------- //# ENVIRONMENT GROUND-TRUTHS @@ -902,7 +897,7 @@ TOML_IMPL_NAMESPACE_START return static_cast>(val); } - // Q: "why not use the built-in fpclassify?" + // Q: "why not use std::fpclassify?" // A: Because it gets broken by -ffast-math and friends enum class fp_class : unsigned { @@ -930,9 +925,10 @@ TOML_IMPL_NAMESPACE_START return (val_bits & sign) ? fp_class::neg_inf : fp_class::pos_inf; } - // Q: "why not use std::find??" - // A: Because is _huge_ and std::find would be the only thing I used from it. + // Q: "why not use std::find and std::min?" + // A: Because is _huge_ and these would be the only things I used from it. // I don't want to impose such a heavy compile-time burden on users. + template TOML_PURE_GETTER inline auto find(Iterator start, Iterator end, const T& needle) noexcept // @@ -943,6 +939,13 @@ TOML_IMPL_NAMESPACE_START return &(*start); return nullptr; } + + template + TOML_PURE_GETTER + inline T& min(T & a, T & b) noexcept // + { + return a < b ? a : b; + } } TOML_IMPL_NAMESPACE_END; /// \endcond diff --git a/include/toml++/impl/header_end.h b/include/toml++/impl/header_end.h index d6e8788..d503cda 100644 --- a/include/toml++/impl/header_end.h +++ b/include/toml++/impl/header_end.h @@ -3,4 +3,8 @@ #include "preprocessor.h" #endif //# }} +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; diff --git a/include/toml++/impl/header_start.h b/include/toml++/impl/header_start.h index edeea8c..2bef418 100644 --- a/include/toml++/impl/header_start.h +++ b/include/toml++/impl/header_start.h @@ -4,3 +4,9 @@ #endif //# }} TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif diff --git a/include/toml++/impl/parser.inl b/include/toml++/impl/parser.inl index 1421106..ff1a18c 100644 --- a/include/toml++/impl/parser.inl +++ b/include/toml++/impl/parser.inl @@ -106,6 +106,18 @@ TOML_ANON_NAMESPACE_START return 0xFFFFFFFFu; return static_cast(static_cast(source_[position_++])); } + + [[maybe_unused]] TOML_NODISCARD + TOML_ATTR(nonnull) + constexpr size_t operator()(char* dest, size_t num) noexcept + { + TOML_ASSERT(!eof()); + + num = source_.length() - min(position_ + num, source_.length()); + std::memcpy(dest, source_.data() + position_, num); + position_ += num; + return num; + } }; template @@ -118,7 +130,7 @@ TOML_ANON_NAMESPACE_START public: TOML_NODISCARD_CTOR - explicit utf8_byte_stream(std::basic_istream& stream) // + explicit utf8_byte_stream(std::basic_istream& stream) noexcept(!TOML_COMPILER_EXCEPTIONS) // : source_{ &stream } { if (!source_->good()) // eof, fail, bad @@ -141,7 +153,7 @@ TOML_ANON_NAMESPACE_START } TOML_NODISCARD - bool peek_eof() const + bool peek_eof() const noexcept(!TOML_COMPILER_EXCEPTIONS) { using stream_traits = typename std::remove_pointer_t::traits_type; return eof() || source_->peek() == stream_traits::eof(); @@ -154,13 +166,23 @@ TOML_ANON_NAMESPACE_START } TOML_NODISCARD - unsigned int operator()() + unsigned int operator()() noexcept(!TOML_COMPILER_EXCEPTIONS) { auto val = source_->get(); if (val == std::basic_istream::traits_type::eof()) return 0xFFFFFFFFu; return static_cast(val); } + + [[maybe_unused]] TOML_NODISCARD + TOML_ATTR(nonnull) + constexpr size_t operator()(char* dest, size_t num) noexcept(!TOML_COMPILER_EXCEPTIONS) + { + TOML_ASSERT(!error() && !eof()); + + source_->read(dest, static_cast(num)); + return static_cast(source_->gcount()); + } }; struct utf8_codepoint @@ -196,10 +218,10 @@ TOML_ANON_NAMESPACE_START virtual const source_path_ptr& source_path() const noexcept = 0; TOML_NODISCARD - virtual const utf8_codepoint* read_next() = 0; + virtual const utf8_codepoint* read_next() noexcept(!TOML_COMPILER_EXCEPTIONS) = 0; TOML_NODISCARD - virtual bool peek_eof() const = 0; + virtual bool peek_eof() const noexcept(!TOML_COMPILER_EXCEPTIONS) = 0; #if !TOML_EXCEPTIONS @@ -225,11 +247,17 @@ TOML_ANON_NAMESPACE_START class TOML_EMPTY_BASES utf8_reader final : public utf8_reader_interface { private: + static constexpr size_t block_capacity = 32; utf8_byte_stream stream_; + char block_[block_capacity]; + size_t block_size_ = {}; + size_t block_end_ = {}; + impl::utf8_decoder decoder_; utf8_codepoint codepoints_[2]; size_t cp_idx_ = 1; uint8_t current_byte_count_ = {}; + source_path_ptr source_path_; #if !TOML_EXCEPTIONS optional err_; @@ -257,7 +285,7 @@ TOML_ANON_NAMESPACE_START } TOML_NODISCARD - const utf8_codepoint* read_next() final + const utf8_codepoint* read_next() noexcept(!TOML_COMPILER_EXCEPTIONS) final { TOML_ERROR_CHECK; @@ -297,9 +325,9 @@ TOML_ANON_NAMESPACE_START throw parse_error{ "An unspecified error occurred", prev.position, source_path_ }; } } -#endif +#endif // TOML_EXCEPTIONS - if (next_byte_raw >= 256u) + if TOML_UNLIKELY(next_byte_raw >= 256u) { if (stream_.eof()) { @@ -349,7 +377,7 @@ TOML_ANON_NAMESPACE_START } TOML_NODISCARD - bool peek_eof() const final + bool peek_eof() const noexcept(!TOML_COMPILER_EXCEPTIONS) final { return stream_.peek_eof(); } @@ -412,7 +440,7 @@ TOML_ANON_NAMESPACE_START return reader_.source_path(); } - const utf8_codepoint* read_next() final + const utf8_codepoint* read_next() noexcept(!TOML_COMPILER_EXCEPTIONS) final { TOML_ERROR_CHECK; @@ -463,7 +491,7 @@ TOML_ANON_NAMESPACE_START : head_; } - bool peek_eof() const final + bool peek_eof() const noexcept(!TOML_COMPILER_EXCEPTIONS) final { return reader_.peek_eof(); } @@ -3518,7 +3546,7 @@ TOML_ANON_NAMESPACE_START // open file with a custom-sized stack buffer std::ifstream file; - char file_buffer[sizeof(void*) * 1024u]; + alignas(32) char file_buffer[sizeof(void*) * 1024u]; file.rdbuf()->pubsetbuf(file_buffer, sizeof(file_buffer)); file.open(file_path_str, std::ifstream::in | std::ifstream::binary | std::ifstream::ate); if (!file.is_open()) diff --git a/include/toml++/impl/std_string.inl b/include/toml++/impl/std_string.inl index 6172ba6..78a47cc 100644 --- a/include/toml++/impl/std_string.inl +++ b/include/toml++/impl/std_string.inl @@ -13,8 +13,6 @@ #if TOML_ENABLE_WINDOWS_COMPAT #include "std_string.h" -#include "header_start.h" - #ifndef _WINDOWS_ #if TOML_INCLUDE_WINDOWS_H #include @@ -38,6 +36,7 @@ extern "C" __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int #endif // TOML_INCLUDE_WINDOWS_H #endif // _WINDOWS_ +#include "header_start.h" TOML_IMPL_NAMESPACE_START { diff --git a/include/toml++/impl/utf8.h b/include/toml++/impl/utf8.h index 90ff28c..12a83b3 100644 --- a/include/toml++/impl/utf8.h +++ b/include/toml++/impl/utf8.h @@ -10,6 +10,16 @@ TOML_IMPL_NAMESPACE_START { + TOML_PURE_GETTER + TOML_ATTR(nonnull) + constexpr bool is_ascii(const char* str, size_t size) noexcept + { + for (const char* const e = str + size; str < e; str++) + if (static_cast(*str) > 127u) + return false; + return true; + } + TOML_CONST_GETTER constexpr bool is_ascii_whitespace(char32_t codepoint) noexcept { diff --git a/tests/meson.build b/tests/meson.build index 18049e8..a549870 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -131,9 +131,6 @@ foreach cpp20 : cpp20_modes test_args += '-DTOML_ENABLE_UNRELEASED_FEATURES=0' endif - if counter % 6 == 3 - test_args += '-DTOML_HEADER_ONLY=1' - endif if counter % 2 == 1 test_args += '-DUSE_SINGLE_HEADER=1' endif diff --git a/tests/settings.h b/tests/settings.h index 0004802..017a5a5 100644 --- a/tests/settings.h +++ b/tests/settings.h @@ -6,9 +6,7 @@ // toml++ config #define TOML_UNDEF_MACROS 0 -#ifndef TOML_HEADER_ONLY -#define TOML_HEADER_ONLY 0 -#endif +#define TOML_HEADER_ONLY 0 #ifndef USE_SINGLE_HEADER #define USE_SINGLE_HEADER 0 #endif diff --git a/toml++.sln b/toml++.sln index b05def4..0175a50 100644 --- a/toml++.sln +++ b/toml++.sln @@ -81,6 +81,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_release_x86_noexcept_u EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_release_x86_unrel", "tests\vs\test_release_x86_unrel.vcxproj", "{B3077FF1-FC90-5C14-A69F-3524F62167B1}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "parse_benchmark", "examples\parse_benchmark.vcxproj", "{407FCAA8-FC2C-424D-B44B-C6A1AFAD757A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -233,6 +235,10 @@ Global {B3077FF1-FC90-5C14-A69F-3524F62167B1}.Debug|x64.Build.0 = Release|Win32 {B3077FF1-FC90-5C14-A69F-3524F62167B1}.Release|x64.ActiveCfg = Release|Win32 {B3077FF1-FC90-5C14-A69F-3524F62167B1}.Release|x64.Build.0 = Release|Win32 + {407FCAA8-FC2C-424D-B44B-C6A1AFAD757A}.Debug|x64.ActiveCfg = Debug|x64 + {407FCAA8-FC2C-424D-B44B-C6A1AFAD757A}.Debug|x64.Build.0 = Debug|x64 + {407FCAA8-FC2C-424D-B44B-C6A1AFAD757A}.Release|x64.ActiveCfg = Release|x64 + {407FCAA8-FC2C-424D-B44B-C6A1AFAD757A}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -274,6 +280,7 @@ Global {0D4D9D25-3F93-5C37-866E-F8B0AC23F851} = {4E25CF88-D7D8-4A9C-A52E-0D78281E82EC} {151E9E68-E325-5B08-8722-257F2B083BAD} = {4E25CF88-D7D8-4A9C-A52E-0D78281E82EC} {B3077FF1-FC90-5C14-A69F-3524F62167B1} = {4E25CF88-D7D8-4A9C-A52E-0D78281E82EC} + {407FCAA8-FC2C-424D-B44B-C6A1AFAD757A} = {412816A5-9D22-4A30-BCDF-ABFB54BB3735} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0926DDCC-88CD-4839-A82D-D9B99E02A0B1} diff --git a/toml.hpp b/toml.hpp index 9900755..06adcfd 100644 --- a/toml.hpp +++ b/toml.hpp @@ -976,7 +976,6 @@ TOML_NAMESPACE_END; //******** impl/forward_declarations.h ******************************************************************************* -TOML_PUSH_WARNINGS; TOML_DISABLE_WARNINGS; #include #include @@ -989,6 +988,13 @@ TOML_DISABLE_WARNINGS; #include #include TOML_ENABLE_WARNINGS; +TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif #ifndef TOML_DISABLE_ENVIRONMENT_CHECKS #define TOML_ENV_MESSAGE \ @@ -1737,7 +1743,7 @@ TOML_IMPL_NAMESPACE_START return static_cast>(val); } - // Q: "why not use the built-in fpclassify?" + // Q: "why not use std::fpclassify?" // A: Because it gets broken by -ffast-math and friends enum class fp_class : unsigned { @@ -1765,9 +1771,10 @@ TOML_IMPL_NAMESPACE_START return (val_bits & sign) ? fp_class::neg_inf : fp_class::pos_inf; } - // Q: "why not use std::find??" - // A: Because is _huge_ and std::find would be the only thing I used from it. + // Q: "why not use std::find and std::min?" + // A: Because is _huge_ and these would be the only things I used from it. // I don't want to impose such a heavy compile-time burden on users. + template TOML_PURE_GETTER inline auto find(Iterator start, Iterator end, const T& needle) noexcept // @@ -1778,14 +1785,31 @@ TOML_IMPL_NAMESPACE_START return &(*start); return nullptr; } + + template + TOML_PURE_GETTER + inline T& min(T & a, T & b) noexcept // + { + return a < b ? a : b; + } } TOML_IMPL_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/print_to_stream.h ************************************************************************************ TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_IMPL_NAMESPACE_START { @@ -1918,11 +1942,21 @@ TOML_IMPL_NAMESPACE_START } TOML_IMPL_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/source_region.h ************************************************************************************** TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_NAMESPACE_START { @@ -2002,11 +2036,21 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/date_time.h ****************************************************************************************** TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_NAMESPACE_START { @@ -2310,6 +2354,10 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/node.h *********************************************************************************************** @@ -2318,6 +2366,12 @@ TOML_DISABLE_WARNINGS; #include TOML_ENABLE_WARNINGS; TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_NAMESPACE_START { @@ -2812,6 +2866,10 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/node_view.h ****************************************************************************************** @@ -2822,6 +2880,13 @@ TOML_DISABLE_WARNINGS; #include TOML_ENABLE_WARNINGS; TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif + TOML_DISABLE_ARITHMETIC_WARNINGS; TOML_NAMESPACE_START @@ -3340,11 +3405,22 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/value.h ********************************************************************************************** TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif + TOML_DISABLE_ARITHMETIC_WARNINGS; // clang-format off @@ -4427,11 +4503,21 @@ TOML_NAMESPACE_END; #endif +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/make_node.h ****************************************************************************************** TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_IMPL_NAMESPACE_START { @@ -4549,11 +4635,21 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/array.h ********************************************************************************************** TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_IMPL_NAMESPACE_START { @@ -5407,6 +5503,10 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/table.h ********************************************************************************************** @@ -5416,6 +5516,12 @@ TOML_DISABLE_WARNINGS; #include TOML_ENABLE_WARNINGS; TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_IMPL_NAMESPACE_START { @@ -6317,14 +6423,34 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/utf8.h *********************************************************************************************** TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_IMPL_NAMESPACE_START { + TOML_PURE_GETTER + TOML_ATTR(nonnull) + constexpr bool is_ascii(const char* str, size_t size) noexcept + { + for (const char* const e = str + size; str < e; str++) + if (static_cast(*str) > 127u) + return false; + return true; + } + TOML_CONST_GETTER constexpr bool is_ascii_whitespace(char32_t codepoint) noexcept { @@ -7244,6 +7370,10 @@ TOML_IMPL_NAMESPACE_START } TOML_IMPL_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/parse_error.h **************************************************************************************** @@ -7256,6 +7386,12 @@ TOML_DISABLE_WARNINGS; #endif TOML_ENABLE_WARNINGS; TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif #if defined(DOXYGEN) || !TOML_EXCEPTIONS #define TOML_PARSE_ERROR_BASE @@ -7349,6 +7485,10 @@ TOML_NAMESPACE_END; #undef TOML_PARSE_ERROR_BASE +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; #endif // TOML_ENABLE_PARSER @@ -7358,6 +7498,12 @@ TOML_POP_WARNINGS; #if defined(DOXYGEN) || (TOML_ENABLE_PARSER && !TOML_EXCEPTIONS) TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_NAMESPACE_START { @@ -7632,6 +7778,10 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; #endif // TOML_ENABLE_PARSER && !TOML_EXCEPTIONS @@ -7641,6 +7791,12 @@ TOML_POP_WARNINGS; #if TOML_ENABLE_PARSER TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_NAMESPACE_START { @@ -7733,6 +7889,10 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; #endif // TOML_ENABLE_PARSER @@ -7742,6 +7902,12 @@ TOML_POP_WARNINGS; #if TOML_ENABLE_FORMATTERS TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_IMPL_NAMESPACE_START { @@ -7893,6 +8059,10 @@ TOML_IMPL_NAMESPACE_START } TOML_IMPL_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; #endif // TOML_ENABLE_FORMATTERS @@ -7902,6 +8072,12 @@ TOML_POP_WARNINGS; #if TOML_ENABLE_FORMATTERS TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_NAMESPACE_START { @@ -7984,6 +8160,10 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; #endif // TOML_ENABLE_FORMATTERS @@ -7993,6 +8173,12 @@ TOML_POP_WARNINGS; #if TOML_ENABLE_FORMATTERS TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_NAMESPACE_START { @@ -8057,6 +8243,10 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; #endif // TOML_ENABLE_FORMATTERS @@ -8066,6 +8256,12 @@ TOML_POP_WARNINGS; #if TOML_ENABLE_FORMATTERS TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_NAMESPACE_START { @@ -8135,6 +8331,10 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; #endif // TOML_ENABLE_FORMATTERS @@ -8145,8 +8345,6 @@ TOML_POP_WARNINGS; #if TOML_ENABLE_WINDOWS_COMPAT -TOML_PUSH_WARNINGS; - #ifndef _WINDOWS_ #if TOML_INCLUDE_WINDOWS_H #include @@ -8171,6 +8369,14 @@ extern "C" __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int #endif // TOML_INCLUDE_WINDOWS_H #endif // _WINDOWS_ +TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif + TOML_IMPL_NAMESPACE_START { TOML_EXTERNAL_LINKAGE @@ -8228,6 +8434,10 @@ TOML_IMPL_NAMESPACE_START } TOML_IMPL_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; #endif // TOML_ENABLE_WINDOWS_COMPAT @@ -8247,6 +8457,12 @@ TOML_DISABLE_WARNINGS; #endif TOML_ENABLE_WARNINGS; TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_ANON_NAMESPACE_START { @@ -8683,11 +8899,21 @@ TOML_IMPL_NAMESPACE_START } TOML_IMPL_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/node.inl ********************************************************************************************* TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_NAMESPACE_START { @@ -8728,11 +8954,21 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/node_view.inl **************************************************************************************** TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif #if TOML_EXTERN_TEMPLATES && TOML_IMPLEMENTATION @@ -8800,11 +9036,21 @@ TOML_NAMESPACE_END; #endif // TOML_EXTERN_TEMPLATES +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/value.inl ******************************************************************************************** TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif #if TOML_EXTERN_TEMPLATES && TOML_IMPLEMENTATION @@ -8877,11 +9123,21 @@ TOML_NAMESPACE_END; #endif // TOML_EXTERN_TEMPLATES +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/array.inl ******************************************************************************************** TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_ANON_NAMESPACE_START { @@ -9107,11 +9363,21 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/table.inl ******************************************************************************************** TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_ANON_NAMESPACE_START { @@ -9269,6 +9535,10 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; //******** impl/parser.inl ******************************************************************************************* @@ -9289,6 +9559,12 @@ TOML_DISABLE_WARNINGS; #endif TOML_ENABLE_WARNINGS; TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_ANON_NAMESPACE_START { @@ -9356,6 +9632,18 @@ TOML_ANON_NAMESPACE_START return 0xFFFFFFFFu; return static_cast(static_cast(source_[position_++])); } + + [[maybe_unused]] TOML_NODISCARD + TOML_ATTR(nonnull) + constexpr size_t operator()(char* dest, size_t num) noexcept + { + TOML_ASSERT(!eof()); + + num = source_.length() - min(position_ + num, source_.length()); + std::memcpy(dest, source_.data() + position_, num); + position_ += num; + return num; + } }; template @@ -9368,7 +9656,7 @@ TOML_ANON_NAMESPACE_START public: TOML_NODISCARD_CTOR - explicit utf8_byte_stream(std::basic_istream& stream) // + explicit utf8_byte_stream(std::basic_istream& stream) noexcept(!TOML_COMPILER_EXCEPTIONS) // : source_{ &stream } { if (!source_->good()) // eof, fail, bad @@ -9391,7 +9679,7 @@ TOML_ANON_NAMESPACE_START } TOML_NODISCARD - bool peek_eof() const + bool peek_eof() const noexcept(!TOML_COMPILER_EXCEPTIONS) { using stream_traits = typename std::remove_pointer_t::traits_type; return eof() || source_->peek() == stream_traits::eof(); @@ -9404,13 +9692,23 @@ TOML_ANON_NAMESPACE_START } TOML_NODISCARD - unsigned int operator()() + unsigned int operator()() noexcept(!TOML_COMPILER_EXCEPTIONS) { auto val = source_->get(); if (val == std::basic_istream::traits_type::eof()) return 0xFFFFFFFFu; return static_cast(val); } + + [[maybe_unused]] TOML_NODISCARD + TOML_ATTR(nonnull) + constexpr size_t operator()(char* dest, size_t num) noexcept(!TOML_COMPILER_EXCEPTIONS) + { + TOML_ASSERT(!error() && !eof()); + + source_->read(dest, static_cast(num)); + return static_cast(source_->gcount()); + } }; struct utf8_codepoint @@ -9446,10 +9744,10 @@ TOML_ANON_NAMESPACE_START virtual const source_path_ptr& source_path() const noexcept = 0; TOML_NODISCARD - virtual const utf8_codepoint* read_next() = 0; + virtual const utf8_codepoint* read_next() noexcept(!TOML_COMPILER_EXCEPTIONS) = 0; TOML_NODISCARD - virtual bool peek_eof() const = 0; + virtual bool peek_eof() const noexcept(!TOML_COMPILER_EXCEPTIONS) = 0; #if !TOML_EXCEPTIONS @@ -9475,11 +9773,17 @@ TOML_ANON_NAMESPACE_START class TOML_EMPTY_BASES utf8_reader final : public utf8_reader_interface { private: + static constexpr size_t block_capacity = 32; utf8_byte_stream stream_; + char block_[block_capacity]; + size_t block_size_ = {}; + size_t block_end_ = {}; + impl::utf8_decoder decoder_; utf8_codepoint codepoints_[2]; size_t cp_idx_ = 1; uint8_t current_byte_count_ = {}; + source_path_ptr source_path_; #if !TOML_EXCEPTIONS optional err_; @@ -9507,7 +9811,7 @@ TOML_ANON_NAMESPACE_START } TOML_NODISCARD - const utf8_codepoint* read_next() final + const utf8_codepoint* read_next() noexcept(!TOML_COMPILER_EXCEPTIONS) final { TOML_ERROR_CHECK; @@ -9547,9 +9851,9 @@ TOML_ANON_NAMESPACE_START throw parse_error{ "An unspecified error occurred", prev.position, source_path_ }; } } -#endif +#endif // TOML_EXCEPTIONS - if (next_byte_raw >= 256u) + if TOML_UNLIKELY(next_byte_raw >= 256u) { if (stream_.eof()) { @@ -9599,7 +9903,7 @@ TOML_ANON_NAMESPACE_START } TOML_NODISCARD - bool peek_eof() const final + bool peek_eof() const noexcept(!TOML_COMPILER_EXCEPTIONS) final { return stream_.peek_eof(); } @@ -9662,7 +9966,7 @@ TOML_ANON_NAMESPACE_START return reader_.source_path(); } - const utf8_codepoint* read_next() final + const utf8_codepoint* read_next() noexcept(!TOML_COMPILER_EXCEPTIONS) final { TOML_ERROR_CHECK; @@ -9713,7 +10017,7 @@ TOML_ANON_NAMESPACE_START : head_; } - bool peek_eof() const final + bool peek_eof() const noexcept(!TOML_COMPILER_EXCEPTIONS) final { return reader_.peek_eof(); } @@ -12759,7 +13063,7 @@ TOML_ANON_NAMESPACE_START // open file with a custom-sized stack buffer std::ifstream file; - char file_buffer[sizeof(void*) * 1024u]; + alignas(32) char file_buffer[sizeof(void*) * 1024u]; file.rdbuf()->pubsetbuf(file_buffer, sizeof(file_buffer)); file.open(file_path_str, std::ifstream::in | std::ifstream::binary | std::ifstream::ate); if (!file.is_open()) @@ -12885,6 +13189,10 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; #endif // TOML_ENABLE_PARSER @@ -12894,6 +13202,12 @@ TOML_POP_WARNINGS; #if TOML_ENABLE_FORMATTERS TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_IMPL_NAMESPACE_START { @@ -13193,6 +13507,10 @@ TOML_IMPL_NAMESPACE_START } TOML_IMPL_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; #endif // TOML_ENABLE_FORMATTERS @@ -13202,6 +13520,13 @@ TOML_POP_WARNINGS; #if TOML_ENABLE_FORMATTERS TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif + TOML_DISABLE_ARITHMETIC_WARNINGS; TOML_ANON_NAMESPACE_START @@ -13575,6 +13900,10 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; #endif // TOML_ENABLE_FORMATTERS @@ -13584,6 +13913,12 @@ TOML_POP_WARNINGS; #if TOML_ENABLE_FORMATTERS TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_NAMESPACE_START { @@ -13681,6 +14016,10 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; #endif // TOML_ENABLE_FORMATTERS @@ -13690,6 +14029,12 @@ TOML_POP_WARNINGS; #if TOML_ENABLE_FORMATTERS TOML_PUSH_WARNINGS; +#ifdef _MSC_VER +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif TOML_NAMESPACE_START { @@ -13831,6 +14176,10 @@ TOML_NAMESPACE_START } TOML_NAMESPACE_END; +#ifdef _MSC_VER +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif TOML_POP_WARNINGS; #endif // TOML_ENABLE_FORMATTERS