1
0
Fork 0

Windows compat

windows
May B. 2020-11-11 20:25:03 +01:00
parent 18c840b945
commit ebada328e8
90 changed files with 6510 additions and 3610 deletions

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
.vscode
build
build*
docs
external
resource/*/.*

View File

@ -8,6 +8,7 @@ option(USE_FMA "Use fma" 1)
option(LOG_DEBUG "Show debug logs" 0)
option(LOG_TRACE "Show trace logs" 0)
option(NATIVE "Build with -march=native" 0)
option(GL_OLD "Use OpenGL 4.2 not 4.6" 0)
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
@ -23,10 +24,15 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
if(WIN32)
add_definitions(/std:c++latest)
add_compile_definitions(WIN32_LEAN_AND_MEAN=)
else()
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
endif()
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_compile_definitions(FIXED_WINDOW=${FIXED_WINDOW} LOG_DEBUG=${LOG_DEBUG} LOG_TRACE=${LOG_TRACE} HN_USE_FILESYSTEM=1)
add_compile_definitions(FIXED_WINDOW=${FIXED_WINDOW} LOG_DEBUG=${LOG_DEBUG} LOG_TRACE=${LOG_TRACE} GL_OLD=${GL_OLD} HN_USE_FILESYSTEM=1)
if(PROFILING)
add_compile_definitions(TRACY_ENABLE=1)
endif(PROFILING)
@ -38,23 +44,39 @@ if(SIMD_LEVEL EQUAL "avx2")
elseif(SIMD_LEVEL EQUAL "avx512f")
add_compile_definitions(FN_COMPILE_AVX512=1)
endif()
add_definitions(-m${SIMD_LEVEL})
if(WIN32)
add_definitions(/arch:AVX2)
else()
add_definitions(-m${SIMD_LEVEL})
endif()
if(USE_FMA)
add_definitions(-mfma)
if(WIN32)
add_definitions(/GL /fp:fast)
else()
add_definitions(-mfma)
endif()
endif(USE_FMA)
file(GLOB_RECURSE CORE_SOURCES "src/core/*.cpp" "deps/tracy/TracyClient.cpp")
set(CORE_HEADERS "deps/toml++" "deps/robin_hood" "deps/libguarded" "deps/tracy")
set(CORE_LIBS pthread dl glm::glm_static picoquic-core zstd::zstd_static)
set(CORE_LIBS glm::glm_static zstd::zstd_static) # picoquic
file(GLOB_RECURSE CLIENT_SOURCES "src/client/*.cpp" "deps/imgui/*.cpp" "deps/meshoptimizer/*.cpp" "deps/gl3w/gl3w.c" "deps/volk/volk.c")
set(CLIENT_HEADERS "deps/imgui" "deps/meshoptimizer" "deps/gl3w" "deps/volk")
set(CLIENT_HEADERS "deps/imgui" "deps/meshoptimizer" "deps/gl3w" "deps/volk") # vulkan
set(CLIENT_LIBS glfw)
file(GLOB_RECURSE SERVER_SOURCES "src/server/*.cpp" "deps/FastNoiseSIMD/*.cpp")
set(SERVER_HEADERS "deps/FastNoiseSIMD")
set(SERVER_LINKED)
if(WIN32)
set(CLIENT_HEADERS ${CLIENT_HEADERS} $ENV{VULKAN_SDK}\\include)
find_package(OpenSSL)
set(CORE_LIBS ${CORE_LIBS} ${CMAKE_BINARY_DIR}/libs/*.lib ${OPENSSL_LIBRARIES} ws2_32)
else()
set(CORE_LIBS ${CORE_LIBS} picoquic-core pthread dl)
endif()
# All in one exec
add_executable(univerxel "src/main.cpp" ${CORE_SOURCES} ${CLIENT_SOURCES} ${SERVER_SOURCES})
target_compile_features(univerxel PUBLIC cxx_std_17)

View File

@ -14,6 +14,7 @@ Work in progress galaxy down to atom (mostly centimeter) online voxel game
- [Optionally](#optionally)
- [Installation](#installation)
- [Additionally](#additionally)
- [Windows](#windows)
- [RoadMap](#roadmap)
- [License](#license)
- [Contact](#contact)
@ -102,6 +103,7 @@ PROFILING | Tracy profiling | `0`
LOG_DEBUG | Debug logs | `0`
LOG_TRACE | Trace logs | `0`
NATIVE | Optimize for native CPU | `0`
GL_OLD | Use OpenGL 4.2 not 4.6 | `0`
1. Build Make
```sh
@ -132,6 +134,14 @@ cd resource/textures-src
./merge.py <args> # Combine grey images to RGB
```
### Windows
1. Setup Visual Studio 2017+ with C++
2. Clone picotls and picoquic in a separate directory
3. Set `%OPENSSL64DIR%` and check `WindowsPort.md` and `Readme.md` note from respective library
4. Compile then with MsBuild
5. Copy picoquic.lib, picotls-openssl.lib and picotls-fusion.lib to build/libs
6. Build univerxel with cmake `-A x64` and MsBuild
<!-- ROADMAP -->
## RoadMap

View File

@ -46,6 +46,9 @@
- [~] CI build
- [ ] CMake package
- [x] GitLab CI
- Platfoms
- [x] Linux
- [~] Windows
- [ ] Universe
- [ ] Galaxy
- [ ] Rotation
@ -107,5 +110,6 @@
- [ ] Deferred
- [ ] Cascaded shadow maps
- [ ] Ray Tracing
- [ ] Avoid transparent back-face
- [ ] Translucency
- Back face Depth based

View File

@ -4,45 +4,6 @@ cmake_policy(SET CMP0048 NEW)
project(picoquic VERSION 0.0.1 LANGUAGES C CXX)
find_package (Threads REQUIRED)
add_subdirectory("picotls")
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_FLAGS "-std=c99 -Wall -Werror -O2 -g ${CC_WARNING_FLAGS} ${CMAKE_C_FLAGS}")
if(DISABLE_DEBUG_PRINTF)
set(CMAKE_C_FLAGS "-DDISABLE_DEBUG_PRINTF ${CMAKE_C_FLAGS}")
endif()
set(PICOQUIC_LIBRARY_FILES
bbr.c
bytestream.c
cc_common.c
cubic.c
fastcc.c
frames.c
intformat.c
logger.c
logwriter.c
newreno.c
packet.c
picohash.c
picosocks.c
picosplay.c
quicctx.c
sacks.c
sender.c
sim_link.c
sockloop.c
spinbit.c
ticket_store.c
token_store.c
tls_api.c
transport.c
unified_log.c
util.c
)
set(PICOQUIC_CORE_HEADERS
picoquic.h
picosocks.h
@ -56,5 +17,50 @@ set(PICOQUIC_CORE_HEADERS
find_package(OpenSSL)
include_directories(picoquic "picotls/include" ${OPENSSL_INCLUDE_DIR})
add_library(picoquic-core ${PICOQUIC_CORE_HEADERS} ${PICOQUIC_LIBRARY_FILES})
target_link_libraries(picoquic-core picotls-core picotls-openssl picotls-fusion ${OPENSSL_LIBRARIES})
if(WIN32)
MESSAGE(WARNING "Please build picoquic and picotls with Visual Studio")
MESSAGE(WARNING "Then put picoquic.lib, picotls-core.lib picotls-openssl.lib and picotls-fusion.lib in build/libs")
else()
add_subdirectory("picotls")
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_FLAGS "-std=c99 -O2 -g ${CC_WARNING_FLAGS} ${CMAKE_C_FLAGS}")
if(DISABLE_DEBUG_PRINTF)
set(CMAKE_C_FLAGS "-DDISABLE_DEBUG_PRINTF ${CMAKE_C_FLAGS}")
endif()
set(PICOQUIC_LIBRARY_FILES
bbr.c
bytestream.c
cc_common.c
cubic.c
fastcc.c
frames.c
intformat.c
logger.c
logwriter.c
newreno.c
packet.c
picohash.c
picosocks.c
picosplay.c
quicctx.c
sacks.c
sender.c
sim_link.c
sockloop.c
spinbit.c
ticket_store.c
token_store.c
tls_api.c
transport.c
unified_log.c
util.c
)
add_library(picoquic-core ${PICOQUIC_CORE_HEADERS} ${PICOQUIC_LIBRARY_FILES})
target_link_libraries(picoquic-core picotls-core picotls-openssl picotls-fusion ${OPENSSL_LIBRARIES})
endif()

16
deps/toml++/LICENSE vendored Normal file
View File

@ -0,0 +1,16 @@
MIT License
Copyright (c) 2019-2020 Mark Gillard <mark.gillard@outlook.com.au>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

137
deps/toml++/toml.h vendored
View File

@ -1,19 +1,20 @@
#define TOML_HEADER_ONLY 0
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
//# Copyright (c) 2019-2020 Mark Gillard <mark.gillard@outlook.com.au>
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT
//# {{
#ifndef INCLUDE_TOMLPLUSPLUS_H
#define INCLUDE_TOMLPLUSPLUS_H
//# }}
//# Note: most of these would be included transitively but
//# they're listed explicitly here because this file
//# is used as the source for generate_single_header.py.
#include "toml_preprocessor.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_SPAM_WARNINGS
#include "toml_common.h"
#include "toml_date_time.h"
#include "toml_print_to_stream.h"
@ -22,7 +23,6 @@
#include "toml_array.h"
#include "toml_table.h"
#include "toml_node_view.h"
#include "toml_utf8_generated.h"
#include "toml_utf8.h"
#include "toml_formatter.h"
#include "toml_default_formatter.h"
@ -40,68 +40,109 @@
#include "toml_default_formatter.hpp"
#include "toml_json_formatter.hpp"
#if TOML_PARSER
#include "toml_utf8_streams.hpp"
#include "toml_parser.hpp"
#endif // TOML_PARSER
#if !TOML_ALL_INLINE
#if !TOML_HEADER_ONLY
#include "toml_instantiations.hpp"
#endif // !TOML_ALL_INLINE
#endif // !TOML_HEADER_ONLY
#endif // TOML_IMPLEMENTATION
TOML_POP_WARNINGS // TOML_DISABLE_SPAM_WARNINGS
// macro hygiene
#if TOML_UNDEF_MACROS
#undef TOML_INT_CHARCONV
#undef TOML_FLOAT_CHARCONV
#undef TOML_ABI_NAMESPACES
#undef TOML_ABI_NAMESPACE_BOOL
#undef TOML_ABI_NAMESPACE_END
#undef TOML_ABI_NAMESPACE_START
#undef TOML_ALWAYS_INLINE
#undef TOML_ANON_NAMESPACE
#undef TOML_ANON_NAMESPACE_END
#undef TOML_ANON_NAMESPACE_START
#undef TOML_ARM
#undef TOML_ASSERT
#undef TOML_ASSUME
#undef TOML_ASYMMETRICAL_EQUALITY_OPS
#undef TOML_ATTR
#undef TOML_PUSH_WARNINGS
#undef TOML_DISABLE_SWITCH_WARNINGS
#undef TOML_CLANG
#undef TOML_COMPILER_EXCEPTIONS
#undef TOML_CONCAT
#undef TOML_CONCAT_1
#undef TOML_CONSTEVAL
#undef TOML_CPP
#undef TOML_DISABLE_ARITHMETIC_WARNINGS
#undef TOML_DISABLE_INIT_WARNINGS
#undef TOML_DISABLE_VTABLE_WARNINGS
#undef TOML_DISABLE_PADDING_WARNINGS
#undef TOML_DISABLE_FLOAT_WARNINGS
#undef TOML_DISABLE_SPAM_WARNINGS
#undef TOML_DISABLE_SHADOW_WARNINGS
#undef TOML_DISABLE_SUGGEST_WARNINGS
#undef TOML_DISABLE_ALL_WARNINGS
#undef TOML_POP_WARNINGS
#undef TOML_ALWAYS_INLINE
#undef TOML_NEVER_INLINE
#undef TOML_ASSUME
#undef TOML_UNREACHABLE
#undef TOML_INTERFACE
#undef TOML_DISABLE_SWITCH_WARNINGS
#undef TOML_DISABLE_WARNINGS
#undef TOML_ENABLE_WARNINGS
#undef TOML_EMPTY_BASES
#undef TOML_CPP_VERSION
#undef TOML_CPP
#undef TOML_MAY_THROW
#undef TOML_NO_DEFAULT_CASE
#undef TOML_CONSTEVAL
#undef TOML_LIKELY
#undef TOML_UNLIKELY
#undef TOML_NODISCARD_CTOR
#undef TOML_MAKE_VERSION
#undef TOML_EVAL_BOOL_0
#undef TOML_EVAL_BOOL_1
#undef TOML_EXTERNAL_LINKAGE
#undef TOML_FLOAT128
#undef TOML_FLOAT16
#undef TOML_FLOAT_CHARCONV
#undef TOML_FP16
#undef TOML_GCC
#undef TOML_HAS_ATTR
#undef TOML_HAS_CUSTOM_OPTIONAL_TYPE
#undef TOML_HAS_INCLUDE
#undef TOML_ICC
#undef TOML_ICC_CL
#undef TOML_IMPLEMENTATION
#undef TOML_IMPL_NAMESPACE_END
#undef TOML_IMPL_NAMESPACE_START
#undef TOML_INT128
#undef TOML_INTELLISENSE
#undef TOML_INTERFACE
#undef TOML_INTERNAL_LINKAGE
#undef TOML_INT_CHARCONV
#undef TOML_LANG_AT_LEAST
#undef TOML_LANG_EFFECTIVE_VERSION
#undef TOML_LANG_HIGHER_THAN
#undef TOML_LANG_AT_LEAST
#undef TOML_LANG_UNRELEASED
#undef TOML_STRING_PREFIX_1
#undef TOML_STRING_PREFIX
#undef TOML_UNDEF_MACROS
#undef TOML_RELOPS_REORDERING
#undef TOML_ASYMMETRICAL_EQUALITY_OPS
#undef TOML_ALL_INLINE
#undef TOML_IMPLEMENTATION
#undef TOML_EXTERNAL_LINKAGE
#undef TOML_INTERNAL_LINKAGE
#undef TOML_INTERNAL_NAMESPACE
#undef TOML_COMPILER_EXCEPTIONS
#undef TOML_TRIVIAL_ABI
#undef TOML_ABI_NAMESPACES
#undef TOML_ABI_NAMESPACE_START
#undef TOML_ABI_NAMESPACE_END
#undef TOML_PARSER_TYPENAME
#undef TOML_LAUNDER
#undef TOML_LIFETIME_HOOKS
#undef TOML_LIKELY
#undef TOML_MAKE_BITOPS
#undef TOML_MAKE_VERSION
#undef TOML_MAY_THROW
#undef TOML_MSVC
#undef TOML_NAMESPACE
#undef TOML_NAMESPACE_END
#undef TOML_NAMESPACE_START
#undef TOML_NEVER_INLINE
#undef TOML_NODISCARD_CTOR
#undef TOML_NO_DEFAULT_CASE
#undef TOML_PARSER_TYPENAME
#undef TOML_POP_WARNINGS
#undef TOML_PUSH_WARNINGS
#undef TOML_SA_LIST_BEG
#undef TOML_SA_LIST_END
#undef TOML_SA_LIST_NEW
#undef TOML_SA_LIST_NXT
#undef TOML_SA_LIST_SEP
#undef TOML_SA_NATIVE_VALUE_TYPE_LIST
#undef TOML_SA_NEWLINE
#undef TOML_SA_NODE_TYPE_LIST
#undef TOML_SA_UNWRAPPED_NODE_TYPE_LIST
#undef TOML_SA_VALUE_EXACT_FUNC_MESSAGE
#undef TOML_SA_VALUE_FUNC_MESSAGE
#undef TOML_SA_VALUE_MESSAGE_CONST_CHAR8
#undef TOML_SA_VALUE_MESSAGE_U8STRING_VIEW
#undef TOML_SA_VALUE_MESSAGE_WSTRING
#undef TOML_SIMPLE_STATIC_ASSERT_MESSAGES
#undef TOML_TRIVIAL_ABI
#undef TOML_UINT128
#undef TOML_UNLIKELY
#undef TOML_UNREACHABLE
#undef TOML_USING_ANON_NAMESPACE
#endif
//# {{
#endif // INCLUDE_TOMLPLUSPLUS_H
//# }}

File diff suppressed because it is too large Load Diff

View File

@ -13,41 +13,104 @@
#include "toml_array.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_SUGGEST_WARNINGS
namespace toml
TOML_NAMESPACE_START
{
#if TOML_LIFETIME_HOOKS
TOML_EXTERNAL_LINKAGE
void array::preinsertion_resize(size_t idx, size_t count) noexcept
void array::lh_ctor() noexcept
{
const auto new_size = values.size() + count;
const auto inserting_at_end = idx == values.size();
values.resize(new_size);
if (!inserting_at_end)
{
for (size_t r = new_size, e = idx + count, l = e; r-- > e; l--)
values[r] = std::move(values[l]);
}
TOML_ARRAY_CREATED;
}
TOML_EXTERNAL_LINKAGE
array::array() noexcept = default;
void array::lh_dtor() noexcept
{
TOML_ARRAY_DESTROYED;
}
#endif
TOML_EXTERNAL_LINKAGE
array::array() noexcept
{
#if TOML_LIFETIME_HOOKS
lh_ctor();
#endif
}
TOML_EXTERNAL_LINKAGE
array::array(const array& other) noexcept
: node{ other }
{
elements.reserve(other.elements.size());
for (const auto& elem : other)
elements.emplace_back(impl::make_node(elem));
#if TOML_LIFETIME_HOOKS
lh_ctor();
#endif
}
TOML_EXTERNAL_LINKAGE
array::array(array&& other) noexcept
: node{ std::move(other) },
values{ std::move(other.values) }
{}
elements{ std::move(other.elements) }
{
#if TOML_LIFETIME_HOOKS
lh_ctor();
#endif
}
TOML_EXTERNAL_LINKAGE
array& array::operator= (const array& rhs) noexcept
{
if (&rhs != this)
{
node::operator=(rhs);
elements.clear();
elements.reserve(rhs.elements.size());
for (const auto& elem : rhs)
elements.emplace_back(impl::make_node(elem));
}
return *this;
}
TOML_EXTERNAL_LINKAGE
array& array::operator= (array&& rhs) noexcept
{
node::operator=(std::move(rhs));
values = std::move(rhs.values);
if (&rhs != this)
{
node::operator=(std::move(rhs));
elements = std::move(rhs.elements);
}
return *this;
}
TOML_EXTERNAL_LINKAGE
array::~array() noexcept
{
#if TOML_LIFETIME_HOOKS
lh_dtor();
#endif
}
TOML_EXTERNAL_LINKAGE
void array::preinsertion_resize(size_t idx, size_t count) noexcept
{
TOML_ASSERT(idx <= elements.size());
TOML_ASSERT(count >= 1_sz);
const auto old_size = elements.size();
const auto new_size = old_size + count;
const auto inserting_at_end = idx == old_size;
elements.resize(new_size);
if (!inserting_at_end)
{
for(size_t left = old_size, right = new_size - 1_sz; left --> idx; right--)
elements[right] = std::move(elements[left]);
}
}
#define TOML_MEMBER_ATTR(attr) TOML_EXTERNAL_LINKAGE TOML_ATTR(attr)
TOML_MEMBER_ATTR(const) node_type array::type() const noexcept { return node_type::array; }
@ -57,69 +120,122 @@ namespace toml
TOML_MEMBER_ATTR(const) const array* array::as_array() const noexcept { return this; }
TOML_MEMBER_ATTR(const) array* array::as_array() noexcept { return this; }
TOML_MEMBER_ATTR(pure) const node& array::operator[] (size_t index) const noexcept { return *values[index]; }
TOML_MEMBER_ATTR(pure) node& array::operator[] (size_t index) noexcept { return *values[index]; }
TOML_MEMBER_ATTR(pure) const node& array::operator[] (size_t index) const noexcept { return *elements[index]; }
TOML_MEMBER_ATTR(pure) node& array::operator[] (size_t index) noexcept { return *elements[index]; }
TOML_MEMBER_ATTR(pure) const node& array::front() const noexcept { return *values.front(); }
TOML_MEMBER_ATTR(pure) const node& array::back() const noexcept { return *values.back(); }
TOML_MEMBER_ATTR(pure) node& array::front() noexcept { return *values.front(); }
TOML_MEMBER_ATTR(pure) node& array::back() noexcept { return *values.back(); }
TOML_MEMBER_ATTR(pure) const node& array::front() const noexcept { return *elements.front(); }
TOML_MEMBER_ATTR(pure) const node& array::back() const noexcept { return *elements.back(); }
TOML_MEMBER_ATTR(pure) node& array::front() noexcept { return *elements.front(); }
TOML_MEMBER_ATTR(pure) node& array::back() noexcept { return *elements.back(); }
TOML_MEMBER_ATTR(pure) array::const_iterator array::begin() const noexcept { return { values.begin() }; }
TOML_MEMBER_ATTR(pure) array::const_iterator array::end() const noexcept { return { values.end() }; }
TOML_MEMBER_ATTR(pure) array::const_iterator array::cbegin() const noexcept { return { values.cbegin() }; }
TOML_MEMBER_ATTR(pure) array::const_iterator array::cend() const noexcept { return { values.cend() }; }
TOML_MEMBER_ATTR(pure) array::iterator array::begin() noexcept { return { values.begin() }; }
TOML_MEMBER_ATTR(pure) array::iterator array::end() noexcept { return { values.end() }; }
TOML_MEMBER_ATTR(pure) array::const_iterator array::begin() const noexcept { return { elements.begin() }; }
TOML_MEMBER_ATTR(pure) array::const_iterator array::end() const noexcept { return { elements.end() }; }
TOML_MEMBER_ATTR(pure) array::const_iterator array::cbegin() const noexcept { return { elements.cbegin() }; }
TOML_MEMBER_ATTR(pure) array::const_iterator array::cend() const noexcept { return { elements.cend() }; }
TOML_MEMBER_ATTR(pure) array::iterator array::begin() noexcept { return { elements.begin() }; }
TOML_MEMBER_ATTR(pure) array::iterator array::end() noexcept { return { elements.end() }; }
TOML_MEMBER_ATTR(pure) size_t array::size() const noexcept { return values.size(); }
TOML_MEMBER_ATTR(pure) size_t array::capacity() const noexcept { return values.capacity(); }
TOML_MEMBER_ATTR(pure) bool array::empty() const noexcept { return values.empty(); }
TOML_MEMBER_ATTR(const) size_t array::max_size() const noexcept { return values.max_size(); }
TOML_MEMBER_ATTR(pure) size_t array::size() const noexcept { return elements.size(); }
TOML_MEMBER_ATTR(pure) size_t array::capacity() const noexcept { return elements.capacity(); }
TOML_MEMBER_ATTR(pure) bool array::empty() const noexcept { return elements.empty(); }
TOML_MEMBER_ATTR(const) size_t array::max_size() const noexcept { return elements.max_size(); }
TOML_EXTERNAL_LINKAGE void array::reserve(size_t new_capacity) { values.reserve(new_capacity); }
TOML_EXTERNAL_LINKAGE void array::clear() noexcept { values.clear(); }
TOML_EXTERNAL_LINKAGE void array::shrink_to_fit() { values.shrink_to_fit(); }
TOML_EXTERNAL_LINKAGE void array::reserve(size_t new_capacity) { elements.reserve(new_capacity); }
TOML_EXTERNAL_LINKAGE void array::clear() noexcept { elements.clear(); }
TOML_EXTERNAL_LINKAGE void array::shrink_to_fit() { elements.shrink_to_fit(); }
#undef TOML_MEMBER_ATTR
TOML_EXTERNAL_LINKAGE
bool array::is_homogeneous(node_type ntype) const noexcept
{
if (elements.empty())
return false;
if (ntype == node_type::none)
ntype = elements[0]->type();
for (const auto& val : elements)
if (val->type() != ntype)
return false;
return true;
}
namespace impl
{
template <typename T, typename U>
TOML_INTERNAL_LINKAGE
bool array_is_homogeneous(T& elements, node_type ntype, U& first_nonmatch) noexcept
{
if (elements.empty())
{
first_nonmatch = {};
return false;
}
if (ntype == node_type::none)
ntype = elements[0]->type();
for (const auto& val : elements)
{
if (val->type() != ntype)
{
first_nonmatch = val.get();
return false;
}
}
return true;
}
}
TOML_EXTERNAL_LINKAGE
bool array::is_homogeneous(node_type ntype, toml::node*& first_nonmatch) noexcept
{
return impl::array_is_homogeneous(elements, ntype, first_nonmatch);
}
TOML_EXTERNAL_LINKAGE
bool array::is_homogeneous(node_type ntype, const toml::node*& first_nonmatch) const noexcept
{
return impl::array_is_homogeneous(elements, ntype, first_nonmatch);
}
TOML_EXTERNAL_LINKAGE
void array::truncate(size_t new_size)
{
if (new_size < values.size())
values.resize(new_size);
if (new_size < elements.size())
elements.resize(new_size);
}
TOML_EXTERNAL_LINKAGE
array::iterator array::erase(const_iterator pos) noexcept
{
return { values.erase(pos.raw_) };
return { elements.erase(pos.raw_) };
}
TOML_EXTERNAL_LINKAGE
array::iterator array::erase(const_iterator first, const_iterator last) noexcept
{
return { values.erase(first.raw_, last.raw_) };
return { elements.erase(first.raw_, last.raw_) };
}
TOML_EXTERNAL_LINKAGE
void array::pop_back() noexcept
{
values.pop_back();
elements.pop_back();
}
TOML_EXTERNAL_LINKAGE
TOML_ATTR(pure)
node* array::get(size_t index) noexcept
{
return index < values.size() ? values[index].get() : nullptr;
return index < elements.size() ? elements[index].get() : nullptr;
}
TOML_EXTERNAL_LINKAGE
TOML_ATTR(pure)
const node* array::get(size_t index) const noexcept
{
return index < values.size() ? values[index].get() : nullptr;
return index < elements.size() ? elements[index].get() : nullptr;
}
TOML_API
@ -128,17 +244,17 @@ namespace toml
{
if (&lhs == &rhs)
return true;
if (lhs.values.size() != rhs.values.size())
if (lhs.elements.size() != rhs.elements.size())
return false;
for (size_t i = 0, e = lhs.values.size(); i < e; i++)
for (size_t i = 0, e = lhs.elements.size(); i < e; i++)
{
const auto lhs_type = lhs.values[i]->type();
const node& rhs_ = *rhs.values[i];
const auto lhs_type = lhs.elements[i]->type();
const node& rhs_ = *rhs.elements[i];
const auto rhs_type = rhs_.type();
if (lhs_type != rhs_type)
return false;
const bool equal = lhs.values[i]->visit([&](const auto& lhs_) noexcept
const bool equal = lhs.elements[i]->visit([&](const auto& lhs_) noexcept
{
return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_);
});
@ -159,9 +275,9 @@ namespace toml
size_t array::total_leaf_count() const noexcept
{
size_t leaves{};
for (size_t i = 0, e = values.size(); i < e; i++)
for (size_t i = 0, e = elements.size(); i < e; i++)
{
auto arr = values[i]->as_array();
auto arr = elements[i]->as_array();
leaves += arr ? arr->total_leaf_count() : 1_sz;
}
return leaves;
@ -172,29 +288,29 @@ namespace toml
{
for (size_t i = 0, e = child.size(); i < e; i++)
{
auto type = child.values[i]->type();
auto type = child.elements[i]->type();
if (type == node_type::array)
{
array& arr = *reinterpret_cast<array*>(child.values[i].get());
array& arr = *reinterpret_cast<array*>(child.elements[i].get());
if (!arr.empty())
flatten_child(std::move(arr), dest_index);
}
else
values[dest_index++] = std::move(child.values[i]);
elements[dest_index++] = std::move(child.elements[i]);
}
}
TOML_EXTERNAL_LINKAGE
array& array::flatten() &
{
if (values.empty())
if (elements.empty())
return *this;
bool requires_flattening = false;
size_t size_after_flattening = values.size();
for (size_t i = values.size(); i --> 0_sz;)
size_t size_after_flattening = elements.size();
for (size_t i = elements.size(); i --> 0_sz;)
{
auto arr = values[i]->as_array();
auto arr = elements[i]->as_array();
if (!arr)
continue;
size_after_flattening--; //discount the array itself
@ -205,25 +321,25 @@ namespace toml
size_after_flattening += leaf_count;
}
else
values.erase(values.cbegin() + static_cast<ptrdiff_t>(i));
elements.erase(elements.cbegin() + static_cast<ptrdiff_t>(i));
}
if (!requires_flattening)
return *this;
values.reserve(size_after_flattening);
elements.reserve(size_after_flattening);
size_t i = 0;
while (i < values.size())
while (i < elements.size())
{
auto arr = values[i]->as_array();
auto arr = elements[i]->as_array();
if (!arr)
{
i++;
continue;
}
std::unique_ptr<node> arr_storage = std::move(values[i]);
std::unique_ptr<node> arr_storage = std::move(elements[i]);
const auto leaf_count = arr->total_leaf_count();
if (leaf_count > 1_sz)
preinsertion_resize(i + 1_sz, leaf_count - 1_sz);
@ -232,6 +348,11 @@ namespace toml
return *this;
}
}
TOML_POP_WARNINGS // TOML_DISABLE_SUGGEST_WARNINGS
TOML_EXTERNAL_LINKAGE
bool array::is_array_of_tables() const noexcept
{
return is_homogeneous(node_type::table);
}
}
TOML_NAMESPACE_END

File diff suppressed because it is too large Load Diff

View File

@ -6,10 +6,7 @@
#pragma once
#include "toml_common.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml
TOML_NAMESPACE_START
{
/// \brief A local date.
struct TOML_TRIVIAL_ABI date
@ -82,21 +79,20 @@ namespace toml
/// \brief Prints a date out to a stream as `YYYY-MM-DD` (per RFC 3339).
/// \detail \cpp
/// std::cout << toml::date{ 1987, 3, 16 } << std::endl;
/// std::cout << toml::date{ 1987, 3, 16 } << "\n";
/// \ecpp
///
/// \out
/// 1987-03-16
/// \eout
template <typename Char>
TOML_EXTERNAL_LINKAGE
std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const date& rhs)
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const date& rhs)
{
impl::print_to_stream(rhs, lhs);
return lhs;
}
#if !TOML_ALL_INLINE
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
extern template TOML_API std::ostream& operator << (std::ostream&, const date&);
#endif
@ -131,7 +127,8 @@ namespace toml
private:
[[nodiscard]] TOML_ALWAYS_INLINE
[[nodiscard]]
TOML_ALWAYS_INLINE
static constexpr uint64_t pack(time t) noexcept
{
return static_cast<uint64_t>(t.hour) << 48
@ -173,8 +170,8 @@ namespace toml
/// \brief Prints a time out to a stream as `HH:MM:SS.FFFFFF` (per RFC 3339).
/// \detail \cpp
/// std::cout << toml::time{ 10, 20, 34 } << std::endl;
/// std::cout << toml::time{ 10, 20, 34, 500000000 } << std::endl;
/// std::cout << toml::time{ 10, 20, 34 } << "\n";
/// std::cout << toml::time{ 10, 20, 34, 500000000 } << "\n";
/// \ecpp
///
/// \out
@ -182,14 +179,13 @@ namespace toml
/// 10:20:34.5
/// \eout
template <typename Char>
TOML_EXTERNAL_LINKAGE
std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const time& rhs)
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const time& rhs)
{
impl::print_to_stream(rhs, lhs);
return lhs;
}
#if !TOML_ALL_INLINE
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
extern template TOML_API std::ostream& operator << (std::ostream&, const time&);
#endif
@ -208,10 +204,10 @@ namespace toml
/// \brief Constructs a timezone offset from separate hour and minute totals.
///
/// \detail \cpp
/// std::cout << toml::time_offset{ 2, 30 } << std::endl;
/// std::cout << toml::time_offset{ -2, 30 } << std::endl;
/// std::cout << toml::time_offset{ -2, -30 } << std::endl;
/// std::cout << toml::time_offset{ 0, 0 } << std::endl;
/// std::cout << toml::time_offset{ 2, 30 } << "\n";
/// std::cout << toml::time_offset{ -2, 30 } << "\n";
/// std::cout << toml::time_offset{ -2, -30 } << "\n";
/// std::cout << toml::time_offset{ 0, 0 } << "\n";
///
/// \ecpp
///
@ -274,11 +270,11 @@ namespace toml
/// \brief Prints a time_offset out to a stream as `+-HH:MM or Z` (per RFC 3339).
/// \detail \cpp
/// std::cout << toml::time_offset{ 2, 30 } << std::endl;
/// std::cout << toml::time_offset{ 2, -30 } << std::endl;
/// std::cout << toml::time_offset{} << std::endl;
/// std::cout << toml::time_offset{ -2, 30 } << std::endl;
/// std::cout << toml::time_offset{ -2, -30 } << std::endl;
/// std::cout << toml::time_offset{ 2, 30 } << "\n";
/// std::cout << toml::time_offset{ 2, -30 } << "\n";
/// std::cout << toml::time_offset{} << "\n";
/// std::cout << toml::time_offset{ -2, 30 } << "\n";
/// std::cout << toml::time_offset{ -2, -30 } << "\n";
/// \ecpp
///
/// \out
@ -289,22 +285,17 @@ namespace toml
/// -02:30
/// \eout
template <typename Char>
TOML_EXTERNAL_LINKAGE
std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const time_offset& rhs)
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const time_offset& rhs)
{
impl::print_to_stream(rhs, lhs);
return lhs;
}
#if !TOML_ALL_INLINE
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
extern template TOML_API std::ostream& operator << (std::ostream&, const time_offset&);
#endif
#ifdef TOML_OPTIONAL_TYPE
TOML_ABI_NAMESPACE_START(custopt)
#else
TOML_ABI_NAMESPACE_START(stdopt)
#endif
TOML_ABI_NAMESPACE_BOOL(TOML_HAS_CUSTOM_OPTIONAL_TYPE, custopt, stdopt)
/// \brief A date-time.
struct date_time
@ -315,8 +306,8 @@ namespace toml
toml::time time;
/// \brief The timezone offset component.
///
/// \remarks The date_time is said to be 'local' if the time_offset is empty.
optional<toml::time_offset> time_offset;
/// \remarks The date_time is said to be 'local' if the offset is empty.
optional<toml::time_offset> offset;
/// \brief Default-constructs a zero date-time.
TOML_NODISCARD_CTOR
@ -339,19 +330,19 @@ namespace toml
///
/// \param d The date component.
/// \param t The time component.
/// \param offset The timezone offset.
/// \param off The timezone offset.
TOML_NODISCARD_CTOR
constexpr date_time(toml::date d, toml::time t, toml::time_offset offset) noexcept
constexpr date_time(toml::date d, toml::time t, toml::time_offset off) noexcept
: date{ d },
time{ t },
time_offset{ offset }
offset{ off }
{}
/// \brief Returns true if this date_time does not contain timezone offset information.
[[nodiscard]]
constexpr bool is_local() const noexcept
{
return !time_offset.has_value();
return !offset.has_value();
}
/// \brief Equality operator.
@ -360,7 +351,7 @@ namespace toml
{
return lhs.date == rhs.date
&& lhs.time == rhs.time
&& lhs.time_offset == rhs.time_offset;
&& lhs.offset == rhs.offset;
}
/// \brief Inequality operator.
@ -378,7 +369,7 @@ namespace toml
return lhs.date < rhs.date;
if (lhs.time != rhs.time)
return lhs.time < rhs.time;
return lhs.time_offset < rhs.time_offset;
return lhs.offset < rhs.offset;
}
/// \brief Less-than-or-equal-to operator.
@ -389,7 +380,7 @@ namespace toml
return lhs.date < rhs.date;
if (lhs.time != rhs.time)
return lhs.time < rhs.time;
return lhs.time_offset <= rhs.time_offset;
return lhs.offset <= rhs.offset;
}
/// \brief Greater-than operator.
@ -407,13 +398,13 @@ namespace toml
}
};
TOML_ABI_NAMESPACE_END // TOML_OPTIONAL_TYPE
TOML_ABI_NAMESPACE_END // TOML_HAS_CUSTOM_OPTIONAL_TYPE
/// \brief Prints a date_time out to a stream in RFC 3339 format.
/// \detail \cpp
/// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 } } << std::endl;
/// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 }, { -2, -30 } } << std::endl;
/// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 }, {} } << std::endl;
/// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 } } << "\n";
/// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 }, { -2, -30 } } << "\n";
/// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 }, {} } << "\n";
/// \ecpp
///
/// \out
@ -422,16 +413,14 @@ namespace toml
/// 1987-03-16T10:20:34Z
/// \eout
template <typename Char>
TOML_EXTERNAL_LINKAGE
std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const date_time& rhs)
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const date_time& rhs)
{
impl::print_to_stream(rhs, lhs);
return lhs;
}
#if !TOML_ALL_INLINE
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
extern template TOML_API std::ostream& operator << (std::ostream&, const date_time&);
#endif
}
TOML_POP_WARNINGS // TOML_DISABLE_PADDING_WARNINGS
TOML_NAMESPACE_END

View File

@ -11,27 +11,17 @@
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml::impl
TOML_IMPL_NAMESPACE_START
{
[[nodiscard]] TOML_API
toml::string default_formatter_make_key_segment(const toml::string& str) noexcept;
[[nodiscard]] TOML_API
size_t default_formatter_inline_columns(const node& node) noexcept;
[[nodiscard]] TOML_API
bool default_formatter_forces_multiline(const node& node, size_t starting_column_bias = 0) noexcept;
[[nodiscard]] TOML_API std::string default_formatter_make_key_segment(const std::string&) noexcept;
[[nodiscard]] TOML_API size_t default_formatter_inline_columns(const node&) noexcept;
[[nodiscard]] TOML_API bool default_formatter_forces_multiline(const node&, size_t = 0) noexcept;
}
TOML_IMPL_NAMESPACE_END
namespace toml
TOML_NAMESPACE_START
{
template <typename T, typename U>
std::basic_ostream<T>& operator << (std::basic_ostream<T>&, default_formatter<U>&);
template <typename T, typename U>
std::basic_ostream<T>& operator << (std::basic_ostream<T>&, default_formatter<U>&&);
/// \brief A wrapper for printing TOML objects out to a stream as formatted TOML.
///
/// \remarks You generally don't need to create an instance of this class explicitly; the stream
@ -46,8 +36,8 @@ namespace toml
/// }};
///
/// // these two lines are equivalent:
/// std::cout << toml::default_formatter{ tbl } << std::endl;
/// std::cout << tbl << std::endl;
/// std::cout << toml::default_formatter{ tbl } << "\n";
/// std::cout << tbl << "\n";
///
/// \ecpp
///
@ -66,9 +56,9 @@ namespace toml
{
private:
using base = impl::formatter<Char>;
std::vector<toml::string> key_path;
std::vector<std::string> key_path;
void print_key_segment(const toml::string& str)
void print_key_segment(const std::string& str)
{
if (str.empty())
impl::print_to_stream("''"sv, base::stream());
@ -88,7 +78,11 @@ namespace toml
}
if (requiresQuotes)
base::print_quoted_string(str);
{
impl::print_to_stream('"', base::stream());
impl::print_to_stream_with_escapes(str, base::stream());
impl::print_to_stream('"', base::stream());
}
else
impl::print_to_stream(str, base::stream());
}
@ -179,7 +173,7 @@ namespace toml
&& !arr->template get_as<table>(0_sz)->is_inline();
};
//values, arrays, and inline tables/table arrays
// values, arrays, and inline tables/table arrays
for (auto&& [k, v] : tbl)
{
const auto type = v.type();
@ -201,7 +195,7 @@ namespace toml
}
}
//non-inline tables
// non-inline tables
for (auto&& [k, v] : tbl)
{
const auto type = v.type();
@ -209,8 +203,8 @@ namespace toml
continue;
auto& child_tbl = *reinterpret_cast<const table*>(&v);
//we can skip indenting and emitting the headers for tables that only contain other tables
//(so we don't over-nest)
// we can skip indenting and emitting the headers for tables that only contain other tables
// (so we don't over-nest)
size_t child_value_count{}; //includes inline tables and non-table arrays
size_t child_table_count{};
size_t child_table_array_count{};
@ -243,19 +237,21 @@ namespace toml
if (child_value_count == 0_sz && (child_table_count > 0_sz || child_table_array_count > 0_sz))
skip_self = true;
if (!skip_self)
base::increase_indent();
key_path.push_back(impl::default_formatter_make_key_segment(k));
if (!skip_self)
{
base::print_newline();
base::print_newline(true);
if (!base::naked_newline())
{
base::print_newline();
base::print_newline(true);
}
base::increase_indent();
base::print_indent();
impl::print_to_stream("["sv, base::stream());
print_key_path();
impl::print_to_stream("]"sv, base::stream());
base::print_newline(true);
base::print_newline();
}
print(child_tbl);
@ -265,7 +261,7 @@ namespace toml
base::decrease_indent();
}
//table arrays
// table arrays
for (auto&& [k, v] : tbl)
{
if (!is_non_inline_array_of_tables(v))
@ -305,6 +301,7 @@ namespace toml
{
base::decrease_indent(); // so root kvps and tables have the same indent
print(tbl);
base::print_newline();
}
break;
}
@ -320,12 +317,18 @@ namespace toml
public:
/// \brief The default flags for a default_formatter.
static constexpr format_flags default_flags
= format_flags::allow_literal_strings
| format_flags::allow_multi_line_strings
| format_flags::allow_value_format_flags;
/// \brief Constructs a default formatter and binds it to a TOML object.
///
/// \param source The source TOML object.
/// \param flags Format option flags.
TOML_NODISCARD_CTOR
explicit default_formatter(const toml::node& source, format_flags flags = {}) noexcept
explicit default_formatter(const toml::node& source, format_flags flags = default_flags) noexcept
: base{ source, flags }
{}
@ -335,7 +338,7 @@ namespace toml
friend std::basic_ostream<T>& operator << (std::basic_ostream<T>&, default_formatter<U>&&);
};
#if !TOML_ALL_INLINE
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
extern template class TOML_API default_formatter<char>;
#endif
@ -345,8 +348,7 @@ namespace toml
/// \brief Prints the bound TOML object out to the stream as formatted TOML.
template <typename T, typename U>
TOML_EXTERNAL_LINKAGE
std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, default_formatter<U>& rhs)
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, default_formatter<U>& rhs)
{
rhs.attach(lhs);
rhs.key_path.clear();
@ -357,32 +359,48 @@ namespace toml
/// \brief Prints the bound TOML object out to the stream as formatted TOML (rvalue overload).
template <typename T, typename U>
TOML_EXTERNAL_LINKAGE
std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, default_formatter<U>&& rhs)
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, default_formatter<U>&& rhs)
{
return lhs << rhs; //as lvalue
}
template <typename Char>
TOML_EXTERNAL_LINKAGE
std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const table& rhs)
{
return lhs << default_formatter<Char>{ rhs };
}
#ifndef DOXYGEN
template <typename Char>
TOML_EXTERNAL_LINKAGE
std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const array& rhs)
{
return lhs << default_formatter<Char>{ rhs };
}
#if !TOML_ALL_INLINE
#if !TOML_HEADER_ONLY
extern template TOML_API std::ostream& operator << (std::ostream&, default_formatter<char>&);
extern template TOML_API std::ostream& operator << (std::ostream&, default_formatter<char>&&);
extern template TOML_API std::ostream& operator << (std::ostream&, const table&);
extern template TOML_API std::ostream& operator << (std::ostream&, const array&);
extern template TOML_API std::ostream& operator << (std::ostream&, const value<std::string>&);
extern template TOML_API std::ostream& operator << (std::ostream&, const value<int64_t>&);
extern template TOML_API std::ostream& operator << (std::ostream&, const value<double>&);
extern template TOML_API std::ostream& operator << (std::ostream&, const value<bool>&);
extern template TOML_API std::ostream& operator << (std::ostream&, const value<toml::date>&);
extern template TOML_API std::ostream& operator << (std::ostream&, const value<toml::time>&);
extern template TOML_API std::ostream& operator << (std::ostream&, const value<toml::date_time>&);
#endif
}
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_PADDING_WARNINGS
template <typename Char>
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const table& rhs)
{
return lhs << default_formatter<Char>{ rhs };
}
template <typename Char>
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const array& rhs)
{
return lhs << default_formatter<Char>{ rhs };
}
template <typename Char, typename T>
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const value<T>& rhs)
{
return lhs << default_formatter<Char>{ rhs };
}
#endif // !DOXYGEN
}
TOML_NAMESPACE_END
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS

View File

@ -12,24 +12,24 @@
//# }}
#include "toml_default_formatter.h"
TOML_DISABLE_WARNINGS
#include <cmath>
TOML_ENABLE_WARNINGS
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_FLOAT_WARNINGS
TOML_DISABLE_ARITHMETIC_WARNINGS
namespace toml::impl
TOML_IMPL_NAMESPACE_START
{
inline constexpr size_t default_formatter_line_wrap = 120_sz;
TOML_PUSH_WARNINGS
TOML_DISABLE_ALL_WARNINGS
TOML_API
TOML_EXTERNAL_LINKAGE
string default_formatter_make_key_segment(const string& str) noexcept
std::string default_formatter_make_key_segment(const std::string& str) noexcept
{
if (str.empty())
return TOML_STRING_PREFIX("''"s);
return "''"s;
else
{
bool requiresQuotes = false;
@ -47,24 +47,24 @@ namespace toml::impl
if (requiresQuotes)
{
string s;
std::string s;
s.reserve(str.length() + 2_sz);
s += TOML_STRING_PREFIX('"');
s += '"';
for (auto c : str)
{
if TOML_UNLIKELY(c >= TOML_STRING_PREFIX('\x00') && c <= TOML_STRING_PREFIX('\x1F'))
if TOML_UNLIKELY(c >= '\x00' && c <= '\x1F')
{
const auto& sv = low_character_escape_table[c];
s.append(reinterpret_cast<const string_char*>(sv.data()), sv.length());
s.append(reinterpret_cast<const char*>(sv.data()), sv.length());
}
else if TOML_UNLIKELY(c == TOML_STRING_PREFIX('\x7F'))
s.append(TOML_STRING_PREFIX("\\u007F"sv));
else if TOML_UNLIKELY(c == TOML_STRING_PREFIX('"'))
s.append(TOML_STRING_PREFIX("\\\""sv));
else if TOML_UNLIKELY(c == '\x7F')
s.append("\\u007F"sv);
else if TOML_UNLIKELY(c == '"')
s.append("\\\""sv);
else
s += c;
}
s += TOML_STRING_PREFIX('"');
s += '"';
return s;
}
else
@ -72,8 +72,6 @@ namespace toml::impl
}
}
TOML_POP_WARNINGS
TOML_API
TOML_EXTERNAL_LINKAGE
size_t default_formatter_inline_columns(const node& node) noexcept
@ -112,7 +110,7 @@ namespace toml::impl
case node_type::string:
{
auto& n = *reinterpret_cast<const value<string>*>(&node);
auto& n = *reinterpret_cast<const value<std::string>*>(&node);
return n.get().length() + 2_sz; // + ""
}
@ -165,12 +163,12 @@ namespace toml::impl
return (default_formatter_inline_columns(node) + starting_column_bias) > default_formatter_line_wrap;
}
}
TOML_IMPL_NAMESPACE_END
namespace toml
TOML_NAMESPACE_START
{
template <typename Char>
TOML_EXTERNAL_LINKAGE
void default_formatter<Char>::print_inline(const toml::table& tbl)
inline void default_formatter<Char>::print_inline(const toml::table& tbl)
{
if (tbl.empty())
impl::print_to_stream("{}"sv, base::stream());
@ -204,5 +202,69 @@ namespace toml
base::clear_naked_newline();
}
}
TOML_NAMESPACE_END
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_FLOAT_WARNINGS
// implementations of windows wide string nonsense
#if TOML_WINDOWS_COMPAT
TOML_DISABLE_WARNINGS
#include <windows.h> // fuckkkk :(
TOML_ENABLE_WARNINGS
TOML_IMPL_NAMESPACE_START
{
TOML_API
TOML_EXTERNAL_LINKAGE
std::string narrow(std::wstring_view str) noexcept
{
if (str.empty())
return {};
std::string s;
const auto len = WideCharToMultiByte(
65001, 0, str.data(), static_cast<int>(str.length()), nullptr, 0, nullptr, nullptr
);
if (len)
{
s.resize(static_cast<size_t>(len));
WideCharToMultiByte(65001, 0, str.data(), static_cast<int>(str.length()), s.data(), len, nullptr, nullptr);
}
return s;
}
TOML_API
TOML_EXTERNAL_LINKAGE
std::wstring widen(std::string_view str) noexcept
{
if (str.empty())
return {};
std::wstring s;
const auto len = MultiByteToWideChar(65001, 0, str.data(), static_cast<int>(str.length()), nullptr, 0);
if (len)
{
s.resize(static_cast<size_t>(len));
MultiByteToWideChar(65001, 0, str.data(), static_cast<int>(str.length()), s.data(), len);
}
return s;
}
#ifdef __cpp_lib_char8_t
TOML_API
TOML_EXTERNAL_LINKAGE
std::wstring widen(std::u8string_view str) noexcept
{
if (str.empty())
return {};
return widen(std::string_view{ reinterpret_cast<const char*>(str.data()), str.length() });
}
#endif // __cpp_lib_char8_t
}
TOML_IMPL_NAMESPACE_END
#endif // TOML_WINDOWS_COMPAT
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_ARITHMETIC_WARNINGS

View File

@ -8,35 +8,8 @@
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml
{
/// \brief Format flags for modifying how TOML data is printed to streams.
enum class format_flags : uint8_t
{
none,
quote_dates_and_times = 1
};
[[nodiscard]]
TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr format_flags operator & (format_flags lhs, format_flags rhs) noexcept
{
return static_cast<format_flags>(impl::unbox_enum(lhs) & impl::unbox_enum(rhs));
}
[[nodiscard]]
TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr format_flags operator | (format_flags lhs, format_flags rhs) noexcept
{
return static_cast<format_flags>( impl::unbox_enum(lhs) | impl::unbox_enum(rhs) );
}
}
namespace toml::impl
TOML_IMPL_NAMESPACE_START
{
template <typename Char = char>
class TOML_API formatter
@ -45,24 +18,55 @@ namespace toml::impl
const toml::node* source_;
std::basic_ostream<Char>* stream_ = nullptr;
format_flags flags_;
int8_t indent_;
int indent_;
bool naked_newline_;
protected:
[[nodiscard]] const toml::node& source() const noexcept { return *source_; }
[[nodiscard]] format_flags flags() const noexcept { return flags_; }
[[nodiscard]] std::basic_ostream<Char>& stream() const noexcept { return *stream_; }
static constexpr size_t indent_columns = 4;
static constexpr toml::string_view indent_string = TOML_STRING_PREFIX(" "sv);
[[nodiscard]] int8_t indent() const noexcept { return indent_; }
void indent(int8_t level) noexcept { indent_ = level; }
static constexpr std::string_view indent_string = " "sv;
[[nodiscard]] int indent() const noexcept { return indent_; }
void indent(int level) noexcept { indent_ = level; }
void increase_indent() noexcept { indent_++; }
void decrease_indent() noexcept { indent_--; }
TOML_ALWAYS_INLINE
void clear_naked_newline() noexcept { naked_newline_ = false; }
[[nodiscard]]
bool quote_dates_and_times() const noexcept
{
return (flags_ & format_flags::quote_dates_and_times) != format_flags::none;
}
[[nodiscard]]
bool literal_strings_allowed() const noexcept
{
return (flags_ & format_flags::allow_literal_strings) != format_flags::none;
}
[[nodiscard]]
bool multi_line_strings_allowed() const noexcept
{
return (flags_ & format_flags::allow_multi_line_strings) != format_flags::none;
}
[[nodiscard]]
bool value_format_flags_allowed() const noexcept
{
return (flags_ & format_flags::allow_value_format_flags) != format_flags::none;
}
[[nodiscard]]
bool naked_newline() const noexcept
{
return naked_newline_;
}
void clear_naked_newline() noexcept
{
naked_newline_ = false;
}
void attach(std::basic_ostream<Char>& stream) noexcept
{
@ -87,53 +91,115 @@ namespace toml::impl
void print_indent()
{
for (int8_t i = 0; i < indent_; i++)
for (int i = 0; i < indent_; i++)
{
print_to_stream(indent_string, *stream_);
naked_newline_ = false;
}
}
void print_quoted_string(toml::string_view str)
void print_quoted_string(std::string_view str, bool allow_multi_line = true)
{
auto literals = literal_strings_allowed();
if (str.empty())
print_to_stream("\"\""sv, *stream_);
{
print_to_stream(literals ? "''"sv : "\"\""sv, *stream_);
clear_naked_newline();
return;
}
auto multi_line = allow_multi_line && multi_line_strings_allowed();
if (multi_line || literals)
{
utf8_decoder decoder;
bool has_line_breaks = false;
bool has_control_chars = false;
bool has_single_quotes = false;
for (size_t i = 0; i < str.length() && !(has_line_breaks && has_control_chars && has_single_quotes); i++)
{
decoder(static_cast<uint8_t>(str[i]));
if (decoder.error())
{
has_line_breaks = false;
has_control_chars = true; //force ""
has_single_quotes = true;
break;
}
else if (decoder.has_code_point())
{
if (is_line_break(decoder.codepoint))
has_line_breaks = true;
else if (is_nontab_control_character(decoder.codepoint))
has_control_chars = true;
else if (decoder.codepoint == U'\'')
has_single_quotes = true;
}
}
multi_line = multi_line && has_line_breaks;
literals = literals && !has_control_chars && !(!multi_line && has_single_quotes);
}
if (literals)
{
const auto quot = multi_line ? "'''"sv : "'"sv;
print_to_stream(quot, *stream_);
print_to_stream(str, *stream_);
print_to_stream(quot, *stream_);
}
else
{
print_to_stream('"', *stream_);
const auto quot = multi_line ? R"(""")"sv : R"(")"sv;
print_to_stream(quot, *stream_);
print_to_stream_with_escapes(str, *stream_);
print_to_stream('"', *stream_);
print_to_stream(quot, *stream_);
}
naked_newline_ = false;
clear_naked_newline();
}
template <typename T>
void print(const value<T>& val)
{
if constexpr (std::is_same_v<T, string>)
if constexpr (std::is_same_v<T, std::string>)
{
print_quoted_string(val.get());
}
else
{
static constexpr auto is_dt =
std::is_same_v<T, date>
|| std::is_same_v<T, time>
|| std::is_same_v<T, date_time>;
if constexpr (is_dt)
if constexpr (is_one_of<T, date, time, date_time>)
{
if ((flags_ & format_flags::quote_dates_and_times) != format_flags::none)
print_to_stream('"', *stream_);
if (quote_dates_and_times())
{
const auto quot = literal_strings_allowed() ? '\'' : '"';
print_to_stream(quot, *stream_);
print_to_stream(*val, *stream_);
print_to_stream(quot, *stream_);
}
else
print_to_stream(*val, *stream_);
}
*stream_ << val;
if constexpr (is_dt)
else if constexpr (is_one_of<T, int64_t/*, double*/>)
{
if ((flags_ & format_flags::quote_dates_and_times) != format_flags::none)
print_to_stream('"', *stream_);
if (value_format_flags_allowed() && *val >= 0)
{
const auto fmt = val.flags() & value_flags::format_as_hexadecimal;
if (fmt != value_flags::none)
{
switch (fmt)
{
case value_flags::format_as_binary: print_to_stream("0b"sv, *stream_); break;
case value_flags::format_as_octal: print_to_stream("0o"sv, *stream_); break;
case value_flags::format_as_hexadecimal: print_to_stream("0x"sv, *stream_); break;
}
print_to_stream(*val, *stream_, fmt);
}
else
print_to_stream(*val, *stream_);
}
else
print_to_stream(*val, *stream_);
}
else
print_to_stream(*val, *stream_);
naked_newline_ = false;
}
@ -144,7 +210,7 @@ namespace toml::impl
TOML_ASSUME(type > node_type::array);
switch (type)
{
case node_type::string: print(*reinterpret_cast<const value<string>*>(&val_node)); break;
case node_type::string: print(*reinterpret_cast<const value<std::string>*>(&val_node)); break;
case node_type::integer: print(*reinterpret_cast<const value<int64_t>*>(&val_node)); break;
case node_type::floating_point: print(*reinterpret_cast<const value<double>*>(&val_node)); break;
case node_type::boolean: print(*reinterpret_cast<const value<bool>*>(&val_node)); break;
@ -161,9 +227,11 @@ namespace toml::impl
{}
};
#if !TOML_ALL_INLINE
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
extern template class TOML_API formatter<char>;
#endif
}
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_PADDING_WARNINGS
}
TOML_IMPL_NAMESPACE_END
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS

View File

@ -9,25 +9,40 @@
#if !TOML_IMPLEMENTATION
#error This is an implementation-only header.
#endif
#if TOML_ALL_INLINE
#error This header cannot not be included when TOML_ALL_INLINE is enabled.
#if TOML_HEADER_ONLY && !TOML_INTELLISENSE
#error This header cannot not be included when TOML_HEADER_ONLY is enabled.
#endif
//# }}
TOML_PUSH_WARNINGS
TOML_DISABLE_ALL_WARNINGS
TOML_DISABLE_WARNINGS
#include <ostream>
#include <istream>
#include <fstream>
TOML_POP_WARNINGS
TOML_ENABLE_WARNINGS
#include "toml_node_view.h"
#include "toml_default_formatter.h"
#include "toml_json_formatter.h"
#if TOML_PARSER
#include "toml_parser.h"
#endif
namespace toml
// internal implementation namespace
TOML_IMPL_NAMESPACE_START
{
// formatters
template class TOML_API formatter<char>;
// print to stream machinery
template TOML_API void print_floating_point_to_stream(double, std::ostream&, bool);
}
TOML_IMPL_NAMESPACE_END
// public namespace
TOML_NAMESPACE_START
{
// value<>
template class TOML_API value<string>;
template class TOML_API value<std::string>;
template class TOML_API value<int64_t>;
template class TOML_API value<double>;
template class TOML_API value<bool>;
@ -40,10 +55,6 @@ namespace toml
template class TOML_API node_view<const node>;
// formatters
namespace impl
{
template class TOML_API formatter<char>;
}
template class TOML_API default_formatter<char>;
template class TOML_API json_formatter<char>;
@ -54,7 +65,7 @@ namespace toml
template TOML_API std::ostream& operator << (std::ostream&, const time&);
template TOML_API std::ostream& operator << (std::ostream&, const time_offset&);
template TOML_API std::ostream& operator << (std::ostream&, const date_time&);
template TOML_API std::ostream& operator << (std::ostream&, const value<toml::string>&);
template TOML_API std::ostream& operator << (std::ostream&, const value<std::string>&);
template TOML_API std::ostream& operator << (std::ostream&, const value<int64_t>&);
template TOML_API std::ostream& operator << (std::ostream&, const value<double>&);
template TOML_API std::ostream& operator << (std::ostream&, const value<bool>&);
@ -71,32 +82,74 @@ namespace toml
template TOML_API std::ostream& operator << (std::ostream&, const node_view<const node>&);
template TOML_API std::ostream& operator << (std::ostream&, node_type);
// print_to_stream() machinery
namespace impl
{
template TOML_API void print_floating_point_to_stream(float, std::ostream&, bool);
template TOML_API void print_floating_point_to_stream(double, std::ostream&, bool);
}
// node::value, node_view:::value etc
#define TOML_INSTANTIATE(name, T) \
template TOML_API optional<T> node::name<T>() const noexcept; \
template TOML_API optional<T> node_view<node>::name<T>() const noexcept; \
template TOML_API optional<T> node_view<const node>::name<T>() const noexcept
TOML_INSTANTIATE(value_exact, std::string_view);
TOML_INSTANTIATE(value_exact, std::string);
TOML_INSTANTIATE(value_exact, const char*);
TOML_INSTANTIATE(value_exact, int64_t);
TOML_INSTANTIATE(value_exact, double);
TOML_INSTANTIATE(value_exact, date);
TOML_INSTANTIATE(value_exact, time);
TOML_INSTANTIATE(value_exact, date_time);
TOML_INSTANTIATE(value_exact, bool);
TOML_INSTANTIATE(value, std::string_view);
TOML_INSTANTIATE(value, std::string);
TOML_INSTANTIATE(value, const char*);
TOML_INSTANTIATE(value, signed char);
TOML_INSTANTIATE(value, signed short);
TOML_INSTANTIATE(value, signed int);
TOML_INSTANTIATE(value, signed long);
TOML_INSTANTIATE(value, signed long long);
TOML_INSTANTIATE(value, unsigned char);
TOML_INSTANTIATE(value, unsigned short);
TOML_INSTANTIATE(value, unsigned int);
TOML_INSTANTIATE(value, unsigned long);
TOML_INSTANTIATE(value, unsigned long long);
TOML_INSTANTIATE(value, double);
TOML_INSTANTIATE(value, float);
TOML_INSTANTIATE(value, date);
TOML_INSTANTIATE(value, time);
TOML_INSTANTIATE(value, date_time);
TOML_INSTANTIATE(value, bool);
#ifdef __cpp_lib_char8_t
TOML_INSTANTIATE(value_exact, std::u8string_view);
TOML_INSTANTIATE(value_exact, std::u8string);
TOML_INSTANTIATE(value_exact, const char8_t*);
TOML_INSTANTIATE(value, std::u8string_view);
TOML_INSTANTIATE(value, std::u8string);
TOML_INSTANTIATE(value, const char8_t*);
#endif
#if TOML_WINDOWS_COMPAT
TOML_INSTANTIATE(value_exact, std::wstring);
TOML_INSTANTIATE(value, std::wstring);
#endif
#undef TOML_INSTANTIATE
// parser machinery
// parser instantiations
#if TOML_PARSER
// parse error ostream
template TOML_API std::ostream& operator << (std::ostream&, const parse_error&);
// parse() and parse_file()
#if TOML_EXCEPTIONS
TOML_ABI_NAMESPACE_START(parse_ex)
#else
TOML_ABI_NAMESPACE_START(parse_noex)
#endif
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex)
template TOML_API parse_result parse(std::istream&, std::string_view) TOML_MAY_THROW;
template TOML_API parse_result parse(std::istream&, std::string&&) TOML_MAY_THROW;
template TOML_API parse_result parse_file(std::string_view) TOML_MAY_THROW;
#ifdef __cpp_lib_char8_t
template TOML_API parse_result parse_file(std::u8string_view) TOML_MAY_THROW;
#endif
#if TOML_WINDOWS_COMPAT
template TOML_API parse_result parse_file(std::wstring_view) TOML_MAY_THROW;
#endif
TOML_ABI_NAMESPACE_END // TOML_EXCEPTIONS
#endif // TOML_PARSER
}
TOML_NAMESPACE_END

View File

@ -8,15 +8,9 @@
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml
TOML_NAMESPACE_START
{
template <typename T, typename U>
std::basic_ostream<T>& operator << (std::basic_ostream<T>&, json_formatter<U>&);
template <typename T, typename U>
std::basic_ostream<T>& operator << (std::basic_ostream<T>&, json_formatter<U>&&);
/// \brief A wrapper for printing TOML objects out to a stream as formatted JSON.
///
/// \detail \cpp
@ -28,7 +22,7 @@ namespace toml
/// [fruit.apple.texture]
/// smooth = true
/// )"sv);
/// std::cout << toml::json_formatter{ some_toml } << std::endl;
/// std::cout << toml::json_formatter{ some_toml } << "\n";
///
/// \ecpp
///
@ -96,21 +90,32 @@ namespace toml
{
switch (auto source_type = base::source().type())
{
case node_type::table: print(*reinterpret_cast<const table*>(&base::source())); break;
case node_type::array: print(*reinterpret_cast<const array*>(&base::source())); break;
default: base::print_value(base::source(), source_type);
case node_type::table:
print(*reinterpret_cast<const table*>(&base::source()));
base::print_newline();
break;
case node_type::array:
print(*reinterpret_cast<const array*>(&base::source()));
break;
default:
base::print_value(base::source(), source_type);
}
}
public:
/// \brief The default flags for a json_formatter.
static constexpr format_flags default_flags = format_flags::quote_dates_and_times;
/// \brief Constructs a JSON formatter and binds it to a TOML object.
///
/// \param source The source TOML object.
/// \param flags Format option flags.
TOML_NODISCARD_CTOR
explicit json_formatter(const toml::node& source, format_flags flags = {}) noexcept
: base{ source, flags | format_flags::quote_dates_and_times }
explicit json_formatter(const toml::node& source, format_flags flags = default_flags) noexcept
: base{ source, flags }
{}
template <typename T, typename U>
@ -119,7 +124,7 @@ namespace toml
friend std::basic_ostream<T>& operator << (std::basic_ostream<T>&, json_formatter<U>&&);
};
#if !TOML_ALL_INLINE
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
extern template class TOML_API json_formatter<char>;
#endif
@ -129,8 +134,7 @@ namespace toml
/// \brief Prints the bound TOML object out to the stream as JSON.
template <typename T, typename U>
TOML_EXTERNAL_LINKAGE
std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, json_formatter<U>& rhs)
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, json_formatter<U>& rhs)
{
rhs.attach(lhs);
rhs.print();
@ -140,16 +144,16 @@ namespace toml
/// \brief Prints the bound TOML object out to the stream as JSON (rvalue overload).
template <typename T, typename U>
TOML_EXTERNAL_LINKAGE
std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, json_formatter<U>&& rhs)
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, json_formatter<U>&& rhs)
{
return lhs << rhs; //as lvalue
}
#if !TOML_ALL_INLINE
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
extern template TOML_API std::ostream& operator << (std::ostream&, json_formatter<char>&);
extern template TOML_API std::ostream& operator << (std::ostream&, json_formatter<char>&&);
#endif
}
TOML_NAMESPACE_END
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_PADDING_WARNINGS
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS

View File

@ -16,11 +16,10 @@
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
namespace toml
TOML_NAMESPACE_START
{
template <typename Char>
TOML_EXTERNAL_LINKAGE
void json_formatter<Char>::print(const toml::table& tbl)
inline void json_formatter<Char>::print(const toml::table& tbl)
{
if (tbl.empty())
impl::print_to_stream("{}"sv, base::stream());
@ -37,7 +36,7 @@ namespace toml
base::print_newline(true);
base::print_indent();
base::print_quoted_string(k);
base::print_quoted_string(k, false);
impl::print_to_stream(" : "sv, base::stream());
const auto type = v.type();
@ -59,5 +58,6 @@ namespace toml
base::clear_naked_newline();
}
}
TOML_NAMESPACE_END
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS

View File

@ -6,10 +6,56 @@
#pragma once
#include "toml_common.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_VTABLE_WARNINGS
#if defined(DOXYGEN) || TOML_SIMPLE_STATIC_ASSERT_MESSAGES
namespace toml
#define TOML_SA_NEWLINE " "
#define TOML_SA_LIST_SEP ", "
#define TOML_SA_LIST_BEG " ("
#define TOML_SA_LIST_END ")"
#define TOML_SA_LIST_NEW " "
#define TOML_SA_LIST_NXT ", "
#else
#define TOML_SA_NEWLINE "\n| "
#define TOML_SA_LIST_SEP TOML_SA_NEWLINE " - "
#define TOML_SA_LIST_BEG TOML_SA_LIST_SEP
#define TOML_SA_LIST_END
#define TOML_SA_LIST_NEW TOML_SA_NEWLINE TOML_SA_NEWLINE
#define TOML_SA_LIST_NXT TOML_SA_LIST_NEW
#endif
#define TOML_SA_NATIVE_VALUE_TYPE_LIST \
TOML_SA_LIST_BEG "std::string" \
TOML_SA_LIST_SEP "int64_t" \
TOML_SA_LIST_SEP "double" \
TOML_SA_LIST_SEP "bool" \
TOML_SA_LIST_SEP "toml::date" \
TOML_SA_LIST_SEP "toml::time" \
TOML_SA_LIST_SEP "toml::date_time" \
TOML_SA_LIST_END
#define TOML_SA_NODE_TYPE_LIST \
TOML_SA_LIST_BEG "toml::table" \
TOML_SA_LIST_SEP "toml::array" \
TOML_SA_LIST_SEP "toml::value<std::string>" \
TOML_SA_LIST_SEP "toml::value<int64_t>" \
TOML_SA_LIST_SEP "toml::value<double>" \
TOML_SA_LIST_SEP "toml::value<bool>" \
TOML_SA_LIST_SEP "toml::value<toml::date>" \
TOML_SA_LIST_SEP "toml::value<toml::time>" \
TOML_SA_LIST_SEP "toml::value<toml::date_time>" \
TOML_SA_LIST_END
#define TOML_SA_UNWRAPPED_NODE_TYPE_LIST \
TOML_SA_LIST_NEW "A native TOML value type" \
TOML_SA_NATIVE_VALUE_TYPE_LIST \
\
TOML_SA_LIST_NXT "A TOML node type" \
TOML_SA_NODE_TYPE_LIST
TOML_NAMESPACE_START
{
/// \brief A TOML node.
///
@ -23,37 +69,39 @@ namespace toml
protected:
node(node&& other) noexcept;
node& operator= (node&& rhs) noexcept;
node() noexcept = default;
node(const node&) noexcept;
node(node&&) noexcept;
node& operator= (const node&) noexcept;
node& operator= (node&&) noexcept;
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
impl::node_of<T>& ref_cast() & noexcept
[[nodiscard]]
TOML_ALWAYS_INLINE
impl::wrap_node<T>& ref_cast() & noexcept
{
return *reinterpret_cast<impl::node_of<T>*>(this);
return *reinterpret_cast<impl::wrap_node<T>*>(this);
}
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
impl::node_of<T>&& ref_cast() && noexcept
[[nodiscard]]
TOML_ALWAYS_INLINE
impl::wrap_node<T>&& ref_cast() && noexcept
{
return std::move(*reinterpret_cast<impl::node_of<T>*>(this));
return std::move(*reinterpret_cast<impl::wrap_node<T>*>(this));
}
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
const impl::node_of<T>& ref_cast() const & noexcept
[[nodiscard]]
TOML_ALWAYS_INLINE
const impl::wrap_node<T>& ref_cast() const & noexcept
{
return *reinterpret_cast<const impl::node_of<T>*>(this);
return *reinterpret_cast<const impl::wrap_node<T>*>(this);
}
template <typename N, typename T>
using ref_cast_type = decltype(std::declval<N>().template ref_cast<T>());
node() noexcept = default;
node(const node&) = delete;
node& operator= (const node&) = delete;
public:
virtual ~node() noexcept = default;
@ -93,18 +141,19 @@ namespace toml
///
/// \returns Returns true if this node is an instance of the specified type.
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
[[nodiscard]]
bool is() const noexcept
{
using type = impl::unwrapped<impl::remove_cvref_t<T>>;
using type = impl::unwrap_node<T>;
static_assert(
impl::is_value_or_node<type>,
"Template type parameter must be one of the TOML value types, a toml::table, or a toml::array"
(impl::is_native<type> || impl::is_one_of<type, table, array>) && !impl::is_cvref<type>,
"The template type argument of node::is() must be one of:"
TOML_SA_UNWRAPPED_NODE_TYPE_LIST
);
if constexpr (std::is_same_v<type, table>) return is_table();
else if constexpr (std::is_same_v<type, array>) return is_array();
else if constexpr (std::is_same_v<type, string>) return is_string();
else if constexpr (std::is_same_v<type, std::string>) return is_string();
else if constexpr (std::is_same_v<type, int64_t>) return is_integer();
else if constexpr (std::is_same_v<type, double>) return is_floating_point();
else if constexpr (std::is_same_v<type, bool>) return is_boolean();
@ -118,7 +167,7 @@ namespace toml
/// \brief Returns a pointer to the node as a toml::array, if it is one.
[[nodiscard]] virtual array* as_array() noexcept;
/// \brief Returns a pointer to the node as a toml::value<string>, if it is one.
[[nodiscard]] virtual toml::value<string>* as_string() noexcept;
[[nodiscard]] virtual toml::value<std::string>* as_string() noexcept;
/// \brief Returns a pointer to the node as a toml::value<int64_t>, if it is one.
[[nodiscard]] virtual toml::value<int64_t>* as_integer() noexcept;
/// \brief Returns a pointer to the node as a toml::value<double>, if it is one.
@ -134,7 +183,7 @@ namespace toml
[[nodiscard]] virtual const table* as_table() const noexcept;
[[nodiscard]] virtual const array* as_array() const noexcept;
[[nodiscard]] virtual const toml::value<string>* as_string() const noexcept;
[[nodiscard]] virtual const toml::value<std::string>* as_string() const noexcept;
[[nodiscard]] virtual const toml::value<int64_t>* as_integer() const noexcept;
[[nodiscard]] virtual const toml::value<double>* as_floating_point() const noexcept;
[[nodiscard]] virtual const toml::value<bool>* as_boolean() const noexcept;
@ -142,67 +191,292 @@ namespace toml
[[nodiscard]] virtual const toml::value<time>* as_time() const noexcept;
[[nodiscard]] virtual const toml::value<date_time>* as_date_time() const noexcept;
/// \brief Gets the raw value contained by this node.
/// \brief Checks if a node contains values/elements of only one type.
///
/// \detail \cpp
/// auto cfg = toml::parse("arr = [ 1, 2, 3, 4.0 ]");
/// toml::array& arr = *cfg["arr"].as_array();
///
/// \detail The optional returned by this function will only contain a value if the node was an instance of
/// toml::value with the same value type as the template argument. Additionally, some type are allowed to
/// convert to each other, for instance asking for an integer when the value exists as a double,
/// or requesting a string value as a string_view: \cpp
/// auto tbl = toml::parse(R"(
/// int_val = 10
/// float_val = 25.6
/// string_val = "kek"
/// )"sv);
///
/// if (auto val = tbl.get("int_val"sv)->value<int64_t>())
/// std::cout << "'int_val' as int64_t: "sv << *val << std::endl;
///
/// if (auto val = tbl.get("int_val"sv)->value<double>())
/// std::cout << "'int_val' as double: "sv << *val << std::endl;
///
/// if (auto val = tbl.get("float_val"sv)->value<int64_t>())
/// std::cout << "'float_val' as int64_t: "sv << *val << std::endl;
///
/// if (auto val = tbl.get("float_val"sv)->value<double>())
/// std::cout << "'float_val' as double: "sv << *val << std::endl;
///
/// if (auto val = tbl.get("string_val"sv)->value<std::string>())
/// std::cout << "'string_val' as std::string: "sv << *val << std::endl;
///
/// if (auto val = tbl.get("string_val"sv)->value<std::string_view>())
/// std::cout << "'string_val' as std::string_view: "sv << *val << std::endl;
///
/// if (auto val = tbl.get("string_val"sv)->value<int64_t>())
/// std::cout << "this line won't be printed because string_val wasn't an int."sv << std::endl;
/// toml::node* nonmatch{};
/// if (arr.is_homogeneous(toml::node_type::integer, nonmatch))
/// std::cout << "array was homogeneous"sv << "\n";
/// else
/// std::cout << "array was not homogeneous!\n"
/// << "first non-match was a "sv << nonmatch->type() << " at " << nonmatch->source() << "\n";
/// \ecpp
///
/// \out
/// 'int_val' as int64_t: 10
/// 'int_val' as double: 10
/// 'float_val' as int64_t: 25
/// 'float_val' as double: 25.6
/// 'string_val' as std::string: kek
/// 'string_val' as std::string_view: kek
/// array was not homogeneous!
/// first non-match was a floating-point at line 1, column 18
/// \eout
///
/// \param ntype A TOML node type. <br>
/// <strong><em>toml::node_type::none: </em></strong> "is every element the same type?" <br>
/// <strong><em>Anything else:</em></strong> "is every element one of these?"
/// \param first_nonmatch Reference to a pointer in which the address of the first non-matching element
/// will be stored if the return value is false.
///
/// \tparam T One of the TOML value types. Can also be a string_view.
///
/// \returns The underlying value if the node was a value of the matching type (or convertible to it), or an empty optional.
template <typename T>
[[nodiscard]] optional<T> value() const noexcept;
/// \returns True if the node was homogeneous.
///
/// \remarks Always returns `false` for empty tables and arrays.
[[nodiscard]] virtual bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept = 0;
/// \brief Gets the raw value contained by this node, or a default.
/// \brief Checks if a node contains values/elements of only one type (const overload).
[[nodiscard]] virtual bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept = 0;
/// \brief Checks if the node contains values/elements of only one type.
///
/// \tparam T Default value type. Must be (or be promotable to) one of the TOML value types.
/// \param default_value The default value to return if the node wasn't a value, wasn't the
/// correct type, or no conversion was possible.
/// \detail \cpp
/// auto arr = toml::array{ 1, 2, 3 };
/// std::cout << "homogenous: "sv << arr.is_homogeneous(toml::node_type::none) << "\n";
/// std::cout << "all floats: "sv << arr.is_homogeneous(toml::node_type::floating_point) << "\n";
/// std::cout << "all arrays: "sv << arr.is_homogeneous(toml::node_type::array) << "\n";
/// std::cout << "all ints: "sv << arr.is_homogeneous(toml::node_type::integer) << "\n";
///
/// \ecpp
///
/// \out
/// homogeneous: true
/// all floats: false
/// all arrays: false
/// all ints: true
/// \eout
///
/// \param ntype A TOML node type. <br>
/// <strong><em>toml::node_type::none: </em></strong> "is every element the same type?" <br>
/// <strong><em>Anything else:</em></strong> "is every element one of these?"
///
/// \returns The node's underlying value, or the default if the node wasn't a value, wasn't the
/// correct type, or no conversion was possible.
/// \returns True if the node was homogeneous.
///
/// \remarks Always returns `false` for empty tables and arrays.
[[nodiscard]] virtual bool is_homogeneous(node_type ntype) const noexcept = 0;
/// \brief Checks if the node contains values/elements of only one type.
///
/// \detail \cpp
/// auto arr = toml::array{ 1, 2, 3 };
/// std::cout << "homogenous: "sv << arr.is_homogeneous() << "\n";
/// std::cout << "all doubles: "sv << arr.is_homogeneous<double>() << "\n";
/// std::cout << "all arrays: "sv << arr.is_homogeneous<toml::array>() << "\n";
/// std::cout << "all integers: "sv << arr.is_homogeneous<int64_t>() << "\n";
///
/// \ecpp
///
/// \out
/// homogeneous: true
/// all floats: false
/// all arrays: false
/// all ints: true
/// \eout
///
/// \tparam ElemType A TOML node or value type. <br>
/// <strong><em>Left as `void`:</em></strong> "is every element the same type?" <br>
/// <strong><em>Explicitly specified:</em></strong> "is every element a T?"
///
/// \returns True if the node was homogeneous.
///
/// \remarks Always returns `false` for empty tables and arrays.
template <typename ElemType = void>
[[nodiscard]]
bool is_homogeneous() const noexcept
{
using type = impl::unwrap_node<ElemType>;
static_assert(
std::is_void_v<type>
|| ((impl::is_native<type> || impl::is_one_of<type, table, array>) && !impl::is_cvref<type>),
"The template type argument of node::is_homogeneous() must be void or one of:"
TOML_SA_UNWRAPPED_NODE_TYPE_LIST
);
return is_homogeneous(impl::node_type_of<type>);
}
private:
#ifndef DOXYGEN
template <typename T>
[[nodiscard]]
decltype(auto) get_value_exact() const noexcept;
#endif // !DOXYGEN
public:
/// \brief Gets the value contained by this node.
///
/// \detail This function has 'exact' retrieval semantics; the only return value types allowed are the
/// TOML native value types, or types that can losslessly represent a native value type (e.g.
/// std::wstring on Windows).
///
/// \tparam T One of the native TOML value types, or a type capable of losslessly representing one.
///
/// \returns The underlying value if the node was a value of the
/// matching type (or losslessly convertible to it), or an empty optional.
///
/// \see node::value()
template <typename T>
[[nodiscard]] auto value_or(T&& default_value) const noexcept;
[[nodiscard]]
optional<T> value_exact() const noexcept;
/// \brief Gets the value contained by this node.
///
/// \detail This function has 'permissive' retrieval semantics; some value types are allowed
/// to convert to others (e.g. retrieving a boolean as an integer), and the specified return value
/// type can be any type where a reasonable conversion from a native TOML value exists
/// (e.g. std::wstring on Windows). If the source value cannot be represented by
/// the destination type, an empty optional is returned.
///
/// \godbolt{zzG81K}
///
/// \cpp
/// auto tbl = toml::parse(R"(
/// int = -10
/// flt = 25.0
/// pi = 3.14159
/// bool = false
/// huge = 9223372036854775807
/// str = "foo"
/// )"sv);
///
/// const auto print_value_with_typename =
/// [&](std::string_view key, std::string_view type_name, auto* dummy)
/// {
/// std::cout << "- " << std::setw(18) << std::left << type_name;
/// using type = std::remove_pointer_t<decltype(dummy)>;
/// if (std::optional<type> val = tbl.get(key)->value<type>())
/// std::cout << *val << "\n";
/// else
/// std::cout << "n/a\n";
/// };
///
/// #define print_value(key, T) print_value_with_typename(key, #T, (T*)nullptr)
///
/// for (auto key : { "int", "flt", "pi", "bool", "huge", "str" })
/// {
/// std::cout << tbl[key].type() << " value '" << key << "' as:\n";
/// print_value(key, bool);
/// print_value(key, int);
/// print_value(key, unsigned int);
/// print_value(key, long long);
/// print_value(key, float);
/// print_value(key, double);
/// print_value(key, std::string);
/// print_value(key, std::string_view);
/// print_value(key, const char*);
/// std::cout << "\n";
/// }
/// \ecpp
///
/// \out
/// integer value 'int' as:
/// - bool true
/// - int -10
/// - unsigned int n/a
/// - long long -10
/// - float -10
/// - double -10
/// - std::string n/a
/// - std::string_view n/a
/// - const char* n/a
///
/// floating-point value 'flt' as:
/// - bool n/a
/// - int 25
/// - unsigned int 25
/// - long long 25
/// - float 25
/// - double 25
/// - std::string n/a
/// - std::string_view n/a
/// - const char* n/a
///
/// floating-point value 'pi' as:
/// - bool n/a
/// - int n/a
/// - unsigned int n/a
/// - long long n/a
/// - float 3.14159
/// - double 3.14159
/// - std::string n/a
/// - std::string_view n/a
/// - const char* n/a
///
/// boolean value 'bool' as:
/// - bool false
/// - int 0
/// - unsigned int 0
/// - long long 0
/// - float n/a
/// - double n/a
/// - std::string n/a
/// - std::string_view n/a
/// - const char* n/a
///
/// integer value 'huge' as:
/// - bool true
/// - int n/a
/// - unsigned int n/a
/// - long long 9223372036854775807
/// - float n/a
/// - double n/a
/// - std::string n/a
/// - std::string_view n/a
/// - const char* n/a
///
/// string value 'str' as:
/// - bool n/a
/// - int n/a
/// - unsigned int n/a
/// - long long n/a
/// - float n/a
/// - double n/a
/// - std::string foo
/// - std::string_view foo
/// - const char* foo
/// \eout
///
/// \tparam T One of the native TOML value types, or a type capable of converting to one.
///
/// \returns The underlying value if the node was a value of the matching type (or convertible to it)
/// and within the range of the output type, or an empty optional.
///
/// \attention If you want strict value retrieval semantics that do not allow for any type conversions,
/// use node::value_exact() instead.
///
/// \see node::value_exact()
template <typename T>
[[nodiscard]]
optional<T> value() const noexcept;
/// \brief Gets the raw value contained by this node, or a default.
///
/// \tparam T Default value type. Must be one of the native TOML value types,
/// or convertible to it.
/// \param default_value The default value to return if the node wasn't a value, wasn't the
/// correct type, or no conversion was possible.
///
/// \returns The underlying value if the node was a value of the matching type (or convertible to it)
/// and within the range of the output type, or the provided default.
///
/// \attention This function has the same permissive retrieval semantics as node::value(). If you want strict
/// value retrieval semantics that do not allow for any type conversions, use node::value_exact()
/// instead.
///
/// \see
/// - node::value()
/// - node::value_exact()
template <typename T>
[[nodiscard]]
auto value_or(T&& default_value) const noexcept;
//template <typename T>
//[[nodiscard]]
//std::vector<T> select_exact() const noexcept;
//template <typename T>
//[[nodiscard]]
//std::vector<T> select() const noexcept;
/// \brief Gets a pointer to the node as a more specific node type.
///
@ -211,14 +485,14 @@ namespace toml
/// toml::value<int64_t>* int_value = node->as<int64_t>();
/// toml::table* tbl = node->as<toml::table>();
/// if (int_value)
/// std::cout << "Node is a value<int64_t>" << std::endl;
/// std::cout << "Node is a value<int64_t>\n";
/// else if (tbl)
/// std::cout << "Node is a table" << std::endl;
/// std::cout << "Node is a table\n";
///
/// // fully-qualified value node types also work (useful for template code):
/// toml::value<int64_t>* int_value2 = node->as<toml::value<int64_t>>();
/// if (int_value2)
/// std::cout << "Node is a value<int64_t>" << std::endl;
/// std::cout << "Node is a value<int64_t>\n";
///
/// \ecpp
///
@ -226,18 +500,19 @@ namespace toml
///
/// \returns A pointer to the node as the given type, or nullptr if it was a different type.
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
impl::node_of<T>* as() noexcept
[[nodiscard]]
impl::wrap_node<T>* as() noexcept
{
using type = impl::unwrapped<T>;
using type = impl::unwrap_node<T>;
static_assert(
impl::is_value_or_node<type>,
"Template type parameter must be one of the TOML value types, a toml::table, or a toml::array"
(impl::is_native<type> || impl::is_one_of<type, table, array>) && !impl::is_cvref<type>,
"The template type argument of node::as() must be one of:"
TOML_SA_UNWRAPPED_NODE_TYPE_LIST
);
if constexpr (std::is_same_v<type, table>) return as_table();
else if constexpr (std::is_same_v<type, array>) return as_array();
else if constexpr (std::is_same_v<type, string>) return as_string();
else if constexpr (std::is_same_v<type, std::string>) return as_string();
else if constexpr (std::is_same_v<type, int64_t>) return as_integer();
else if constexpr (std::is_same_v<type, double>) return as_floating_point();
else if constexpr (std::is_same_v<type, bool>) return as_boolean();
@ -248,18 +523,19 @@ namespace toml
/// \brief Gets a pointer to the node as a more specific node type (const overload).
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
const impl::node_of<T>* as() const noexcept
[[nodiscard]]
const impl::wrap_node<T>* as() const noexcept
{
using type = impl::unwrapped<T>;
using type = impl::unwrap_node<T>;
static_assert(
impl::is_value_or_node<type>,
"Template type parameter must be one of the TOML value types, a toml::table, or a toml::array"
(impl::is_native<type> || impl::is_one_of<type, table, array>) && !impl::is_cvref<type>,
"The template type argument of node::as() must be one of:"
TOML_SA_UNWRAPPED_NODE_TYPE_LIST
);
if constexpr (std::is_same_v<type, table>) return as_table();
else if constexpr (std::is_same_v<type, array>) return as_array();
else if constexpr (std::is_same_v<type, string>) return as_string();
else if constexpr (std::is_same_v<type, std::string>) return as_string();
else if constexpr (std::is_same_v<type, int64_t>) return as_integer();
else if constexpr (std::is_same_v<type, double>) return as_floating_point();
else if constexpr (std::is_same_v<type, bool>) return as_boolean();
@ -280,7 +556,7 @@ namespace toml
static constexpr bool can_visit_any =
can_visit<Func, N, table>
|| can_visit<Func, N, array>
|| can_visit<Func, N, string>
|| can_visit<Func, N, std::string>
|| can_visit<Func, N, int64_t>
|| can_visit<Func, N, double>
|| can_visit<Func, N, bool>
@ -292,7 +568,7 @@ namespace toml
static constexpr bool can_visit_all =
can_visit<Func, N, table>
&& can_visit<Func, N, array>
&& can_visit<Func, N, string>
&& can_visit<Func, N, std::string>
&& can_visit<Func, N, int64_t>
&& can_visit<Func, N, double>
&& can_visit<Func, N, bool>
@ -309,7 +585,7 @@ namespace toml
static constexpr bool visit_is_nothrow =
visit_is_nothrow_one<Func, N, table>
&& visit_is_nothrow_one<Func, N, array>
&& visit_is_nothrow_one<Func, N, string>
&& visit_is_nothrow_one<Func, N, std::string>
&& visit_is_nothrow_one<Func, N, int64_t>
&& visit_is_nothrow_one<Func, N, double>
&& visit_is_nothrow_one<Func, N, bool>
@ -341,7 +617,8 @@ namespace toml
{
static_assert(
can_visit_any<Func&&, N&&>,
"Visitors must be invocable for at least one of the toml::node specializations"
"TOML node visitors must be invocable for at least one of the toml::node specializations:"
TOML_SA_NODE_TYPE_LIST
);
switch (n.type())
@ -357,8 +634,8 @@ namespace toml
break;
case node_type::string:
if constexpr (can_visit<Func&&, N&&, string>)
return std::forward<Func>(visitor)(std::forward<N>(n).template ref_cast<string>());
if constexpr (can_visit<Func&&, N&&, std::string>)
return std::forward<Func>(visitor)(std::forward<N>(n).template ref_cast<std::string>());
break;
case node_type::integer:
@ -402,7 +679,7 @@ namespace toml
using return_type =
nonvoid<typename visit_return_type<Func&&, N&&, table>::type,
nonvoid<typename visit_return_type<Func&&, N&&, array>::type,
nonvoid<typename visit_return_type<Func&&, N&&, string>::type,
nonvoid<typename visit_return_type<Func&&, N&&, std::string>::type,
nonvoid<typename visit_return_type<Func&&, N&&, int64_t>::type,
nonvoid<typename visit_return_type<Func&&, N&&, double>::type,
nonvoid<typename visit_return_type<Func&&, N&&, bool>::type,
@ -424,18 +701,20 @@ namespace toml
template <typename T, typename N>
[[nodiscard]] static decltype(auto) do_ref(N&& n) noexcept
[[nodiscard]]
static decltype(auto) do_ref(N&& n) noexcept
{
using type = impl::unwrapped<T>;
using type = impl::unwrap_node<T>;
static_assert(
impl::is_value_or_node<type>,
"Template type parameter must be one of the TOML value types, a toml::table, or a toml::array"
(impl::is_native<type> || impl::is_one_of<type, table, array>) && !impl::is_cvref<type>,
"The template type argument of node::ref() must be one of:"
TOML_SA_UNWRAPPED_NODE_TYPE_LIST
);
TOML_ASSERT(
n.template is<T>()
&& "template type argument T provided to toml::node::ref() didn't match the node's actual type"
);
if constexpr (impl::is_value<type>)
if constexpr (impl::is_native<type>)
return std::forward<N>(n).template ref_cast<type>().get();
else
return std::forward<N>(n).template ref_cast<type>();
@ -453,7 +732,7 @@ namespace toml
/// node.visit([](auto&& n)
/// {
/// if constexpr (toml::is_string<decltype(n)>)
/// do_something_with_a_string(*n)); //n is a toml::value<toml::string>
/// do_something_with_a_string(*n)); //n is a toml::value<std::string>
/// else if constexpr (toml::is_integer<decltype(n)>)
/// do_something_with_an_int(*n); //n is a toml::value<int64_t>
/// else
@ -472,21 +751,24 @@ namespace toml
///
/// \see https://en.wikipedia.org/wiki/Visitor_pattern
template <typename Func>
decltype(auto) visit(Func&& visitor) & noexcept(visit_is_nothrow<Func&&, node&>)
decltype(auto) visit(Func&& visitor) &
noexcept(visit_is_nothrow<Func&&, node&>)
{
return do_visit(*this, std::forward<Func>(visitor));
}
/// \brief Invokes a visitor on the node based on the node's concrete type (rvalue overload).
template <typename Func>
decltype(auto) visit(Func&& visitor) && noexcept(visit_is_nothrow<Func&&, node&&>)
decltype(auto) visit(Func&& visitor) &&
noexcept(visit_is_nothrow<Func&&, node&&>)
{
return do_visit(std::move(*this), std::forward<Func>(visitor));
}
/// \brief Invokes a visitor on the node based on the node's concrete type (const lvalue overload).
template <typename Func>
decltype(auto) visit(Func&& visitor) const& noexcept(visit_is_nothrow<Func&&, const node&>)
decltype(auto) visit(Func&& visitor) const&
noexcept(visit_is_nothrow<Func&&, const node&>)
{
return do_visit(*this, std::forward<Func>(visitor));
}
@ -511,25 +793,33 @@ namespace toml
///
/// \returns A reference to the underlying data.
template <typename T>
[[nodiscard]] impl::unwrapped<T>& ref() & noexcept
[[nodiscard]]
impl::unwrap_node<T>& ref() & noexcept
{
return do_ref<T>(*this);
}
/// \brief Gets a raw reference to a value node's underlying data (rvalue overload).
template <typename T>
[[nodiscard]] impl::unwrapped<T>&& ref() && noexcept
[[nodiscard]]
impl::unwrap_node<T>&& ref() && noexcept
{
return do_ref<T>(std::move(*this));
}
/// \brief Gets a raw reference to a value node's underlying data (const lvalue overload).
template <typename T>
[[nodiscard]] const impl::unwrapped<T>& ref() const& noexcept
[[nodiscard]]
const impl::unwrap_node<T>& ref() const& noexcept
{
return do_ref<T>(*this);
}
/// \brief Creates a `node_view` pointing to this node.
[[nodiscard]] explicit operator node_view<node>() noexcept;
/// \brief Creates a `node_view` pointing to this node (const overload).
[[nodiscard]] explicit operator node_view<const node>() const noexcept;
};
}
TOML_POP_WARNINGS //TOML_DISABLE_VTABLE_WARNINGS
TOML_NAMESPACE_END

View File

@ -13,11 +13,16 @@
#include "toml_node.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_SUGGEST_WARNINGS
namespace toml
TOML_NAMESPACE_START
{
TOML_EXTERNAL_LINKAGE
node::node(const node& /*other*/) noexcept
{
// does not copy source information - this is not an error
//
// see https://github.com/marzer/tomlplusplus/issues/49#issuecomment-665089577
}
TOML_EXTERNAL_LINKAGE
node::node(node && other) noexcept
: source_{ std::move(other.source_) }
@ -27,7 +32,18 @@ namespace toml
}
TOML_EXTERNAL_LINKAGE
node & node::operator= (node && rhs) noexcept
node& node::operator= (const node& /*rhs*/) noexcept
{
// does not copy source information - this is not an error
//
// see https://github.com/marzer/tomlplusplus/issues/49#issuecomment-665089577
source_ = {};
return *this;
}
TOML_EXTERNAL_LINKAGE
node& node::operator= (node && rhs) noexcept
{
source_ = std::move(rhs.source_);
rhs.source_.begin = {};
@ -49,7 +65,7 @@ namespace toml
TOML_MEMBER_ATTR(const) table* node::as_table() noexcept { return nullptr; }
TOML_MEMBER_ATTR(const) array* node::as_array() noexcept { return nullptr; }
TOML_MEMBER_ATTR(const) value<string>* node::as_string() noexcept { return nullptr; }
TOML_MEMBER_ATTR(const) value<std::string>* node::as_string() noexcept { return nullptr; }
TOML_MEMBER_ATTR(const) value<int64_t>* node::as_integer() noexcept { return nullptr; }
TOML_MEMBER_ATTR(const) value<double>* node::as_floating_point() noexcept { return nullptr; }
TOML_MEMBER_ATTR(const) value<bool>* node::as_boolean() noexcept { return nullptr; }
@ -59,7 +75,7 @@ namespace toml
TOML_MEMBER_ATTR(const) const table* node::as_table() const noexcept { return nullptr; }
TOML_MEMBER_ATTR(const) const array* node::as_array() const noexcept { return nullptr; }
TOML_MEMBER_ATTR(const) const value<string>* node::as_string() const noexcept { return nullptr; }
TOML_MEMBER_ATTR(const) const value<std::string>* node::as_string() const noexcept { return nullptr; }
TOML_MEMBER_ATTR(const) const value<int64_t>* node::as_integer() const noexcept { return nullptr; }
TOML_MEMBER_ATTR(const) const value<double>* node::as_floating_point() const noexcept { return nullptr; }
TOML_MEMBER_ATTR(const) const value<bool>* node::as_boolean() const noexcept { return nullptr; }
@ -70,6 +86,17 @@ namespace toml
TOML_MEMBER_ATTR(const) const source_region& node::source() const noexcept { return source_; }
#undef TOML_MEMBER_ATTR
}
TOML_POP_WARNINGS // TOML_DISABLE_SUGGEST_WARNINGS
TOML_EXTERNAL_LINKAGE
node::operator node_view<node>() noexcept
{
return node_view<node>(this);
}
TOML_EXTERNAL_LINKAGE
node::operator node_view<const node>() const noexcept
{
return node_view<const node>(this);
}
}
TOML_NAMESPACE_END

View File

@ -8,19 +8,16 @@
#include "toml_array.h"
#include "toml_value.h"
namespace toml
TOML_PUSH_WARNINGS
TOML_DISABLE_ARITHMETIC_WARNINGS
TOML_NAMESPACE_START
{
TOML_PUSH_WARNINGS
TOML_DISABLE_FLOAT_WARNINGS
template <typename Char, typename T>
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>&, const node_view<T>&);
/// \brief A view of a node.
///
/// \detail A node_view is like a std::optional<toml::node> with lots of toml-specific stuff built-in.
/// It _may_ represent a node, and allows you to do many of the same operations that you'd do
/// on nodes directly, as well as easily traversing the node tree by creating
/// \detail A node_view is like a std::optional<toml::node&> (if such a construct were legal), with lots of
/// toml-specific stuff built-in. It _may_ represent a node, and allows you to do many of the
/// same operations that you'd do on nodes directly, as well as easily traversing the node tree by creating
/// subviews (via node_view::operator[]). \cpp
///
/// auto tbl = toml::parse(R"(
@ -39,16 +36,16 @@ namespace toml
///
/// )"sv);
///
/// std::cout << tbl["title"] << std::endl;
/// std::cout << tbl["products"][0]["name"] << std::endl;
/// std::cout << tbl["products"][0]["keywords"] << std::endl;
/// std::cout << tbl["products"][0]["keywords"][2] << std::endl;
/// std::cout << tbl["title"] << "\n";
/// std::cout << tbl["products"][0]["name"] << "\n";
/// std::cout << tbl["products"][0]["keywords"] << "\n";
/// std::cout << tbl["products"][0]["keywords"][2] << "\n";
///
/// tbl["products"][0]["keywords"].as_array()->push_back("heavy");
/// std::cout << tbl["products"][0]["keywords"] << std::endl;
/// std::cout << "has product[2]: "sv << !!tbl["products"][2] << std::endl;
/// std::cout << "product[2]: "sv << tbl["products"][2] << std::endl;
/// \ecpp
/// std::cout << tbl["products"][0]["keywords"] << "\n";
/// std::cout << "has product[2]: "sv << !!tbl["products"][2] << "\n";
/// std::cout << "product[2]: "sv << tbl["products"][2] << "\n";
/// \ecpp
///
/// \out
/// "my hardware store"
@ -59,23 +56,22 @@ namespace toml
/// has product[2]: false
/// product[2]:
/// \eout
template <typename T>
template <typename ViewedType>
class TOML_API TOML_TRIVIAL_ABI node_view
{
static_assert(
impl::is_one_of<ViewedType, toml::node, const toml::node>,
"A toml::node_view<> must wrap toml::node or const toml::node."
);
public:
using viewed_type = T;
using viewed_type = ViewedType;
private:
friend class toml::table;
template <typename U> friend class toml::node_view;
template <typename T> friend class TOML_NAMESPACE::node_view;
mutable viewed_type* node_ = nullptr;
TOML_NODISCARD_CTOR
node_view(viewed_type* node) noexcept
: node_{ node }
{}
template <typename Func>
static constexpr bool visit_is_nothrow
= noexcept(std::declval<viewed_type*>()->visit(std::declval<Func&&>()));
@ -86,10 +82,39 @@ namespace toml
TOML_NODISCARD_CTOR
node_view() noexcept = default;
/// \brief Constructs node_view of a specific node.
TOML_NODISCARD_CTOR
explicit node_view(viewed_type* node) noexcept
: node_{ node }
{}
/// \brief Constructs node_view of a specific node.
TOML_NODISCARD_CTOR
explicit node_view(viewed_type& node) noexcept
: node_{ &node }
{}
///// \brief Copy constructor.
TOML_NODISCARD_CTOR
node_view(const node_view&) noexcept = default;
///// \brief Copy-assignment operator.
node_view& operator= (const node_view&) & noexcept = default;
///// \brief Move constructor.
TOML_NODISCARD_CTOR
node_view(node_view&&) noexcept = default;
///// \brief Move-assignment operator.
node_view& operator= (node_view&&) & noexcept = default;
/// \brief Returns true if the view references a node.
[[nodiscard]] explicit operator bool() const noexcept { return node_ != nullptr; }
/// \brief Returns the node that's being referenced by the view.
[[nodiscard]] viewed_type* get() const noexcept { return node_; }
[[nodiscard]] viewed_type* node() const noexcept { return node_; }
[[nodiscard, deprecated("use node_view::node() instead")]]
viewed_type* get() const noexcept { return node_; }
/// \brief Returns the type identifier for the viewed node.
[[nodiscard]] node_type type() const noexcept { return node_ ? node_->type() : node_type::none; }
@ -121,35 +146,30 @@ namespace toml
/// \brief Checks if this view references a node of a specific type.
///
/// \tparam U A TOML node or value type.
/// \tparam T A TOML node or value type.
///
/// \returns Returns true if the viewed node is an instance of the specified type.
///
/// \see toml::node::is()
template <typename U>
template <typename T>
[[nodiscard]]
bool is() const noexcept
{
return node_ ? node_->template is<U>() : false;
return node_ ? node_->template is<T>() : false;
}
/// \brief Gets a pointer to the viewed node as a more specific node type.
///
/// \tparam U The node type or TOML value type to cast to.
/// \tparam T The node type or TOML value type to cast to.
///
/// \returns A pointer to the node as the given type, or nullptr if it was a different type.
///
/// \see toml::node::as()
template <typename U>
template <typename T>
[[nodiscard]]
auto as() const noexcept
{
static_assert(
impl::is_value_or_node<impl::unwrapped<U>>,
"Template type parameter must be one of the basic value types, a toml::table, or a toml::array"
);
return node_ ? node_->template as<U>() : nullptr;
return node_ ? node_->template as<T>() : nullptr;
}
/// \brief Returns a pointer to the viewed node as a toml::table, if it is one.
@ -157,7 +177,7 @@ namespace toml
/// \brief Returns a pointer to the viewed node as a toml::array, if it is one.
[[nodiscard]] auto as_array() const noexcept { return as<array>(); }
/// \brief Returns a pointer to the viewed node as a toml::value<string>, if it is one.
[[nodiscard]] auto as_string() const noexcept { return as<string>(); }
[[nodiscard]] auto as_string() const noexcept { return as<std::string>(); }
/// \brief Returns a pointer to the viewed node as a toml::value<int64_t>, if it is one.
[[nodiscard]] auto as_integer() const noexcept { return as<int64_t>(); }
/// \brief Returns a pointer to the viewed node as a toml::value<double>, if it is one.
@ -171,21 +191,159 @@ namespace toml
/// \brief Returns a pointer to the viewed node as a toml::value<date_time>, if it is one.
[[nodiscard]] auto as_date_time() const noexcept { return as<date_time>(); }
/// \brief Checks if the viewed node contains values/elements of only one type.
///
/// \detail \cpp
/// auto cfg = toml::parse("arr = [ 1, 2, 3, 4.0 ]");
///
/// toml::node* nonmatch{};
/// if (cfg["arr"].is_homogeneous(toml::node_type::integer, nonmatch))
/// std::cout << "array was homogeneous"sv << "\n";
/// else
/// std::cout << "array was not homogeneous!\n"
/// << "first non-match was a "sv << nonmatch->type() << " at " << nonmatch->source() << "\n";
/// \ecpp
///
/// \out
/// array was not homogeneous!
/// first non-match was a floating-point at line 1, column 18
/// \eout
///
/// \param ntype A TOML node type. <br>
/// <strong><em>toml::node_type::none: </em></strong> "is every element the same type?" <br>
/// <strong><em>Anything else:</em></strong> "is every element one of these?"
/// \param first_nonmatch Reference to a pointer in which the address of the first non-matching element
/// will be stored if the return value is false.
///
/// \returns True if the viewed node was homogeneous.
///
/// \remarks Always returns `false` if the view does not reference a node, or if the viewed node is
/// an empty table or array.
[[nodiscard]]
bool is_homogeneous(node_type ntype, viewed_type*& first_nonmatch) const noexcept
{
if (!node_)
{
first_nonmatch = {};
return false;
}
return node_->is_homogeneous(ntype, first_nonmatch);
}
/// \brief Checks if the viewed node contains values/elements of only one type.
///
/// \detail \cpp
/// auto cfg = toml::parse("arr = [ 1, 2, 3 ]");
/// std::cout << "homogenous: "sv << cfg["arr"].is_homogeneous(toml::node_type::none) << "\n";
/// std::cout << "all floats: "sv << cfg["arr"].is_homogeneous(toml::node_type::floating_point) << "\n";
/// std::cout << "all arrays: "sv << cfg["arr"].is_homogeneous(toml::node_type::array) << "\n";
/// std::cout << "all ints: "sv << cfg["arr"].is_homogeneous(toml::node_type::integer) << "\n";
///
/// \ecpp
///
/// \out
/// homogeneous: true
/// all floats: false
/// all arrays: false
/// all ints: true
/// \eout
///
/// \param ntype A TOML node type. <br>
/// <strong><em>toml::node_type::none: </em></strong> "is every element the same type?" <br>
/// <strong><em>Anything else:</em></strong> "is every element one of these?"
///
/// \returns True if the viewed node was homogeneous.
///
/// \remarks Always returns `false` if the view does not reference a node, or if the viewed node is
/// an empty table or array.
[[nodiscard]]
bool is_homogeneous(node_type ntype) const noexcept
{
return node_ ? node_->is_homogeneous(ntype) : false;
}
/// \brief Checks if the viewed node contains values/elements of only one type.
///
/// \detail \cpp
/// auto cfg = toml::parse("arr = [ 1, 2, 3 ]");
/// std::cout << "homogenous: "sv << cfg["arr"].is_homogeneous() << "\n";
/// std::cout << "all doubles: "sv << cfg["arr"].is_homogeneous<double>() << "\n";
/// std::cout << "all arrays: "sv << cfg["arr"].is_homogeneous<toml::array>() << "\n";
/// std::cout << "all integers: "sv << cfg["arr"].is_homogeneous<int64_t>() << "\n";
///
/// \ecpp
///
/// \out
/// homogeneous: true
/// all floats: false
/// all arrays: false
/// all ints: true
/// \eout
///
/// \tparam ElemType A TOML node or value type. <br>
/// <strong><em>Left as `void`:</em></strong> "is every element the same type?" <br>
/// <strong><em>Explicitly specified:</em></strong> "is every element a T?"
///
/// \returns True if the viewed node was homogeneous.
///
/// \remarks Always returns `false` if the view does not reference a node, or if the viewed node is
/// an empty table or array.
template <typename ElemType = void>
[[nodiscard]]
bool is_homogeneous() const noexcept
{
return node_ ? node_->template is_homogeneous<impl::unwrap_node<ElemType>>() : false;
}
/// \brief Gets the value contained by the referenced node.
///
/// \detail This function has 'exact' retrieval semantics; the only return value types allowed are the
/// TOML native value types, or types that can losslessly represent a native value type (e.g.
/// std::wstring on Windows).
///
/// \tparam T One of the native TOML value types, or a type capable of losslessly representing one.
///
/// \returns The underlying value if the node was a value of the
/// matching type (or losslessly convertible to it), or an empty optional.
///
/// \see node_view::value()
template <typename T>
[[nodiscard]]
optional<T> value_exact() const noexcept
{
if (node_)
return node_->template value_exact<T>();
return {};
}
TOML_PUSH_WARNINGS
TOML_DISABLE_INIT_WARNINGS
/// \brief Gets the raw value contained by the referenced node.
/// \brief Gets the value contained by the referenced node.
///
/// \tparam U One of the TOML value types. Can also be a string_view.
/// \detail This function has 'permissive' retrieval semantics; some value types are allowed
/// to convert to others (e.g. retrieving a boolean as an integer), and the specified return value
/// type can be any type where a reasonable conversion from a native TOML value exists
/// (e.g. std::wstring on Windows). If the source value cannot be represented by
/// the destination type, an empty optional is returned. See node::value() for examples.
///
/// \tparam T One of the native TOML value types, or a type capable of convertible to one.
///
/// \returns The underlying value if the node was a value of the matching type (or convertible to it), or an empty optional.
/// \returns The underlying value if the node was a value of the matching type (or convertible to it)
/// and within the range of the output type, or an empty optional.
///
/// \see node::value()
template <typename U>
[[nodiscard]] optional<U> value() const noexcept
/// \attention If you want strict value retrieval semantics that do not allow for any type conversions,
/// use node_view::value_exact() instead.
///
/// \see
/// - node_view::value()
/// - node_view::value_exact()
template <typename T>
[[nodiscard]]
optional<T> value() const noexcept
{
if (node_)
return node_->template value<U>();
return node_->template value<T>();
return {};
}
@ -193,21 +351,62 @@ namespace toml
/// \brief Gets the raw value contained by the referenced node, or a default.
///
/// \tparam U Default value type. Must be (or be promotable to) one of the TOML value types.
/// \param default_value The default value to return if the view did not reference a node,
/// or if the node wasn't a value, wasn't the correct type, or no conversion was possible.
/// \tparam T Default value type. Must be one of the native TOML value types,
/// or convertible to it.
/// \param default_value The default value to return if the node wasn't a value, wasn't the
/// correct type, or no conversion was possible.
///
/// \returns The node's underlying value, or the default if the node wasn't a value, wasn't the
/// correct type, or no conversion was possible.
/// \returns The underlying value if the node was a value of the matching type (or convertible to it)
/// and within the range of the output type, or the provided default.
///
/// \see node::value_or()
template <typename U>
[[nodiscard]] auto value_or(U&& default_value) const noexcept
/// \attention This function has the same permissive retrieval semantics as node::value(). If you want strict
/// value retrieval semantics that do not allow for any type conversions, use node_view::value_exact()
/// instead.
///
/// \see
/// - node_view::value()
/// - node_view::value_exact()
template <typename T>
[[nodiscard]]
auto value_or(T&& default_value) const noexcept
{
using return_type = decltype(node_->value_or(std::forward<U>(default_value)));
if (node_)
return node_->value_or(std::forward<U>(default_value));
return return_type{ std::forward<U>(default_value) };
using namespace ::toml::impl;
static_assert(
!is_wide_string<T> || TOML_WINDOWS_COMPAT,
"Retrieving values as wide-character strings is only "
"supported on Windows with TOML_WINDOWS_COMPAT enabled."
);
if constexpr (is_wide_string<T>)
{
#if TOML_WINDOWS_COMPAT
if (node_)
return node_->value_or(std::forward<T>(default_value));
return std::wstring{ std::forward<T>(default_value) };
#else
static_assert(impl::dependent_false<T>, "Evaluated unreachable branch!");
#endif
}
else
{
using value_type = std::conditional_t<
std::is_pointer_v<std::decay_t<T>>,
std::add_pointer_t<std::add_const_t<std::remove_pointer_t<std::decay_t<T>>>>,
std::decay_t<T>
>;
if (node_)
return node_->value_or(std::forward<T>(default_value));
if constexpr (std::is_pointer_v<value_type>)
return value_type{ default_value };
else
return std::forward<T>(default_value);
}
}
/// \brief Invokes a visitor on the viewed node based on its concrete type.
@ -243,26 +442,23 @@ namespace toml
///
/// \ecpp
///
/// \tparam U One of the TOML value types.
/// \tparam T One of the TOML value types.
///
/// \returns A reference to the underlying data.
template <typename U>
[[nodiscard]] decltype(auto) ref() const noexcept
template <typename T>
[[nodiscard]]
decltype(auto) ref() const noexcept
{
using type = impl::unwrapped<U>;
static_assert(
impl::is_value_or_node<type>,
"Template type parameter must be one of the TOML value types, a toml::table, or a toml::array"
);
TOML_ASSERT(
node_
&& "toml::node_view::ref() called on a node_view that did not reference a node"
);
return node_->template ref<type>();
return node_->template ref<impl::unwrap_node<T>>();
}
/// \brief Returns true if the viewed node is a table with the same contents as RHS.
[[nodiscard]] friend bool operator == (const node_view& lhs, const table& rhs) noexcept
[[nodiscard]]
friend bool operator == (const node_view& lhs, const table& rhs) noexcept
{
if (lhs.node_ == &rhs)
return true;
@ -272,7 +468,8 @@ namespace toml
TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const table&, )
/// \brief Returns true if the viewed node is an array with the same contents as RHS.
[[nodiscard]] friend bool operator == (const node_view& lhs, const array& rhs) noexcept
[[nodiscard]]
friend bool operator == (const node_view& lhs, const array& rhs) noexcept
{
if (lhs.node_ == &rhs)
return true;
@ -282,46 +479,73 @@ namespace toml
TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const array&, )
/// \brief Returns true if the viewed node is a value with the same value as RHS.
template <typename U>
[[nodiscard]] friend bool operator == (const node_view& lhs, const toml::value<U>& rhs) noexcept
template <typename T>
[[nodiscard]]
friend bool operator == (const node_view& lhs, const toml::value<T>& rhs) noexcept
{
if (lhs.node_ == &rhs)
return true;
const auto val = lhs.as<U>();
const auto val = lhs.as<T>();
return val && *val == rhs;
}
TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const toml::value<U>&, template <typename U>)
TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const toml::value<T>&, template <typename T>)
/// \brief Returns true if the viewed node is a value with the same value as RHS.
template <typename U, typename = std::enable_if_t<impl::is_value_or_promotable<U>>>
[[nodiscard]] friend bool operator == (const node_view& lhs, const U& rhs) noexcept
template <typename T, typename = std::enable_if_t<
impl::is_native<T>
|| impl::is_losslessly_convertible_to_native<T>
>>
[[nodiscard]]
friend bool operator == (const node_view& lhs, const T& rhs) noexcept
{
const auto val = lhs.as<impl::promoted<U>>();
return val && *val == rhs;
static_assert(
!impl::is_wide_string<T> || TOML_WINDOWS_COMPAT,
"Comparison with wide-character strings is only "
"supported on Windows with TOML_WINDOWS_COMPAT enabled."
);
if constexpr (impl::is_wide_string<T>)
{
#if TOML_WINDOWS_COMPAT
return lhs == impl::narrow(rhs);
#else
static_assert(impl::dependent_false<T>, "Evaluated unreachable branch!");
#endif
}
else
{
const auto val = lhs.as<impl::native_type_of<T>>();
return val && *val == rhs;
}
}
TOML_ASYMMETRICAL_EQUALITY_OPS(
const node_view&,
const U&,
template <typename U, typename = std::enable_if_t<impl::is_value_or_promotable<U>>>
const node_view&,
const T&,
template <typename T, typename = std::enable_if_t<
impl::is_native<T>
|| impl::is_losslessly_convertible_to_native<T>
>>
)
/// \brief Returns true if the viewed node is an array with the same contents as the RHS initializer list.
template <typename U>
[[nodiscard]] friend bool operator == (const node_view& lhs, const std::initializer_list<U>& rhs) noexcept
template <typename T>
[[nodiscard]]
friend bool operator == (const node_view& lhs, const std::initializer_list<T>& rhs) noexcept
{
const auto arr = lhs.as<array>();
return arr && *arr == rhs;
}
TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const std::initializer_list<U>&, template <typename U>)
TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const std::initializer_list<T>&, template <typename T>)
/// \brief Returns true if the viewed node is an array with the same contents as the RHS vector.
template <typename U>
[[nodiscard]] friend bool operator == (const node_view& lhs, const std::vector<U>& rhs) noexcept
template <typename T>
[[nodiscard]]
friend bool operator == (const node_view& lhs, const std::vector<T>& rhs) noexcept
{
const auto arr = lhs.as<array>();
return arr && *arr == rhs;
}
TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const std::vector<U>&, template <typename U>)
TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const std::vector<T>&, template <typename T>)
/// \brief Returns a view of the selected subnode.
///
@ -329,34 +553,63 @@ namespace toml
///
/// \returns A view of the selected node if this node represented a table and it contained a
/// value at the given key, or an empty view.
[[nodiscard]] node_view operator[] (string_view key) const noexcept
[[nodiscard]]
node_view operator[] (std::string_view key) const noexcept
{
if (auto tbl = this->as_table())
return { tbl->get(key) };
return { nullptr };
return node_view{ tbl->get(key) };
return node_view{ nullptr };
}
#if TOML_WINDOWS_COMPAT
/// \brief Returns a view of the selected subnode.
///
/// \param key The key of the node to retrieve
///
/// \returns A view of the selected node if this node represented a table and it contained a
/// value at the given key, or an empty view.
///
/// \attention This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
[[nodiscard]]
node_view operator[] (std::wstring_view key) const noexcept
{
if (auto tbl = this->as_table())
return node_view{ tbl->get(key) };
return node_view{ nullptr };
}
#endif // TOML_WINDOWS_COMPAT
/// \brief Returns a view of the selected subnode.
///
/// \param index The index of the node to retrieve
///
/// \returns A view of the selected node if this node represented an array and it contained a
/// value at the given index, or an empty view.
[[nodiscard]] node_view operator[] (size_t index) const noexcept
[[nodiscard]]
node_view operator[] (size_t index) const noexcept
{
if (auto arr = this->as_array())
return { arr->get(index) };
return { nullptr };
return node_view{ arr->get(index) };
return node_view{ nullptr };
}
template <typename Char, typename U>
friend std::basic_ostream<Char>& operator << (std::basic_ostream<Char>&, const node_view<U>&);
template <typename Char, typename T>
friend std::basic_ostream<Char>& operator << (std::basic_ostream<Char>&, const node_view<T>&);
};
template <typename T> node_view(const value<T>&) -> node_view<const node>;
node_view(const table&) -> node_view<const node>;
node_view(const array&) -> node_view<const node>;
template <typename T> node_view(value<T>&) -> node_view<node>;
node_view(table&) -> node_view<node>;
node_view(array&) -> node_view<node>;
template <typename T> node_view(const T*) -> node_view<const node>;
template <typename T> node_view(T*) -> node_view<node>;
/// \brief Prints the viewed node out to a stream.
template <typename Char, typename T>
TOML_EXTERNAL_LINKAGE
std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& os, const node_view<T>& nv)
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& os, const node_view<T>& nv)
{
if (nv.node_)
{
@ -368,13 +621,61 @@ namespace toml
return os;
}
#if !TOML_ALL_INLINE
extern template class TOML_API node_view<node>;
extern template class TOML_API node_view<const node>;
extern template TOML_API std::ostream& operator << (std::ostream&, const node_view<node>&);
extern template TOML_API std::ostream& operator << (std::ostream&, const node_view<const node>&);
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
extern template class TOML_API node_view<node>;
extern template class TOML_API node_view<const node>;
extern template TOML_API std::ostream& operator << (std::ostream&, const node_view<node>&);
extern template TOML_API std::ostream& operator << (std::ostream&, const node_view<const node>&);
#define TOML_EXTERN(name, T) \
extern template TOML_API optional<T> node_view<node>::name<T>() const noexcept; \
extern template TOML_API optional<T> node_view<const node>::name<T>() const noexcept
TOML_EXTERN(value_exact, std::string_view);
TOML_EXTERN(value_exact, std::string);
TOML_EXTERN(value_exact, const char*);
TOML_EXTERN(value_exact, int64_t);
TOML_EXTERN(value_exact, double);
TOML_EXTERN(value_exact, date);
TOML_EXTERN(value_exact, time);
TOML_EXTERN(value_exact, date_time);
TOML_EXTERN(value_exact, bool);
TOML_EXTERN(value, std::string_view);
TOML_EXTERN(value, std::string);
TOML_EXTERN(value, const char*);
TOML_EXTERN(value, signed char);
TOML_EXTERN(value, signed short);
TOML_EXTERN(value, signed int);
TOML_EXTERN(value, signed long);
TOML_EXTERN(value, signed long long);
TOML_EXTERN(value, unsigned char);
TOML_EXTERN(value, unsigned short);
TOML_EXTERN(value, unsigned int);
TOML_EXTERN(value, unsigned long);
TOML_EXTERN(value, unsigned long long);
TOML_EXTERN(value, double);
TOML_EXTERN(value, float);
TOML_EXTERN(value, date);
TOML_EXTERN(value, time);
TOML_EXTERN(value, date_time);
TOML_EXTERN(value, bool);
#ifdef __cpp_lib_char8_t
TOML_EXTERN(value_exact, std::u8string_view);
TOML_EXTERN(value_exact, std::u8string);
TOML_EXTERN(value_exact, const char8_t*);
TOML_EXTERN(value, std::u8string_view);
TOML_EXTERN(value, std::u8string);
TOML_EXTERN(value, const char8_t*);
#endif
#if TOML_WINDOWS_COMPAT
TOML_EXTERN(value_exact, std::wstring);
TOML_EXTERN(value, std::wstring);
#endif
#undef TOML_EXTERN
TOML_POP_WARNINGS // TOML_DISABLE_FLOAT_WARNINGS
#endif // !TOML_HEADER_ONLY
}
TOML_NAMESPACE_END
TOML_POP_WARNINGS // TOML_DISABLE_ARITHMETIC_WARNINGS

View File

@ -10,28 +10,20 @@
#error This header cannot not be included when TOML_PARSER is disabled.
#endif
//# }}
TOML_PUSH_WARNINGS
TOML_DISABLE_ALL_WARNINGS
TOML_DISABLE_WARNINGS
#if TOML_EXCEPTIONS
#include <stdexcept>
#endif
TOML_POP_WARNINGS
TOML_ENABLE_WARNINGS
TOML_PUSH_WARNINGS
TOML_DISABLE_INIT_WARNINGS
TOML_DISABLE_VTABLE_WARNINGS
namespace toml
TOML_NAMESPACE_START
{
#if TOML_LARGE_FILES
TOML_ABI_NAMESPACE_START(lf)
#else
TOML_ABI_NAMESPACE_START(sf)
#endif
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex)
#if TOML_DOXYGEN || !TOML_EXCEPTIONS
TOML_ABI_NAMESPACE_START(noex)
#if defined(DOXYGEN) || !TOML_EXCEPTIONS
/// \brief An error generated when parsing fails.
///
@ -80,8 +72,6 @@ namespace toml
#else
TOML_ABI_NAMESPACE_START(ex)
class parse_error final
: public std::runtime_error
{
@ -125,7 +115,6 @@ namespace toml
#endif
TOML_ABI_NAMESPACE_END // TOML_EXCEPTIONS
TOML_ABI_NAMESPACE_END // TOML_LARGE_FILES
/// \brief Prints a parse_error to a stream.
///
@ -136,7 +125,7 @@ namespace toml
/// }
/// catch (const toml::parse_error & err)
/// {
/// std::cerr << "Parsing failed:\n"sv << err << std::endl;
/// std::cerr << "Parsing failed:\n"sv << err << "\n";
/// }
/// \ecpp
///
@ -152,8 +141,7 @@ namespace toml
///
/// \returns The input stream.
template <typename Char>
TOML_EXTERNAL_LINKAGE
std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const parse_error& rhs)
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const parse_error& rhs)
{
lhs << rhs.description();
lhs << "\n\t(error occurred at "sv;
@ -162,9 +150,10 @@ namespace toml
return lhs;
}
#if !TOML_ALL_INLINE
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
extern template TOML_API std::ostream& operator << (std::ostream&, const parse_error&);
#endif
}
TOML_NAMESPACE_END
TOML_POP_WARNINGS
TOML_POP_WARNINGS // TOML_DISABLE_INIT_WARNINGS

View File

@ -13,14 +13,11 @@
#include "toml_table.h"
#include "toml_utf8_streams.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml
TOML_NAMESPACE_START
{
#if TOML_DOXYGEN || !TOML_EXCEPTIONS
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex)
TOML_ABI_NAMESPACE_START(parse_noex)
#if defined(DOXYGEN) || !TOML_EXCEPTIONS
/// \brief The result of a parsing operation.
///
@ -32,7 +29,7 @@ namespace toml
/// if (result)
/// do_stuff_with_a_table(result); //implicitly converts to table&
/// else
/// std::cerr << "Parse failed:\n"sv << result.error() << std::endl;
/// std::cerr << "Parse failed:\n"sv << result.error() << "\n";
///
/// \ecpp
///
@ -61,8 +58,8 @@ namespace toml
{
private:
std::aligned_storage_t<
(sizeof(table) < sizeof(parse_error) ? sizeof(parse_error) : sizeof(table)),
(alignof(table) < alignof(parse_error) ? alignof(parse_error) : alignof(table))
(sizeof(toml::table) < sizeof(parse_error) ? sizeof(parse_error) : sizeof(toml::table)),
(alignof(toml::table) < alignof(parse_error) ? alignof(parse_error) : alignof(toml::table))
> storage;
bool is_err;
@ -71,7 +68,7 @@ namespace toml
if (is_err)
TOML_LAUNDER(reinterpret_cast<parse_error*>(&storage))->~parse_error();
else
TOML_LAUNDER(reinterpret_cast<table*>(&storage))->~table();
TOML_LAUNDER(reinterpret_cast<toml::table*>(&storage))->~table();
}
public:
@ -86,53 +83,66 @@ namespace toml
[[nodiscard]] bool succeeded() const noexcept { return !is_err; }
/// \brief Returns true if parsing failed.
[[nodiscard]] bool failed() const noexcept { return is_err; }
/// \brief Returns true if parsing succeeeded.
/// \brief Returns true if parsing succeeded.
[[nodiscard]] explicit operator bool() const noexcept { return !is_err; }
/// \brief Returns the internal toml::table.
[[nodiscard]] table& get() & noexcept
[[nodiscard]]
toml::table& table() & noexcept
{
TOML_ASSERT(!is_err);
return *TOML_LAUNDER(reinterpret_cast<table*>(&storage));
return *TOML_LAUNDER(reinterpret_cast<toml::table*>(&storage));
}
/// \brief Returns the internal toml::table (rvalue overload).
[[nodiscard]] table&& get() && noexcept
[[nodiscard]]
toml::table&& table() && noexcept
{
TOML_ASSERT(!is_err);
return std::move(*TOML_LAUNDER(reinterpret_cast<table*>(&storage)));
return std::move(*TOML_LAUNDER(reinterpret_cast<toml::table*>(&storage)));
}
/// \brief Returns the internal toml::table (const lvalue overload).
[[nodiscard]] const table& get() const& noexcept
[[nodiscard]]
const toml::table& table() const& noexcept
{
TOML_ASSERT(!is_err);
return *TOML_LAUNDER(reinterpret_cast<const table*>(&storage));
return *TOML_LAUNDER(reinterpret_cast<const toml::table*>(&storage));
}
[[nodiscard, deprecated("use parse_result::table() instead")]]
toml::table& get() & noexcept { return table(); }
[[nodiscard, deprecated("use parse_result::table() instead")]]
toml::table&& get() && noexcept { return std::move(table()); }
[[nodiscard, deprecated("use parse_result::table() instead")]]
const toml::table& get() const& noexcept { return table(); }
/// \brief Returns the internal toml::parse_error.
[[nodiscard]] parse_error& error() & noexcept
[[nodiscard]]
parse_error& error() & noexcept
{
TOML_ASSERT(is_err);
return *TOML_LAUNDER(reinterpret_cast<parse_error*>(&storage));
}
/// \brief Returns the internal toml::parse_error (rvalue overload).
[[nodiscard]] parse_error&& error() && noexcept
[[nodiscard]]
parse_error&& error() && noexcept
{
TOML_ASSERT(is_err);
return std::move(*TOML_LAUNDER(reinterpret_cast<parse_error*>(&storage)));
}
/// \brief Returns the internal toml::parse_error (const lvalue overload).
[[nodiscard]] const parse_error& error() const& noexcept
[[nodiscard]]
const parse_error& error() const& noexcept
{
TOML_ASSERT(is_err);
return *TOML_LAUNDER(reinterpret_cast<const parse_error*>(&storage));
}
/// \brief Returns the internal toml::table.
[[nodiscard]] operator table& () noexcept { return get(); }
[[nodiscard]] operator toml::table& () noexcept { return table(); }
/// \brief Returns the internal toml::table (rvalue overload).
[[nodiscard]] operator table&& () noexcept { return std::move(get()); }
[[nodiscard]] operator toml::table&& () noexcept { return std::move(table()); }
/// \brief Returns the internal toml::table (const lvalue overload).
[[nodiscard]] operator const table& () const noexcept { return get(); }
[[nodiscard]] operator const toml::table& () const noexcept { return table(); }
/// \brief Returns the internal toml::parse_error.
[[nodiscard]] explicit operator parse_error& () noexcept { return error(); }
@ -142,10 +152,10 @@ namespace toml
[[nodiscard]] explicit operator const parse_error& () const noexcept { return error(); }
TOML_NODISCARD_CTOR
explicit parse_result(table&& tbl) noexcept
explicit parse_result(toml::table&& tbl) noexcept
: is_err{ false }
{
::new (&storage) table{ std::move(tbl) };
::new (&storage) toml::table{ std::move(tbl) };
}
TOML_NODISCARD_CTOR
@ -163,7 +173,7 @@ namespace toml
if (is_err)
::new (&storage) parse_error{ std::move(res).error() };
else
::new (&storage) table{ std::move(res).get() };
::new (&storage) toml::table{ std::move(res).table() };
}
/// \brief Move-assignment operator.
@ -176,14 +186,14 @@ namespace toml
if (is_err)
::new (&storage) parse_error{ std::move(rhs).error() };
else
::new (&storage) table{ std::move(rhs).get() };
::new (&storage) toml::table{ std::move(rhs).table() };
}
else
{
if (is_err)
error() = std::move(rhs).error();
else
get() = std::move(rhs).get();
table() = std::move(rhs).table();
}
return *this;
}
@ -202,98 +212,152 @@ namespace toml
/// or an empty node view.
///
/// \see toml::node_view
[[nodiscard]] node_view<node> operator[] (string_view key) noexcept
[[nodiscard]]
node_view<node> operator[] (string_view key) noexcept
{
return is_err ? node_view<node>{} : get()[key];
return is_err ? node_view<node>{} : table()[key];
}
/// \brief Gets a node_view for the selected key-value pair in the wrapped table (const overload).
[[nodiscard]] node_view<const node> operator[] (string_view key) const noexcept
///
/// \param key The key used for the lookup.
///
/// \returns A view of the value at the given key if parsing was successful and a matching key existed,
/// or an empty node view.
///
/// \see toml::node_view
[[nodiscard]]
node_view<const node> operator[] (string_view key) const noexcept
{
return is_err ? node_view<const node>{} : get()[key];
return is_err ? node_view<const node>{} : table()[key];
}
#if TOML_WINDOWS_COMPAT
/// \brief Gets a node_view for the selected key-value pair in the wrapped table.
///
/// \param key The key used for the lookup.
///
/// \returns A view of the value at the given key if parsing was successful and a matching key existed,
/// or an empty node view.
///
/// \see toml::node_view
///
/// \attention This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
[[nodiscard]]
node_view<node> operator[] (std::wstring_view key) noexcept
{
return is_err ? node_view<node>{} : table()[key];
}
/// \brief Gets a node_view for the selected key-value pair in the wrapped table (const overload).
///
/// \param key The key used for the lookup.
///
/// \returns A view of the value at the given key if parsing was successful and a matching key existed,
/// or an empty node view.
///
/// \see toml::node_view
///
/// \attention This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
[[nodiscard]]
node_view<const node> operator[] (std::wstring_view key) const noexcept
{
return is_err ? node_view<const node>{} : table()[key];
}
#endif // TOML_WINDOWS_COMPAT
/// \brief Returns an iterator to the first key-value pair in the wrapped table.
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
[[nodiscard]]
table_iterator begin() noexcept
{
return is_err ? table_iterator{} : table().begin();
}
/// \brief Returns an iterator to the first key-value pair in the wrapped table.
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
[[nodiscard]] table_iterator begin() noexcept
[[nodiscard]]
const_table_iterator begin() const noexcept
{
return is_err ? table_iterator{} : get().begin();
return is_err ? const_table_iterator{} : table().begin();
}
/// \brief Returns an iterator to the first key-value pair in the wrapped table.
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
[[nodiscard]] const_table_iterator begin() const noexcept
[[nodiscard]]
const_table_iterator cbegin() const noexcept
{
return is_err ? const_table_iterator{} : get().begin();
}
/// \brief Returns an iterator to the first key-value pair in the wrapped table.
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
[[nodiscard]] const_table_iterator cbegin() const noexcept
{
return is_err ? const_table_iterator{} : get().cbegin();
return is_err ? const_table_iterator{} : table().cbegin();
}
/// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table.
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
[[nodiscard]] table_iterator end() noexcept
[[nodiscard]]
table_iterator end() noexcept
{
return is_err ? table_iterator{} : get().end();
return is_err ? table_iterator{} : table().end();
}
/// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table.
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
[[nodiscard]] const_table_iterator end() const noexcept
[[nodiscard]]
const_table_iterator end() const noexcept
{
return is_err ? const_table_iterator{} : get().end();
return is_err ? const_table_iterator{} : table().end();
}
/// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table.
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
[[nodiscard]] const_table_iterator cend() const noexcept
[[nodiscard]]
const_table_iterator cend() const noexcept
{
return is_err ? const_table_iterator{} : get().cend();
return is_err ? const_table_iterator{} : table().cend();
}
};
TOML_ABI_NAMESPACE_END
#else
using parse_result = table;
#endif
}
namespace toml::impl
{
#if TOML_EXCEPTIONS
TOML_ABI_NAMESPACE_START(impl_ex)
#else
TOML_ABI_NAMESPACE_START(impl_noex)
#endif
[[nodiscard]] TOML_API
parse_result do_parse(utf8_reader_interface&&) TOML_MAY_THROW;
TOML_ABI_NAMESPACE_END // TOML_EXCEPTIONS
}
TOML_NAMESPACE_END
namespace toml
TOML_IMPL_NAMESPACE_START
{
#if TOML_EXCEPTIONS
TOML_ABI_NAMESPACE_START(parse_ex)
#else
TOML_ABI_NAMESPACE_START(parse_noex)
#endif
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex)
[[nodiscard]] TOML_API parse_result do_parse(utf8_reader_interface&&) TOML_MAY_THROW;
TOML_ABI_NAMESPACE_END // TOML_EXCEPTIONS
}
TOML_IMPL_NAMESPACE_END
#if TOML_EXCEPTIONS
#define TOML_THROW_PARSE_ERROR(msg, path) \
throw parse_error{ \
msg, source_position{}, std::make_shared<const std::string>(std::move(path)) \
}
#else
#define TOML_THROW_PARSE_ERROR(msg, path) \
return parse_result{ parse_error{ \
msg, source_position{}, std::make_shared<const std::string>(std::move(path)) \
}}
#endif
TOML_NAMESPACE_START
{
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex)
/// \brief Parses a TOML document from a string view.
///
/// \detail \cpp
/// auto tbl = toml::parse("a = 3"sv);
/// std::cout << tbl["a"] << std::endl;
/// std::cout << tbl["a"] << "\n";
///
/// \ecpp
///
@ -316,7 +380,7 @@ namespace toml
///
/// \detail \cpp
/// auto tbl = toml::parse("a = 3"sv, "foo.toml");
/// std::cout << tbl["a"] << std::endl;
/// std::cout << tbl["a"] << "\n";
///
/// \ecpp
///
@ -326,6 +390,8 @@ namespace toml
///
/// \param doc The TOML document to parse. Must be valid UTF-8.
/// \param source_path The path used to initialize each node's `source().path`.
/// If you don't have a path (or you have no intention of using paths in diagnostics)
/// then this parameter can safely be left blank.
///
/// \returns <strong><em>With exceptions:</em></strong> A toml::table. <br>
/// <strong><em>Without exceptions:</em></strong> A toml::parse_result detailing the parsing outcome.
@ -333,13 +399,13 @@ namespace toml
TOML_API
parse_result parse(std::string_view doc, std::string&& source_path) TOML_MAY_THROW;
#ifdef __cpp_lib_char8_t
#if TOML_WINDOWS_COMPAT
/// \brief Parses a TOML document from a char8_t string view.
///
/// \brief Parses a TOML document from a string view.
///
/// \detail \cpp
/// auto tbl = toml::parse(u8"a = 3"sv);
/// std::cout << tbl["a"] << std::endl;
/// auto tbl = toml::parse("a = 3"sv, L"foo.toml");
/// std::cout << tbl["a"] << "\n";
///
/// \ecpp
///
@ -355,16 +421,20 @@ namespace toml
/// \returns <strong><em>With exceptions:</em></strong> A toml::table. <br>
/// <strong><em>Without exceptions:</em></strong> A toml::parse_result detailing the parsing outcome.
///
/// \attention This overload is not available if your compiler does not support char8_t-based strings.
/// \attention This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
[[nodiscard]]
TOML_API
parse_result parse(std::u8string_view doc, std::string_view source_path = {}) TOML_MAY_THROW;
parse_result parse(std::string_view doc, std::wstring_view source_path) TOML_MAY_THROW;
#endif // TOML_WINDOWS_COMPAT
#ifdef __cpp_lib_char8_t
/// \brief Parses a TOML document from a char8_t string view.
///
///
/// \detail \cpp
/// auto tbl = toml::parse(u8"a = 3"sv, "foo.toml");
/// std::cout << tbl["a"] << std::endl;
/// auto tbl = toml::parse(u8"a = 3"sv);
/// std::cout << tbl["a"] << "\n";
///
/// \ecpp
///
@ -374,14 +444,66 @@ namespace toml
///
/// \param doc The TOML document to parse. Must be valid UTF-8.
/// \param source_path The path used to initialize each node's `source().path`.
/// If you don't have a path (or you have no intention of using paths in diagnostics)
/// then this parameter can safely be left blank.
///
/// \returns <strong><em>With exceptions:</em></strong> A toml::table. <br>
/// <strong><em>Without exceptions:</em></strong> A toml::parse_result detailing the parsing outcome.
[[nodiscard]]
TOML_API
parse_result parse(std::u8string_view doc, std::string_view source_path = {}) TOML_MAY_THROW;
/// \brief Parses a TOML document from a char8_t string view.
///
/// \detail \cpp
/// auto tbl = toml::parse(u8"a = 3"sv, "foo.toml");
/// std::cout << tbl["a"] << "\n";
///
/// \ecpp
///
/// \out
/// 3
/// \eout
///
/// \param doc The TOML document to parse. Must be valid UTF-8.
/// \param source_path The path used to initialize each node's `source().path`.
/// If you don't have a path (or you have no intention of using paths in diagnostics)
/// then this parameter can safely be left blank.
///
/// \returns <strong><em>With exceptions:</em></strong> A toml::table. <br>
/// <strong><em>Without exceptions:</em></strong> A toml::parse_result detailing the parsing outcome.
[[nodiscard]]
TOML_API
parse_result parse(std::u8string_view doc, std::string&& source_path) TOML_MAY_THROW;
#if TOML_WINDOWS_COMPAT
/// \brief Parses a TOML document from a char8_t string view.
///
/// \detail \cpp
/// auto tbl = toml::parse(u8"a = 3"sv, L"foo.toml");
/// std::cout << tbl["a"] << "\n";
///
/// \ecpp
///
/// \out
/// 3
/// \eout
///
/// \param doc The TOML document to parse. Must be valid UTF-8.
/// \param source_path The path used to initialize each node's `source().path`.
/// If you don't have a path (or you have no intention of using paths in diagnostics)
/// then this parameter can safely be left blank.
///
/// \returns <strong><em>With exceptions:</em></strong> A toml::table. <br>
/// <strong><em>Without exceptions:</em></strong> A toml::parse_result detailing the parsing outcome.
///
/// \attention This overload is not available if your compiler does not support char8_t-based strings.
/// \attention This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
[[nodiscard]]
TOML_API
parse_result parse(std::u8string_view doc, std::string&& source_path) TOML_MAY_THROW;
parse_result parse(std::u8string_view doc, std::wstring_view source_path) TOML_MAY_THROW;
#endif // TOML_WINDOWS_COMPAT
#endif // __cpp_lib_char8_t
@ -392,7 +514,7 @@ namespace toml
/// ss << "a = 3"sv;
///
/// auto tbl = toml::parse(ss);
/// std::cout << tbl["a"] << std::endl;
/// std::cout << tbl["a"] << "\n";
///
/// \ecpp
///
@ -410,8 +532,7 @@ namespace toml
/// <strong><em>Without exceptions:</em></strong> A toml::parse_result detailing the parsing outcome.
template <typename Char>
[[nodiscard]]
TOML_EXTERNAL_LINKAGE
parse_result parse(std::basic_istream<Char>& doc, std::string_view source_path = {}) TOML_MAY_THROW
inline parse_result parse(std::basic_istream<Char>& doc, std::string_view source_path = {}) TOML_MAY_THROW
{
static_assert(
sizeof(Char) == 1,
@ -428,7 +549,7 @@ namespace toml
/// ss << "a = 3"sv;
///
/// auto tbl = toml::parse(ss, "foo.toml");
/// std::cout << tbl["a"] << std::endl;
/// std::cout << tbl["a"] << "\n";
///
/// \ecpp
///
@ -439,13 +560,14 @@ namespace toml
/// \tparam Char The stream's underlying character type. Must be 1 byte in size.
/// \param doc The TOML document to parse. Must be valid UTF-8.
/// \param source_path The path used to initialize each node's `source().path`.
/// If you don't have a path (or you have no intention of using paths in diagnostics)
/// then this parameter can safely be left blank.
///
/// \returns <strong><em>With exceptions:</em></strong> A toml::table. <br>
/// <strong><em>Without exceptions:</em></strong> A toml::parse_result detailing the parsing outcome.
template <typename Char>
[[nodiscard]]
TOML_EXTERNAL_LINKAGE
parse_result parse(std::basic_istream<Char>& doc, std::string&& source_path) TOML_MAY_THROW
inline parse_result parse(std::basic_istream<Char>& doc, std::string&& source_path) TOML_MAY_THROW
{
static_assert(
sizeof(Char) == 1,
@ -455,6 +577,41 @@ namespace toml
return impl::do_parse(impl::utf8_reader{ doc, std::move(source_path) });
}
#if TOML_WINDOWS_COMPAT
/// \brief Parses a TOML document from a stream.
///
/// \detail \cpp
/// std::stringstream ss;
/// ss << "a = 3"sv;
///
/// auto tbl = toml::parse(ss);
/// std::cout << tbl["a"] << "\n";
///
/// \ecpp
///
/// \out
/// 3
/// \eout
///
/// \tparam Char The stream's underlying character type. Must be 1 byte in size.
/// \param doc The TOML document to parse. Must be valid UTF-8.
/// \param source_path The path used to initialize each node's `source().path`.
/// If you don't have a path (or you have no intention of using paths in diagnostics)
/// then this parameter can safely be left blank.
///
/// \returns <strong><em>With exceptions:</em></strong> A toml::table. <br>
/// <strong><em>Without exceptions:</em></strong> A toml::parse_result detailing the parsing outcome.
///
/// \attention This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
template <typename Char>
[[nodiscard]]
inline parse_result parse(std::basic_istream<Char>& doc, std::wstring_view source_path) TOML_MAY_THROW
{
return parse(doc, impl::narrow(source_path));
}
#endif // TOML_WINDOWS_COMPAT
// Q: "why are the parse_file functions templated??"
// A: I don't want to force users to drag in <fstream> if they're not going to do
@ -474,7 +631,7 @@ namespace toml
/// }
/// \ecpp
///
/// \tparam Char The path's character type. Must be 1 byte in size.
/// \tparam Char The path's character type.
/// \param file_path The TOML document to parse. Must be valid UTF-8.
///
/// \returns <strong><em>With exceptions:</em></strong> A toml::table. <br>
@ -483,29 +640,35 @@ namespace toml
/// \attention You must `#include <fstream>` to use this function (toml++ does not transitively include it for you).
template <typename Char, typename StreamChar = char>
[[nodiscard]]
TOML_EXTERNAL_LINKAGE
parse_result parse_file(std::basic_string_view<Char> file_path) TOML_MAY_THROW
inline parse_result parse_file(std::basic_string_view<Char> file_path) TOML_MAY_THROW
{
static_assert(
sizeof(Char) == 1,
"The path's character type must be 1 byte in size."
!std::is_same_v<Char, wchar_t> || TOML_WINDOWS_COMPAT,
"Wide-character file paths are only supported on Windows with TOML_WINDOWS_COMPAT enabled."
);
static_assert(
sizeof(StreamChar) == 1,
"The stream's character type must be 1 byte in size."
);
#if TOML_EXCEPTIONS
#define TOML_PARSE_FILE_ERROR(msg, pos) \
throw parse_error{ msg, pos, std::make_shared<const std::string>(std::move(file_path_str)) }
#if TOML_WINDOWS_COMPAT
static_assert(
sizeof(Char) == 1 || std::is_same_v<Char, wchar_t>,
"The file path's underlying character type must be wchar_t or be 1 byte in size."
);
#else
#define TOML_PARSE_FILE_ERROR(msg, pos) \
return parse_result{ \
parse_error{ msg, pos, std::make_shared<const std::string>(std::move(file_path_str)) } \
}
static_assert(
sizeof(Char) == 1,
"The file path's underlying character type must be 1 byte in size."
);
#endif
static_assert(
std::is_same_v<StreamChar, char>,
"StreamChar must be 'char' (it is as an instantiation-delaying hack and is not user-configurable)."
);
auto file_path_str = std::string(reinterpret_cast<const char*>(file_path.data()), file_path.length());
std::string file_path_str;
#if TOML_WINDOWS_COMPAT
if constexpr (std::is_same_v<Char, wchar_t>)
file_path_str = impl::narrow(file_path);
else
#endif
file_path_str = std::string_view{ reinterpret_cast<const char*>(file_path.data()), file_path.length() };
// open file with a custom-sized stack buffer
using ifstream = std::basic_ifstream<StreamChar>;
@ -514,13 +677,13 @@ namespace toml
file.rdbuf()->pubsetbuf(file_buffer, sizeof(file_buffer));
file.open(file_path_str, ifstream::in | ifstream::binary | ifstream::ate);
if (!file.is_open())
TOML_PARSE_FILE_ERROR("File could not be opened for reading", source_position{});
TOML_THROW_PARSE_ERROR("File could not be opened for reading", file_path_str);
// get size
const auto file_size = file.tellg();
if (file_size == -1)
TOML_PARSE_FILE_ERROR("Could not determine file size", source_position{});
file.seekg(0, std::ios::beg);
TOML_THROW_PARSE_ERROR("Could not determine file size", file_path_str);
file.seekg(0, ifstream::beg);
// read the whole file into memory first if the file isn't too large
constexpr auto large_file_threshold = 1024 * 1024 * static_cast<int>(sizeof(void*)) * 4; // 32 megabytes on 64-bit
@ -535,17 +698,18 @@ namespace toml
// otherwise parse it using the streams
else
return parse(file, std::move(file_path_str));
#undef TOML_PARSE_FILE_ERROR
}
#if !TOML_ALL_INLINE
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
extern template TOML_API parse_result parse(std::istream&, std::string_view) TOML_MAY_THROW;
extern template TOML_API parse_result parse(std::istream&, std::string&&) TOML_MAY_THROW;
extern template TOML_API parse_result parse_file(std::string_view) TOML_MAY_THROW;
#ifdef __cpp_lib_char8_t
extern template TOML_API parse_result parse_file(std::u8string_view) TOML_MAY_THROW;
#endif
#if TOML_WINDOWS_COMPAT
extern template TOML_API parse_result parse_file(std::wstring_view) TOML_MAY_THROW;
#endif
#endif
template <typename Char>
@ -562,41 +726,15 @@ namespace toml
return parse_file(std::basic_string_view<Char>{ file_path });
}
TOML_ABI_NAMESPACE_END // TOML_EXCEPTIONS
/// \brief Convenience literal operators for working with toml++.
///
/// \detail This namespace exists so you can safely hoist the UDL operators into another scope
/// without dragging in everything in the toml namespace: \cpp
///
/// #include <toml++/toml.h>
/// using namespace toml::literals;
///
/// int main()
/// {
/// auto tbl = "vals = [1, 2, 3]"_toml;
///
/// // ... do stuff with the table generated by the "_toml" UDL ...
///
/// return 0;
/// }
/// \ecpp
///
inline namespace literals
{
#if TOML_EXCEPTIONS
TOML_ABI_NAMESPACE_START(lit_ex)
#else
TOML_ABI_NAMESPACE_START(lit_noex)
#endif
/// \brief Parses TOML data from a string.
/// \brief Parses TOML data from a string literal.
///
/// \detail \cpp
/// using namespace toml::literals;
///
/// auto tbl = "a = 3"_toml;
/// std::cout << tbl["a"] << std::endl;
/// std::cout << tbl["a"] << "\n";
///
/// \ecpp
///
@ -604,7 +742,7 @@ namespace toml
/// 3
/// \eout
///
/// \param str The string data.
/// \param str The string data. Must be valid UTF-8.
/// \param len The string length.
///
/// \returns <strong><em>With exceptions:</em></strong> A toml::table. <br>
@ -615,13 +753,13 @@ namespace toml
#ifdef __cpp_lib_char8_t
/// \brief Parses TOML data from a string.
/// \brief Parses TOML data from a UTF-8 string literal.
///
/// \detail \cpp
/// using namespace toml::literals;
///
/// auto tbl = u8"a = 3"_toml;
/// std::cout << tbl["a"] << std::endl;
/// std::cout << tbl["a"] << "\n";
///
/// \ecpp
///
@ -629,21 +767,21 @@ namespace toml
/// 3
/// \eout
///
/// \param str The string data.
/// \param str The string data. Must be valid UTF-8.
/// \param len The string length.
///
/// \returns <strong><em>With exceptions:</em></strong> A toml::table. <br>
/// <strong><em>Without exceptions:</em></strong> A toml::parse_result detailing the parsing outcome.
///
/// \attention This overload is not available if your compiler does not support char8_t-based strings.
[[nodiscard]]
TOML_API
parse_result operator"" _toml(const char8_t* str, size_t len) TOML_MAY_THROW;
#endif // __cpp_lib_char8_t
TOML_ABI_NAMESPACE_END // TOML_EXCEPTIONS
}
}
TOML_POP_WARNINGS // TOML_DISABLE_PADDING_WARNINGS
TOML_ABI_NAMESPACE_END // TOML_EXCEPTIONS
}
TOML_NAMESPACE_END
#undef TOML_THROW_PARSE_ERROR

File diff suppressed because it is too large Load Diff

View File

@ -3,76 +3,73 @@
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT
#pragma once
// clang-format off
////////// CONFIGURATION
#ifdef TOML_CONFIG_HEADER
#include TOML_CONFIG_HEADER
#endif
#if !defined(TOML_ALL_INLINE) || (defined(TOML_ALL_INLINE) && TOML_ALL_INLINE) || defined(__INTELLISENSE__)
#undef TOML_ALL_INLINE
#define TOML_ALL_INLINE 1
#endif
#if defined(TOML_IMPLEMENTATION) || TOML_ALL_INLINE
#undef TOML_IMPLEMENTATION
#define TOML_IMPLEMENTATION 1
#else
#define TOML_IMPLEMENTATION 0
#endif
#ifndef TOML_API
#define TOML_API
#endif
#ifndef TOML_CHAR_8_STRINGS
#define TOML_CHAR_8_STRINGS 0
#endif
#ifndef TOML_UNRELEASED_FEATURES
#define TOML_UNRELEASED_FEATURES 0
#endif
#ifndef TOML_LARGE_FILES
#define TOML_LARGE_FILES 0
#endif
#ifndef TOML_UNDEF_MACROS
#define TOML_UNDEF_MACROS 1
#endif
#ifndef TOML_PARSER
#define TOML_PARSER 1
#endif
////////// COMPILER & ENVIRONMENT
#pragma once
#ifndef __cplusplus
#error toml++ is a C++ library.
#endif
#ifndef TOML_DOXYGEN
#define TOML_DOXYGEN 0
//#====================================================================================================================
//# COMPILER DETECTION
//#====================================================================================================================
#ifdef __INTELLISENSE__
#define TOML_INTELLISENSE 1
#else
#define TOML_INTELLISENSE 0
#endif
#ifdef __clang__
#define TOML_CLANG __clang_major__
#else
#define TOML_CLANG 0
#endif
#ifdef __INTEL_COMPILER
#define TOML_ICC __INTEL_COMPILER
#ifdef __ICL
#define TOML_ICC_CL TOML_ICC
#else
#define TOML_ICC_CL 0
#endif
#else
#define TOML_ICC 0
#define TOML_ICC_CL 0
#endif
#if defined(_MSC_VER) && !TOML_CLANG && !TOML_ICC
#define TOML_MSVC _MSC_VER
#else
#define TOML_MSVC 0
#endif
#if defined(__GNUC__) && !TOML_CLANG && !TOML_ICC
#define TOML_GCC __GNUC__
#else
#define TOML_GCC 0
#endif
#define TOML_PUSH_WARNINGS _Pragma("clang diagnostic push")
#define TOML_DISABLE_SWITCH_WARNINGS _Pragma("clang diagnostic ignored \"-Wswitch\"")
#define TOML_DISABLE_INIT_WARNINGS _Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"")
#define TOML_DISABLE_VTABLE_WARNINGS _Pragma("clang diagnostic ignored \"-Weverything\"") \
_Pragma("clang diagnostic ignored \"-Wweak-vtables\"")
#define TOML_DISABLE_PADDING_WARNINGS _Pragma("clang diagnostic ignored \"-Wpadded\"")
#define TOML_DISABLE_FLOAT_WARNINGS _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \
_Pragma("clang diagnostic ignored \"-Wdouble-promotion\"")
#define TOML_DISABLE_SHADOW_WARNINGS _Pragma("clang diagnostic ignored \"-Wshadow\"")
#define TOML_DISABLE_ALL_WARNINGS _Pragma("clang diagnostic ignored \"-Weverything\"")
#define TOML_POP_WARNINGS _Pragma("clang diagnostic pop")
//#====================================================================================================================
//# CLANG
//#====================================================================================================================
#define TOML_ASSUME(cond) __builtin_assume(cond)
#define TOML_UNREACHABLE __builtin_unreachable()
#define TOML_ATTR(...) __attribute__((__VA_ARGS__))
#if TOML_CLANG
#define TOML_PUSH_WARNINGS _Pragma("clang diagnostic push")
#define TOML_DISABLE_SWITCH_WARNINGS _Pragma("clang diagnostic ignored \"-Wswitch\"")
#define TOML_DISABLE_INIT_WARNINGS _Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"")
#define TOML_DISABLE_ARITHMETIC_WARNINGS _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \
_Pragma("clang diagnostic ignored \"-Wdouble-promotion\"") \
_Pragma("clang diagnostic ignored \"-Wchar-subscripts\"") \
_Pragma("clang diagnostic ignored \"-Wshift-sign-overflow\"")
#define TOML_DISABLE_SHADOW_WARNINGS _Pragma("clang diagnostic ignored \"-Wshadow\"")
#define TOML_DISABLE_SPAM_WARNINGS _Pragma("clang diagnostic ignored \"-Wweak-vtables\"") \
_Pragma("clang diagnostic ignored \"-Wweak-template-vtables\"") \
_Pragma("clang diagnostic ignored \"-Wpadded\"")
#define TOML_POP_WARNINGS _Pragma("clang diagnostic pop")
#define TOML_DISABLE_WARNINGS TOML_PUSH_WARNINGS \
_Pragma("clang diagnostic ignored \"-Weverything\"")
#define TOML_ENABLE_WARNINGS TOML_POP_WARNINGS
#define TOML_ASSUME(cond) __builtin_assume(cond)
#define TOML_UNREACHABLE __builtin_unreachable()
#define TOML_ATTR(...) __attribute__((__VA_ARGS__))
#if defined(_MSC_VER) // msvc compat mode
#ifdef __has_declspec_attribute
#if __has_declspec_attribute(novtable)
@ -100,11 +97,6 @@
#define TOML_TRIVIAL_ABI __attribute__((__trivial_abi__))
#endif
#endif
#ifdef __EXCEPTIONS
#define TOML_COMPILER_EXCEPTIONS 1
#else
#define TOML_COMPILER_EXCEPTIONS 0
#endif
#define TOML_LIKELY(...) (__builtin_expect(!!(__VA_ARGS__), 1) )
#define TOML_UNLIKELY(...) (__builtin_expect(!!(__VA_ARGS__), 0) )
@ -113,74 +105,96 @@
#define TOML_FLOAT_CHARCONV 0
#endif
#elif defined(_MSC_VER) || (defined(__INTEL_COMPILER) && defined(__ICL))
#define TOML_SIMPLE_STATIC_ASSERT_MESSAGES 1
#endif // clang
//#====================================================================================================================
//# MSVC
//#====================================================================================================================
#if TOML_MSVC || TOML_ICC_CL
#define TOML_CPP_VERSION _MSVC_LANG
#define TOML_PUSH_WARNINGS __pragma(warning(push))
#if TOML_MSVC // !intel-cl
#define TOML_PUSH_WARNINGS __pragma(warning(push))
#define TOML_DISABLE_SWITCH_WARNINGS __pragma(warning(disable: 4063))
#define TOML_POP_WARNINGS __pragma(warning(pop))
#define TOML_DISABLE_WARNINGS __pragma(warning(push, 0))
#define TOML_ENABLE_WARNINGS TOML_POP_WARNINGS
#endif
#ifndef TOML_ALWAYS_INLINE
#define TOML_ALWAYS_INLINE __forceinline
#endif
#define TOML_NEVER_INLINE __declspec(noinline)
#define TOML_ASSUME(cond) __assume(cond)
#define TOML_UNREACHABLE __assume(0)
#define TOML_INTERFACE __declspec(novtable)
#define TOML_EMPTY_BASES __declspec(empty_bases)
#endif // msvc
//#====================================================================================================================
//# ICC
//#====================================================================================================================
#if TOML_ICC
#define TOML_PUSH_WARNINGS __pragma(warning(push))
#define TOML_DISABLE_SWITCH_WARNINGS __pragma(warning(disable: 4063))
#define TOML_DISABLE_ALL_WARNINGS __pragma(warning(pop)) \
__pragma(warning(push, 0))
#define TOML_DISABLE_SPAM_WARNINGS __pragma(warning(disable: 82)) /* storage class is not first */ \
__pragma(warning(disable: 111)) /* statement unreachable (false-positive) */ \
__pragma(warning(disable: 1011)) /* missing return (false-positive) */ \
__pragma(warning(disable: 2261)) /* assume expr side-effects discarded */
#define TOML_POP_WARNINGS __pragma(warning(pop))
#define TOML_DISABLE_WARNINGS __pragma(warning(push, 0))
#define TOML_ENABLE_WARNINGS TOML_POP_WARNINGS
#define TOML_CPP_VERSION _MSVC_LANG
#endif // icc
//#====================================================================================================================
//# GCC
//#====================================================================================================================
#if TOML_GCC
#define TOML_PUSH_WARNINGS _Pragma("GCC diagnostic push")
#define TOML_DISABLE_SWITCH_WARNINGS _Pragma("GCC diagnostic ignored \"-Wswitch\"") \
_Pragma("GCC diagnostic ignored \"-Wswitch-enum\"") \
_Pragma("GCC diagnostic ignored \"-Wswitch-default\"")
#define TOML_DISABLE_INIT_WARNINGS _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") \
_Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") \
_Pragma("GCC diagnostic ignored \"-Wuninitialized\"")
#define TOML_DISABLE_ARITHMETIC_WARNINGS _Pragma("GCC diagnostic ignored \"-Wfloat-equal\"") \
_Pragma("GCC diagnostic ignored \"-Wsign-conversion\"") \
_Pragma("GCC diagnostic ignored \"-Wchar-subscripts\"")
#define TOML_DISABLE_SHADOW_WARNINGS _Pragma("GCC diagnostic ignored \"-Wshadow\"")
#define TOML_DISABLE_SPAM_WARNINGS _Pragma("GCC diagnostic ignored \"-Wpadded\"") \
_Pragma("GCC diagnostic ignored \"-Wcast-align\"") \
_Pragma("GCC diagnostic ignored \"-Wcomment\"") \
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"") \
_Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=const\"") \
_Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=pure\"")
#define TOML_POP_WARNINGS _Pragma("GCC diagnostic pop")
#define TOML_DISABLE_WARNINGS TOML_PUSH_WARNINGS \
_Pragma("GCC diagnostic ignored \"-Wall\"") \
_Pragma("GCC diagnostic ignored \"-Wextra\"") \
_Pragma("GCC diagnostic ignored \"-Wpedantic\"") \
TOML_DISABLE_SWITCH_WARNINGS \
TOML_DISABLE_INIT_WARNINGS \
TOML_DISABLE_ARITHMETIC_WARNINGS \
TOML_DISABLE_SHADOW_WARNINGS \
TOML_DISABLE_SPAM_WARNINGS
#define TOML_ENABLE_WARNINGS TOML_POP_WARNINGS
#define TOML_ATTR(...) __attribute__((__VA_ARGS__))
#ifndef TOML_ALWAYS_INLINE
#define TOML_ALWAYS_INLINE __forceinline
#define TOML_ALWAYS_INLINE __attribute__((__always_inline__)) inline
#endif
#define TOML_NEVER_INLINE __declspec(noinline)
#define TOML_ASSUME(cond) __assume(cond)
#define TOML_UNREACHABLE __assume(0)
#define TOML_INTERFACE __declspec(novtable)
#define TOML_EMPTY_BASES __declspec(empty_bases)
#if !defined(TOML_RELOPS_REORDERING) && defined(__cpp_impl_three_way_comparison)
#define TOML_RELOPS_REORDERING 1
#endif
#ifdef _CPPUNWIND
#define TOML_COMPILER_EXCEPTIONS 1
#else
#define TOML_COMPILER_EXCEPTIONS 0
#endif
#elif defined(__GNUC__)
#define TOML_PUSH_WARNINGS _Pragma("GCC diagnostic push")
#define TOML_DISABLE_SWITCH_WARNINGS _Pragma("GCC diagnostic ignored \"-Wswitch\"") \
_Pragma("GCC diagnostic ignored \"-Wswitch-enum\"") \
_Pragma("GCC diagnostic ignored \"-Wswitch-default\"")
#define TOML_DISABLE_INIT_WARNINGS _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") \
_Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") \
_Pragma("GCC diagnostic ignored \"-Wuninitialized\"")
#define TOML_DISABLE_PADDING_WARNINGS _Pragma("GCC diagnostic ignored \"-Wpadded\"")
#define TOML_DISABLE_FLOAT_WARNINGS _Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
#define TOML_DISABLE_SHADOW_WARNINGS _Pragma("GCC diagnostic ignored \"-Wshadow\"")
#define TOML_DISABLE_SUGGEST_WARNINGS _Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=const\"") \
_Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=pure\"")
#define TOML_DISABLE_ALL_WARNINGS _Pragma("GCC diagnostic ignored \"-Wall\"") \
_Pragma("GCC diagnostic ignored \"-Wextra\"") \
_Pragma("GCC diagnostic ignored \"-Wchar-subscripts\"") \
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"") \
TOML_DISABLE_SUGGEST_WARNINGS \
TOML_DISABLE_SWITCH_WARNINGS \
TOML_DISABLE_INIT_WARNINGS \
TOML_DISABLE_PADDING_WARNINGS \
TOML_DISABLE_FLOAT_WARNINGS \
TOML_DISABLE_SHADOW_WARNINGS
#define TOML_POP_WARNINGS _Pragma("GCC diagnostic pop")
#define TOML_ATTR(...) __attribute__((__VA_ARGS__))
#ifndef TOML_ALWAYS_INLINE
#define TOML_ALWAYS_INLINE __attribute__((__always_inline__)) inline
#endif
#define TOML_NEVER_INLINE __attribute__((__noinline__))
#define TOML_UNREACHABLE __builtin_unreachable()
#if !defined(TOML_RELOPS_REORDERING) && defined(__cpp_impl_three_way_comparison)
#define TOML_RELOPS_REORDERING 1
#endif
#ifdef __cpp_exceptions
#define TOML_COMPILER_EXCEPTIONS 1
#else
#define TOML_COMPILER_EXCEPTIONS 0
#endif
#define TOML_LIKELY(...) (__builtin_expect(!!(__VA_ARGS__), 1) )
#define TOML_UNLIKELY(...) (__builtin_expect(!!(__VA_ARGS__), 0) )
#define TOML_NEVER_INLINE __attribute__((__noinline__))
#define TOML_UNREACHABLE __builtin_unreachable()
#define TOML_LIKELY(...) (__builtin_expect(!!(__VA_ARGS__), 1) )
#define TOML_UNLIKELY(...) (__builtin_expect(!!(__VA_ARGS__), 0) )
// floating-point from_chars and to_chars are not implemented in any version of gcc as of 1/1/2020
#ifndef TOML_FLOAT_CHARCONV
@ -189,10 +203,86 @@
#endif
//#====================================================================================================================
//# USER CONFIGURATION
//#====================================================================================================================
#ifdef TOML_CONFIG_HEADER
#include TOML_CONFIG_HEADER
#endif
#ifdef DOXYGEN
#define TOML_HEADER_ONLY 0
#define TOML_WINDOWS_COMPAT 1
#endif
#if defined(TOML_ALL_INLINE) && !defined(TOML_HEADER_ONLY)
#define TOML_HEADER_ONLY TOML_ALL_INLINE
#endif
#if !defined(TOML_HEADER_ONLY) || (defined(TOML_HEADER_ONLY) && TOML_HEADER_ONLY) || TOML_INTELLISENSE
#undef TOML_HEADER_ONLY
#define TOML_HEADER_ONLY 1
#endif
#if defined(TOML_IMPLEMENTATION) || TOML_HEADER_ONLY
#undef TOML_IMPLEMENTATION
#define TOML_IMPLEMENTATION 1
#else
#define TOML_IMPLEMENTATION 0
#endif
#ifndef TOML_API
#define TOML_API
#endif
#ifndef TOML_UNRELEASED_FEATURES
#define TOML_UNRELEASED_FEATURES 0
#endif
#ifndef TOML_LARGE_FILES
#define TOML_LARGE_FILES 0
#endif
#ifndef TOML_UNDEF_MACROS
#define TOML_UNDEF_MACROS 1
#endif
#ifndef TOML_PARSER
#define TOML_PARSER 1
#endif
#ifndef DOXYGEN
#if defined(_WIN32) && !defined(TOML_WINDOWS_COMPAT)
#define TOML_WINDOWS_COMPAT 1
#endif
#if !defined(_WIN32) || !defined(TOML_WINDOWS_COMPAT)
#undef TOML_WINDOWS_COMPAT
#define TOML_WINDOWS_COMPAT 0
#endif
#endif
#ifdef TOML_OPTIONAL_TYPE
#define TOML_HAS_CUSTOM_OPTIONAL_TYPE 1
#else
#define TOML_HAS_CUSTOM_OPTIONAL_TYPE 0
#endif
#ifdef TOML_CHAR_8_STRINGS
#if TOML_CHAR_8_STRINGS
#error TOML_CHAR_8_STRINGS was removed in toml++ 2.0.0; \
all value setters and getters can now work with char8_t strings implicitly so changing the underlying string type \
is no longer necessary.
#endif
#endif
//#====================================================================================================================
//# ATTRIBUTES, UTILITY MACROS ETC
//#====================================================================================================================
#ifndef TOML_CPP_VERSION
#define TOML_CPP_VERSION __cplusplus
#endif
#if TOML_CPP_VERSION < 201103L
#error toml++ requires C++17 or higher. For a TOML library supporting pre-C++11 see https://github.com/ToruNiina/Boost.toml
#elif TOML_CPP_VERSION < 201703L
@ -206,12 +296,22 @@
#elif TOML_CPP_VERSION >= 201703L
#define TOML_CPP 17
#endif
#undef TOML_CPP_VERSION
#ifndef TOML_COMPILER_EXCEPTIONS
#ifdef __has_include
#define TOML_HAS_INCLUDE(header) __has_include(header)
#else
#define TOML_HAS_INCLUDE(header) 0
#endif
#if defined(__EXCEPTIONS) || defined(_CPPUNWIND) || defined(__cpp_exceptions)
#define TOML_COMPILER_EXCEPTIONS 1
#else
#define TOML_COMPILER_EXCEPTIONS 0
#endif
#if TOML_COMPILER_EXCEPTIONS
#ifndef TOML_EXCEPTIONS
#if !defined(TOML_EXCEPTIONS) || (defined(TOML_EXCEPTIONS) && TOML_EXCEPTIONS)
#undef TOML_EXCEPTIONS
#define TOML_EXCEPTIONS 1
#endif
#else
@ -234,7 +334,7 @@
#ifndef TOML_FLOAT_CHARCONV
#define TOML_FLOAT_CHARCONV 1
#endif
#if (TOML_INT_CHARCONV || TOML_FLOAT_CHARCONV) && !__has_include(<charconv>)
#if (TOML_INT_CHARCONV || TOML_FLOAT_CHARCONV) && !TOML_HAS_INCLUDE(<charconv>)
#undef TOML_INT_CHARCONV
#undef TOML_FLOAT_CHARCONV
#define TOML_INT_CHARCONV 0
@ -250,27 +350,24 @@
#ifndef TOML_DISABLE_INIT_WARNINGS
#define TOML_DISABLE_INIT_WARNINGS
#endif
#ifndef TOML_DISABLE_VTABLE_WARNINGS
#define TOML_DISABLE_VTABLE_WARNINGS
#ifndef TOML_DISABLE_SPAM_WARNINGS
#define TOML_DISABLE_SPAM_WARNINGS
#endif
#ifndef TOML_DISABLE_PADDING_WARNINGS
#define TOML_DISABLE_PADDING_WARNINGS
#endif
#ifndef TOML_DISABLE_FLOAT_WARNINGS
#define TOML_DISABLE_FLOAT_WARNINGS
#ifndef TOML_DISABLE_ARITHMETIC_WARNINGS
#define TOML_DISABLE_ARITHMETIC_WARNINGS
#endif
#ifndef TOML_DISABLE_SHADOW_WARNINGS
#define TOML_DISABLE_SHADOW_WARNINGS
#endif
#ifndef TOML_DISABLE_SUGGEST_WARNINGS
#define TOML_DISABLE_SUGGEST_WARNINGS
#endif
#ifndef TOML_DISABLE_ALL_WARNINGS
#define TOML_DISABLE_ALL_WARNINGS
#endif
#ifndef TOML_POP_WARNINGS
#define TOML_POP_WARNINGS
#endif
#ifndef TOML_DISABLE_WARNINGS
#define TOML_DISABLE_WARNINGS
#endif
#ifndef TOML_ENABLE_WARNINGS
#define TOML_ENABLE_WARNINGS
#endif
#ifndef TOML_ATTR
#define TOML_ATTR(...)
@ -284,10 +381,6 @@
#define TOML_EMPTY_BASES
#endif
#ifndef TOML_ALWAYS_INLINE
#define TOML_ALWAYS_INLINE inline
#endif
#ifndef TOML_NEVER_INLINE
#define TOML_NEVER_INLINE
#endif
@ -308,14 +401,20 @@
#define TOML_CONSTEVAL constexpr
#endif
#if !TOML_DOXYGEN && !defined(__INTELLISENSE__)
#if !defined(TOML_LIKELY) && __has_cpp_attribute(likely)
#ifdef __has_cpp_attribute
#define TOML_HAS_ATTR(...) __has_cpp_attribute(__VA_ARGS__)
#else
#define TOML_HAS_ATTR(...) 0
#endif
#if !defined(DOXYGEN) && !TOML_INTELLISENSE
#if !defined(TOML_LIKELY) && TOML_HAS_ATTR(likely)
#define TOML_LIKELY(...) (__VA_ARGS__) [[likely]]
#endif
#if !defined(TOML_UNLIKELY) && __has_cpp_attribute(unlikely)
#if !defined(TOML_UNLIKELY) && TOML_HAS_ATTR(unlikely)
#define TOML_UNLIKELY(...) (__VA_ARGS__) [[unlikely]]
#endif
#if __has_cpp_attribute(nodiscard) >= 201907L
#if TOML_HAS_ATTR(nodiscard) >= 201907L
#define TOML_NODISCARD_CTOR [[nodiscard]]
#endif
#endif
@ -334,32 +433,90 @@
#define TOML_TRIVIAL_ABI
#endif
#ifndef TOML_RELOPS_REORDERING
#define TOML_RELOPS_REORDERING 0
#endif
#if TOML_RELOPS_REORDERING
#define TOML_ASYMMETRICAL_EQUALITY_OPS(...)
#else
#define TOML_ASYMMETRICAL_EQUALITY_OPS(LHS, RHS, ...) \
__VA_ARGS__ [[nodiscard]] friend bool operator == (RHS rhs, LHS lhs) noexcept { return lhs == rhs; } \
__VA_ARGS__ [[nodiscard]] friend bool operator != (LHS lhs, RHS rhs) noexcept { return !(lhs == rhs); } \
__VA_ARGS__ [[nodiscard]] friend bool operator != (RHS rhs, LHS lhs) noexcept { return !(lhs == rhs); }
#define TOML_ASYMMETRICAL_EQUALITY_OPS(LHS, RHS, ...) \
__VA_ARGS__ [[nodiscard]] friend bool operator == (RHS rhs, LHS lhs) noexcept { return lhs == rhs; } \
__VA_ARGS__ [[nodiscard]] friend bool operator != (LHS lhs, RHS rhs) noexcept { return !(lhs == rhs); } \
__VA_ARGS__ [[nodiscard]] friend bool operator != (RHS rhs, LHS lhs) noexcept { return !(lhs == rhs); }
#ifndef TOML_SIMPLE_STATIC_ASSERT_MESSAGES
#define TOML_SIMPLE_STATIC_ASSERT_MESSAGES 0
#endif
#if TOML_ALL_INLINE
#define TOML_EXTERNAL_LINKAGE inline
#define TOML_INTERNAL_LINKAGE inline
#define TOML_INTERNAL_NAMESPACE toml::impl
#define TOML_CONCAT_1(x, y) x##y
#define TOML_CONCAT(x, y) TOML_CONCAT_1(x, y)
#define TOML_EVAL_BOOL_1(T, F) T
#define TOML_EVAL_BOOL_0(T, F) F
#if defined(__aarch64__) || defined(__ARM_ARCH_ISA_A64) || defined(_M_ARM64) || defined(__ARM_64BIT_STATE) \
|| defined(__arm__) || defined(_M_ARM) || defined(__ARM_32BIT_STATE)
#define TOML_ARM 1
#else
#define TOML_EXTERNAL_LINKAGE
#define TOML_INTERNAL_LINKAGE static
#define TOML_INTERNAL_NAMESPACE
#define TOML_ARM 0
#endif
#define TOML_MAKE_BITOPS(type) \
[[nodiscard]] \
TOML_ALWAYS_INLINE \
TOML_ATTR(const) \
TOML_ATTR(flatten) \
constexpr type operator & (type lhs, type rhs) noexcept \
{ \
return static_cast<type>(::toml::impl::unwrap_enum(lhs) & ::toml::impl::unwrap_enum(rhs)); \
} \
[[nodiscard]] \
TOML_ALWAYS_INLINE \
TOML_ATTR(const) \
TOML_ATTR(flatten) \
constexpr type operator | (type lhs, type rhs) noexcept \
{ \
return static_cast<type>(::toml::impl::unwrap_enum(lhs) | ::toml::impl::unwrap_enum(rhs)); \
}
#ifndef TOML_LIFETIME_HOOKS
#define TOML_LIFETIME_HOOKS 0
#endif
//#====================================================================================================================
//# EXTENDED INT AND FLOAT TYPES
//#====================================================================================================================
#ifdef __FLT16_MANT_DIG__
#if __FLT_RADIX__ == 2 \
&& __FLT16_MANT_DIG__ == 11 \
&& __FLT16_DIG__ == 3 \
&& __FLT16_MIN_EXP__ == -13 \
&& __FLT16_MIN_10_EXP__ == -4 \
&& __FLT16_MAX_EXP__ == 16 \
&& __FLT16_MAX_10_EXP__ == 4
#if TOML_ARM && (TOML_GCC || TOML_CLANG)
#define TOML_FP16 __fp16
#endif
#if TOML_ARM && TOML_CLANG // not present in g++
#define TOML_FLOAT16 _Float16
#endif
#endif
#endif
#if defined(__SIZEOF_FLOAT128__) \
&& defined(__FLT128_MANT_DIG__) \
&& defined(__LDBL_MANT_DIG__) \
&& __FLT128_MANT_DIG__ > __LDBL_MANT_DIG__
#define TOML_FLOAT128 __float128
#endif
#ifdef __SIZEOF_INT128__
#define TOML_INT128 __int128_t
#define TOML_UINT128 __uint128_t
#endif
//#====================================================================================================================
//# VERSIONS AND NAMESPACES
//#====================================================================================================================
#include "toml_version.h"
//# {{
#define TOML_LIB_SINGLE_HEADER 0
//# }}
#define TOML_MAKE_VERSION(maj, min, rev) \
((maj) * 1000 + (min) * 25 + (rev))
@ -381,37 +538,69 @@
#define TOML_LANG_UNRELEASED \
TOML_LANG_HIGHER_THAN(TOML_LANG_MAJOR, TOML_LANG_MINOR, TOML_LANG_PATCH)
#if TOML_DOXYGEN || defined(__INTELLISENSE__)
#define TOML_ABI_NAMESPACES 0
#define TOML_ABI_NAMESPACE_START(name)
#define TOML_ABI_NAMESPACE_END
#else
#define TOML_ABI_NAMESPACES 1
#define TOML_ABI_NAMESPACE_START(name) inline namespace abi_##name {
#ifndef TOML_ABI_NAMESPACES
#ifdef DOXYGEN
#define TOML_ABI_NAMESPACES 0
#else
#define TOML_ABI_NAMESPACES 1
#endif
#endif
#if TOML_ABI_NAMESPACES
#define TOML_NAMESPACE_START namespace toml { inline namespace TOML_CONCAT(v, TOML_LIB_MAJOR)
#define TOML_NAMESPACE_END }
#define TOML_NAMESPACE ::toml::TOML_CONCAT(v, TOML_LIB_MAJOR)
#define TOML_ABI_NAMESPACE_START(name) inline namespace name {
#define TOML_ABI_NAMESPACE_BOOL(cond, T, F) TOML_ABI_NAMESPACE_START(TOML_CONCAT(TOML_EVAL_BOOL_, cond)(T, F))
#define TOML_ABI_NAMESPACE_END }
#else
#define TOML_NAMESPACE_START namespace toml
#define TOML_NAMESPACE_END
#define TOML_NAMESPACE toml
#define TOML_ABI_NAMESPACE_START(...)
#define TOML_ABI_NAMESPACE_BOOL(...)
#define TOML_ABI_NAMESPACE_END
#endif
#define TOML_IMPL_NAMESPACE_START TOML_NAMESPACE_START { namespace impl
#define TOML_IMPL_NAMESPACE_END } TOML_NAMESPACE_END
#if TOML_HEADER_ONLY
#define TOML_ANON_NAMESPACE_START TOML_IMPL_NAMESPACE_START
#define TOML_ANON_NAMESPACE_END TOML_IMPL_NAMESPACE_END
#define TOML_ANON_NAMESPACE TOML_NAMESPACE::impl
#define TOML_USING_ANON_NAMESPACE using namespace TOML_ANON_NAMESPACE
#define TOML_EXTERNAL_LINKAGE inline
#define TOML_INTERNAL_LINKAGE inline
#else
#define TOML_ANON_NAMESPACE_START namespace
#define TOML_ANON_NAMESPACE_END
#define TOML_ANON_NAMESPACE
#define TOML_USING_ANON_NAMESPACE (void)0
#define TOML_EXTERNAL_LINKAGE
#define TOML_INTERNAL_LINKAGE static
#endif
TOML_PUSH_WARNINGS
TOML_DISABLE_ALL_WARNINGS
//#====================================================================================================================
//# ASSERT
//#====================================================================================================================
TOML_DISABLE_WARNINGS
#ifndef TOML_ASSERT
#if defined(NDEBUG) || !defined(_DEBUG)
#define TOML_ASSERT(expr) (void)0
#else
#include <cassert>
#ifndef assert
#include <cassert>
#endif
#define TOML_ASSERT(expr) assert(expr)
#endif
#endif
TOML_POP_WARNINGS
TOML_ENABLE_WARNINGS
#if TOML_CHAR_8_STRINGS
#define TOML_STRING_PREFIX_1(S) u8##S
#define TOML_STRING_PREFIX(S) TOML_STRING_PREFIX_1(S)
#else
#define TOML_STRING_PREFIX(S) S
#endif
//#====================================================================================================================
//# DOXYGEN SPAM
//#====================================================================================================================
//# {{
#if TOML_DOXYGEN
#ifdef DOXYGEN
/// \addtogroup configuration Library Configuration
/// \brief Preprocessor macros for configuring library functionality.
@ -421,14 +610,14 @@ TOML_POP_WARNINGS
/// @{
/// \def TOML_ALL_INLINE
/// \def TOML_HEADER_ONLY
/// \brief Sets whether the library is entirely inline.
/// \detail Defaults to `1`.
/// \remark Disabling this means that you must define `TOML_IMPLEMENTATION` in
/// \remark Disabling this means that you must define #TOML_IMPLEMENTATION in
/// <strong><em>exactly one</em></strong> translation unit in your project:
/// \cpp
/// // global_header_that_includes_toml++.h
/// #define TOML_ALL_INLINE 0
/// #define TOML_HEADER_ONLY 0
/// #include <toml.hpp>
///
/// // some_code_file.cpp
@ -450,11 +639,6 @@ TOML_POP_WARNINGS
/// \detail Defaults to the standard C `assert()`.
/// \def TOML_CHAR_8_STRINGS
/// \brief Uses C++20 char8_t-based strings as the toml string data type.
/// \detail Defaults to `0`.
#define TOML_CONFIG_HEADER
/// \def TOML_CONFIG_HEADER
/// \brief An additional header to include before any other toml++ header files.
@ -467,8 +651,8 @@ TOML_POP_WARNINGS
/// \def TOML_IMPLEMENTATION
/// \brief Enables the library's implementation when #TOML_ALL_INLINE is enabled.
/// \detail Not defined by default. Meaningless when #TOML_ALL_INLINE is disabled.
/// \brief Enables the library's implementation when #TOML_HEADER_ONLY is enabled.
/// \detail Not defined by default. Meaningless when #TOML_HEADER_ONLY is disabled.
/// \def TOML_LARGE_FILES
@ -497,7 +681,8 @@ TOML_POP_WARNINGS
/// \def TOML_SMALL_FLOAT_TYPE
/// \brief If your codebase has an additional 'small' float type (e.g. half-precision), this tells toml++ about it.
/// \detail Not defined by default.
/// \attention If you're building for a platform that has a built-in half precision float (e.g. `_Float16`), you don't
/// need to use this configuration option to make toml++ aware of it; the library comes with that built-in.
#define TOML_SMALL_INT_TYPE
/// \def TOML_SMALL_INT_TYPE
@ -512,8 +697,21 @@ TOML_POP_WARNINGS
/// \see [TOML Language Support](https://github.com/marzer/tomlplusplus/blob/master/README.md#toml-language-support)
/// \def TOML_WINDOWS_COMPAT
/// \brief Enables the use of wide strings (wchar_t, std::wstring) in various places throughout the library
/// when building for Windows.
/// \detail Defaults to `1` when building for Windows, `0` otherwise. Has no effect when building for anything other
/// than Windows.
/// \attention This <strong>does not</strong> change the underlying string type used to represent TOML keys and string
/// values; that will still be std::string. This setting simply enables some narrow &lt;=&gt; wide string
/// conversions when necessary at various interface boundaries.
/// <br><br>
/// If you're building for Windows and you have no need for Windows' "Pretends-to-be-unicode" wide strings,
/// you can safely set this to `0`.
/// @}
#endif // TOML_DOXYGEN
#endif // DOXYGEN
//# }}
// clang-format on

View File

@ -5,8 +5,7 @@
#pragma once
#include "toml_date_time.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_ALL_WARNINGS
TOML_DISABLE_WARNINGS
#include <cmath>
#if TOML_INT_CHARCONV || TOML_FLOAT_CHARCONV
#include <charconv>
@ -17,9 +16,12 @@ TOML_DISABLE_ALL_WARNINGS
#if !TOML_INT_CHARCONV
#include <iomanip>
#endif
TOML_POP_WARNINGS
TOML_ENABLE_WARNINGS
namespace toml::impl
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_IMPL_NAMESPACE_START
{
// Q: "why does print_to_stream() exist? why not just use ostream::write(), ostream::put() etc?"
// A: - I'm supporting C++20's char8_t as well; wrapping streams allows switching string modes transparently.
@ -34,8 +36,7 @@ namespace toml::impl
// - Strings in C++. Honestly.
template <typename Char1, typename Char2>
TOML_ALWAYS_INLINE
void print_to_stream(std::basic_string_view<Char1> str, std::basic_ostream<Char2>& stream)
inline void print_to_stream(std::basic_string_view<Char1> str, std::basic_ostream<Char2>& stream)
{
static_assert(sizeof(Char1) == 1);
static_assert(sizeof(Char2) == 1);
@ -43,8 +44,7 @@ namespace toml::impl
}
template <typename Char1, typename Char2>
TOML_ALWAYS_INLINE
void print_to_stream(const std::basic_string<Char1>& str, std::basic_ostream<Char2>& stream)
inline void print_to_stream(const std::basic_string<Char1>& str, std::basic_ostream<Char2>& stream)
{
static_assert(sizeof(Char1) == 1);
static_assert(sizeof(Char2) == 1);
@ -52,8 +52,7 @@ namespace toml::impl
}
template <typename Char>
TOML_ALWAYS_INLINE
void print_to_stream(char character, std::basic_ostream<Char>& stream)
inline void print_to_stream(char character, std::basic_ostream<Char>& stream)
{
static_assert(sizeof(Char) == 1);
stream.put(static_cast<Char>(character));
@ -61,18 +60,16 @@ namespace toml::impl
template <typename Char>
TOML_ATTR(nonnull)
TOML_ALWAYS_INLINE
void print_to_stream(const char* str, size_t len, std::basic_ostream<Char>& stream)
inline void print_to_stream(const char* str, size_t len, std::basic_ostream<Char>& stream)
{
static_assert(sizeof(Char) == 1);
stream.write(reinterpret_cast<const Char*>(str), static_cast<std::streamsize>(len));
}
#if defined(__cpp_lib_char8_t)
#ifdef __cpp_lib_char8_t
template <typename Char>
TOML_ALWAYS_INLINE
void print_to_stream(char8_t character, std::basic_ostream<Char>& stream)
inline void print_to_stream(char8_t character, std::basic_ostream<Char>& stream)
{
static_assert(sizeof(Char) == 1);
stream.put(static_cast<Char>(character));
@ -80,8 +77,7 @@ namespace toml::impl
template <typename Char>
TOML_ATTR(nonnull)
TOML_ALWAYS_INLINE
void print_to_stream(const char8_t* str, size_t len, std::basic_ostream<Char>& stream)
inline void print_to_stream(const char8_t* str, size_t len, std::basic_ostream<Char>& stream)
{
static_assert(sizeof(Char) == 1);
stream.write(reinterpret_cast<const Char*>(str), static_cast<std::streamsize>(len));
@ -102,39 +98,85 @@ namespace toml::impl
template <> inline constexpr size_t charconv_buffer_length<uint8_t> = 3; // strlen("255")
template <typename T, typename Char>
inline void print_integer_to_stream(T val, std::basic_ostream<Char>& stream)
inline void print_integer_to_stream(T val, std::basic_ostream<Char>& stream, value_flags format = {})
{
static_assert(
sizeof(Char) == 1,
"The stream's underlying character type must be 1 byte in size."
);
if (!val)
{
print_to_stream('0', stream);
return;
}
int base = 10;
if (format != value_flags::none && val >= T{})
{
switch (format)
{
case value_flags::format_as_binary: base = 2; break;
case value_flags::format_as_octal: base = 8; break;
case value_flags::format_as_hexadecimal: base = 16; break;
default: break;
}
}
#if TOML_INT_CHARCONV
char buf[charconv_buffer_length<T>];
const auto res = std::to_chars(buf, buf + sizeof(buf), val);
{
char buf[(sizeof(T) * CHAR_BIT)];
const auto res = std::to_chars(buf, buf + sizeof(buf), val, base);
const auto len = static_cast<size_t>(res.ptr - buf);
if (base == 16)
{
for (size_t i = 0; i < len; i++)
if (buf[i] >= 'a')
buf[i] -= 32;
}
print_to_stream(buf, len, stream);
}
#else
{
using unsigned_type = std::conditional_t<(sizeof(T) > sizeof(unsigned)), std::make_unsigned_t<T>, unsigned>;
using cast_type = std::conditional_t<std::is_signed_v<T>, std::make_signed_t<unsigned_type>, unsigned_type>;
std::ostringstream ss;
ss.imbue(std::locale::classic());
using cast_type = std::conditional_t<std::is_signed_v<T>, int64_t, uint64_t>;
ss << static_cast<cast_type>(val);
const auto str = std::move(ss).str();
print_to_stream(str, stream);
if TOML_UNLIKELY(format == value_flags::format_as_binary)
{
bool found_one = false;
const auto v = static_cast<unsigned_type>(val);
unsigned_type mask = unsigned_type{ 1 } << (sizeof(unsigned_type) * CHAR_BIT - 1u);
for (unsigned i = 0; i < sizeof(unsigned_type) * CHAR_BIT; i++)
{
if ((v & mask))
{
print_to_stream('1', stream);
found_one = true;
}
else if (found_one)
print_to_stream('0', stream);
mask >>= 1;
}
}
else
{
std::ostringstream ss;
ss.imbue(std::locale::classic());
ss << std::uppercase << std::setbase(base);
ss << static_cast<cast_type>(val);
const auto str = std::move(ss).str();
print_to_stream(str, stream);
}
}
#endif
}
#define TOML_P2S_OVERLOAD(Type) \
template <typename Char> \
TOML_ALWAYS_INLINE \
void print_to_stream(Type val, std::basic_ostream<Char>& stream) \
{ \
static_assert(sizeof(Char) == 1); \
print_integer_to_stream(val, stream); \
#define TOML_P2S_OVERLOAD(Type) \
template <typename Char> \
inline void print_to_stream(Type val, std::basic_ostream<Char>& stream, value_flags format) \
{ \
static_assert(sizeof(Char) == 1); \
print_integer_to_stream(val, stream, format); \
}
TOML_P2S_OVERLOAD(int8_t)
@ -149,27 +191,28 @@ namespace toml::impl
#undef TOML_P2S_OVERLOAD
template <typename T, typename Char>
TOML_EXTERNAL_LINKAGE
void print_floating_point_to_stream(T val, std::basic_ostream<Char>& stream, bool hexfloat = false)
inline void print_floating_point_to_stream(T val, std::basic_ostream<Char>& stream, bool hexfloat = false)
{
static_assert(
sizeof(Char) == 1,
"The stream's underlying character type must be 1 byte in size."
);
switch (std::fpclassify(val))
switch (impl::fpclassify(val))
{
case FP_INFINITE:
if (val < T{})
print_to_stream('-', stream);
case fp_class::neg_inf:
print_to_stream("-inf"sv, stream);
break;
case fp_class::pos_inf:
print_to_stream("inf"sv, stream);
return;
break;
case FP_NAN:
case fp_class::nan:
print_to_stream("nan"sv, stream);
return;
break;
default:
case fp_class::ok:
{
static constexpr auto needs_decimal_point = [](auto&& s) noexcept
{
@ -204,32 +247,32 @@ namespace toml::impl
print_to_stream(".0"sv, stream);
}
#endif
break;
}
TOML_NO_DEFAULT_CASE;
}
}
#if !TOML_ALL_INLINE
extern template TOML_API void print_floating_point_to_stream(float, std::ostream&, bool);
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
extern template TOML_API void print_floating_point_to_stream(double, std::ostream&, bool);
#endif
#define TOML_P2S_OVERLOAD(Type) \
template <typename Char> \
TOML_ALWAYS_INLINE \
void print_to_stream(Type val, std::basic_ostream<Char>& stream) \
inline void print_to_stream(Type val, std::basic_ostream<Char>& stream) \
{ \
static_assert(sizeof(Char) == 1); \
print_floating_point_to_stream(val, stream); \
}
TOML_P2S_OVERLOAD(float)
TOML_P2S_OVERLOAD(double)
#undef TOML_P2S_OVERLOAD
template <typename Char>
TOML_ALWAYS_INLINE
void print_to_stream(bool val, std::basic_ostream<Char>& stream)
inline void print_to_stream(bool val, std::basic_ostream<Char>& stream)
{
static_assert(sizeof(Char) == 1);
print_to_stream(val ? "true"sv : "false"sv, stream);
@ -330,12 +373,12 @@ namespace toml::impl
print_to_stream(val.date, stream);
print_to_stream('T', stream);
print_to_stream(val.time, stream);
if (val.time_offset)
print_to_stream(*val.time_offset, stream);
if (val.offset)
print_to_stream(*val.offset, stream);
}
TOML_PUSH_WARNINGS
TOML_DISABLE_ALL_WARNINGS
TOML_DISABLE_ARITHMETIC_WARNINGS
template <typename T, typename Char>
void print_to_stream_with_escapes(T && str, std::basic_ostream<Char>& stream)
@ -343,24 +386,24 @@ namespace toml::impl
static_assert(sizeof(Char) == 1);
for (auto c : str)
{
if TOML_UNLIKELY(c >= TOML_STRING_PREFIX('\x00') && c <= TOML_STRING_PREFIX('\x1F'))
if TOML_UNLIKELY(c >= '\x00' && c <= '\x1F')
print_to_stream(low_character_escape_table[c], stream);
else if TOML_UNLIKELY(c == TOML_STRING_PREFIX('\x7F'))
print_to_stream(TOML_STRING_PREFIX("\\u007F"sv), stream);
else if TOML_UNLIKELY(c == TOML_STRING_PREFIX('"'))
print_to_stream(TOML_STRING_PREFIX("\\\""sv), stream);
else if TOML_UNLIKELY(c == TOML_STRING_PREFIX('\\'))
print_to_stream(TOML_STRING_PREFIX("\\\\"sv), stream);
else if TOML_UNLIKELY(c == '\x7F')
print_to_stream("\\u007F"sv, stream);
else if TOML_UNLIKELY(c == '"')
print_to_stream("\\\""sv, stream);
else if TOML_UNLIKELY(c == '\\')
print_to_stream("\\\\"sv, stream);
else
print_to_stream(c, stream);
}
}
TOML_POP_WARNINGS
TOML_POP_WARNINGS // TOML_DISABLE_ARITHMETIC_WARNINGS
}
TOML_IMPL_NAMESPACE_END
namespace toml
TOML_NAMESPACE_START
{
/// \brief Prints a source_position to a stream.
///
@ -369,7 +412,7 @@ namespace toml
///
/// std::cout << "The value for 'bar' was found on "sv
/// << tbl.get("bar")->source().begin()
/// << std::endl;
/// << "\n";
///
/// \ecpp
///
@ -383,8 +426,7 @@ namespace toml
///
/// \returns The input stream.
template <typename Char>
TOML_EXTERNAL_LINKAGE
std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const source_position& rhs)
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const source_position& rhs)
{
static_assert(
sizeof(Char) == 1,
@ -404,7 +446,7 @@ namespace toml
///
/// std::cout << "The value for 'bar' was found on "sv
/// << tbl.get("bar")->source()
/// << std::endl;
/// << "\n";
///
/// \ecpp
///
@ -418,8 +460,7 @@ namespace toml
///
/// \returns The input stream.
template <typename Char>
TOML_EXTERNAL_LINKAGE
std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const source_region& rhs)
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const source_region& rhs)
{
static_assert(
sizeof(Char) == 1,
@ -435,8 +476,11 @@ namespace toml
return lhs;
}
#if !TOML_ALL_INLINE
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
extern template TOML_API std::ostream& operator << (std::ostream&, const source_position&);
extern template TOML_API std::ostream& operator << (std::ostream&, const source_region&);
#endif
}
TOML_NAMESPACE_END
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS

File diff suppressed because it is too large Load Diff

View File

@ -14,42 +14,104 @@
#include "toml_table.h"
#include "toml_node_view.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_SUGGEST_WARNINGS
namespace toml
TOML_NAMESPACE_START
{
#if TOML_LIFETIME_HOOKS
TOML_EXTERNAL_LINKAGE
void table::lh_ctor() noexcept
{
TOML_TABLE_CREATED;
}
TOML_EXTERNAL_LINKAGE
void table::lh_dtor() noexcept
{
TOML_TABLE_DESTROYED;
}
#endif
TOML_EXTERNAL_LINKAGE
table::table() noexcept
{
#if TOML_LIFETIME_HOOKS
lh_ctor();
#endif
}
TOML_EXTERNAL_LINKAGE
table::table(const table& other) noexcept
: node{ std::move(other) },
inline_{ other.inline_ }
{
for (auto&& [k, v] : other)
map.emplace_hint(map.end(), k, impl::make_node(v));
#if TOML_LIFETIME_HOOKS
lh_ctor();
#endif
}
TOML_EXTERNAL_LINKAGE
table::table(table&& other) noexcept
: node{ std::move(other) },
map{ std::move(other.map) },
inline_{ other.inline_ }
{
#if TOML_LIFETIME_HOOKS
lh_ctor();
#endif
}
TOML_EXTERNAL_LINKAGE
table& table::operator= (const table& rhs) noexcept
{
if (&rhs != this)
{
node::operator=(rhs);
map.clear();
for (auto&& [k, v] : rhs)
map.emplace_hint(map.end(), k, impl::make_node(v));
inline_ = rhs.inline_;
}
return *this;
}
TOML_EXTERNAL_LINKAGE
table& table::operator= (table&& rhs) noexcept
{
if (&rhs != this)
{
node::operator=(std::move(rhs));
map = std::move(rhs.map);
inline_ = rhs.inline_;
}
return *this;
}
TOML_EXTERNAL_LINKAGE
table::~table() noexcept
{
#if TOML_LIFETIME_HOOKS
lh_dtor();
#endif
}
TOML_EXTERNAL_LINKAGE
table::table(impl::table_init_pair* pairs, size_t count) noexcept
{
for (size_t i = 0; i < count; i++)
{
values.insert_or_assign(
if (!pairs[i].value) // empty node_views
continue;
map.insert_or_assign(
std::move(pairs[i].key),
std::move(pairs[i].value)
);
}
}
TOML_EXTERNAL_LINKAGE
table::table() noexcept {}
TOML_EXTERNAL_LINKAGE
table::table(table&& other) noexcept
: node{ std::move(other) },
values{ std::move(other.values) },
inline_{ other.inline_ }
{}
TOML_EXTERNAL_LINKAGE
table& table::operator = (table&& rhs) noexcept
{
node::operator=(std::move(rhs));
values = std::move(rhs.values);
inline_ = rhs.inline_;
return *this;
}
#define TOML_MEMBER_ATTR(attr) TOML_EXTERNAL_LINKAGE TOML_ATTR(attr)
TOML_MEMBER_ATTR(const) node_type table::type() const noexcept { return node_type::table; }
@ -62,99 +124,207 @@ namespace toml
TOML_MEMBER_ATTR(pure) bool table::is_inline() const noexcept { return inline_; }
TOML_EXTERNAL_LINKAGE void table::is_inline(bool val) noexcept { inline_ = val; }
TOML_EXTERNAL_LINKAGE table::const_iterator table::begin() const noexcept { return { values.begin() }; }
TOML_EXTERNAL_LINKAGE table::const_iterator table::end() const noexcept { return { values.end() }; }
TOML_EXTERNAL_LINKAGE table::const_iterator table::cbegin() const noexcept { return { values.cbegin() }; }
TOML_EXTERNAL_LINKAGE table::const_iterator table::cend() const noexcept { return { values.cend() }; }
TOML_EXTERNAL_LINKAGE table::iterator table::begin() noexcept { return { values.begin() }; }
TOML_EXTERNAL_LINKAGE table::iterator table::end() noexcept { return { values.end() }; }
TOML_EXTERNAL_LINKAGE table::const_iterator table::begin() const noexcept { return { map.begin() }; }
TOML_EXTERNAL_LINKAGE table::const_iterator table::end() const noexcept { return { map.end() }; }
TOML_EXTERNAL_LINKAGE table::const_iterator table::cbegin() const noexcept { return { map.cbegin() }; }
TOML_EXTERNAL_LINKAGE table::const_iterator table::cend() const noexcept { return { map.cend() }; }
TOML_EXTERNAL_LINKAGE table::iterator table::begin() noexcept { return { map.begin() }; }
TOML_EXTERNAL_LINKAGE table::iterator table::end() noexcept { return { map.end() }; }
TOML_MEMBER_ATTR(pure) bool table::empty() const noexcept { return values.empty(); }
TOML_MEMBER_ATTR(pure) size_t table::size() const noexcept { return values.size(); }
TOML_EXTERNAL_LINKAGE void table::clear() noexcept { values.clear(); }
TOML_MEMBER_ATTR(pure) bool table::empty() const noexcept { return map.empty(); }
TOML_MEMBER_ATTR(pure) size_t table::size() const noexcept { return map.size(); }
TOML_EXTERNAL_LINKAGE void table::clear() noexcept { map.clear(); }
#undef TOML_MEMBER_ATTR
TOML_EXTERNAL_LINKAGE
node_view<node> table::operator[] (string_view key) noexcept
bool table::is_homogeneous(node_type ntype) const noexcept
{
return { this->get(key) };
if (map.empty())
return false;
if (ntype == node_type::none)
ntype = map.cbegin()->second->type();
for (const auto& [k, v] : map)
{
(void)k;
if (v->type() != ntype)
return false;
}
return true;
}
namespace impl
{
template <typename T, typename U>
TOML_INTERNAL_LINKAGE
bool table_is_homogeneous(T& map, node_type ntype, U& first_nonmatch) noexcept
{
if (map.empty())
{
first_nonmatch = {};
return false;
}
if (ntype == node_type::none)
ntype = map.cbegin()->second->type();
for (const auto& [k, v] : map)
{
(void)k;
if (v->type() != ntype)
{
first_nonmatch = v.get();
return false;
}
}
return true;
}
}
TOML_EXTERNAL_LINKAGE
bool table::is_homogeneous(node_type ntype, toml::node*& first_nonmatch) noexcept
{
return impl::table_is_homogeneous(map, ntype, first_nonmatch);
}
TOML_EXTERNAL_LINKAGE
bool table::is_homogeneous(node_type ntype, const toml::node*& first_nonmatch) const noexcept
{
return impl::table_is_homogeneous(map, ntype, first_nonmatch);
}
TOML_EXTERNAL_LINKAGE
node_view<node> table::operator[] (std::string_view key) noexcept
{
return node_view<node>{ this->get(key) };
}
TOML_EXTERNAL_LINKAGE
node_view<const node> table::operator[] (string_view key) const noexcept
node_view<const node> table::operator[] (std::string_view key) const noexcept
{
return { this->get(key) };
return node_view<const node>{ this->get(key) };
}
TOML_EXTERNAL_LINKAGE
table::iterator table::erase(iterator pos) noexcept
{
return { values.erase(pos.raw_) };
return { map.erase(pos.raw_) };
}
TOML_EXTERNAL_LINKAGE
table::iterator table::erase(const_iterator pos) noexcept
{
return { values.erase(pos.raw_) };
return { map.erase(pos.raw_) };
}
TOML_EXTERNAL_LINKAGE
table::iterator table::erase(const_iterator first, const_iterator last) noexcept
{
return { values.erase(first.raw_, last.raw_) };
return { map.erase(first.raw_, last.raw_) };
}
TOML_EXTERNAL_LINKAGE
bool table::erase(string_view key) noexcept
bool table::erase(std::string_view key) noexcept
{
if (auto it = values.find(key); it != values.end())
if (auto it = map.find(key); it != map.end())
{
values.erase(it);
map.erase(it);
return true;
}
return false;
}
TOML_EXTERNAL_LINKAGE
node* table::get(string_view key) noexcept
node* table::get(std::string_view key) noexcept
{
return do_get(values, key);
return do_get(map, key);
}
TOML_EXTERNAL_LINKAGE
const node* table::get(string_view key) const noexcept
const node* table::get(std::string_view key) const noexcept
{
return do_get(values, key);
return do_get(map, key);
}
TOML_EXTERNAL_LINKAGE
table::iterator table::find(string_view key) noexcept
table::iterator table::find(std::string_view key) noexcept
{
return { values.find(key) };
return { map.find(key) };
}
TOML_EXTERNAL_LINKAGE
table::const_iterator table::find(string_view key) const noexcept
table::const_iterator table::find(std::string_view key) const noexcept
{
return { values.find(key) };
return { map.find(key) };
}
TOML_EXTERNAL_LINKAGE
bool table::contains(string_view key) const noexcept
bool table::contains(std::string_view key) const noexcept
{
return do_contains(values, key);
return do_contains(map, key);
}
#if TOML_WINDOWS_COMPAT
TOML_EXTERNAL_LINKAGE
node_view<node> table::operator[] (std::wstring_view key) noexcept
{
return node_view<node>{ this->get(key) };
}
TOML_EXTERNAL_LINKAGE
node_view<const node> table::operator[] (std::wstring_view key) const noexcept
{
return node_view<const node>{ this->get(key) };
}
TOML_EXTERNAL_LINKAGE
bool table::erase(std::wstring_view key) noexcept
{
return erase(impl::narrow(key));
}
TOML_EXTERNAL_LINKAGE
node* table::get(std::wstring_view key) noexcept
{
return get(impl::narrow(key));
}
TOML_EXTERNAL_LINKAGE
const node* table::get(std::wstring_view key) const noexcept
{
return get(impl::narrow(key));
}
TOML_EXTERNAL_LINKAGE
table::iterator table::find(std::wstring_view key) noexcept
{
return find(impl::narrow(key));
}
TOML_EXTERNAL_LINKAGE
table::const_iterator table::find(std::wstring_view key) const noexcept
{
return find(impl::narrow(key));
}
TOML_EXTERNAL_LINKAGE
bool table::contains(std::wstring_view key) const noexcept
{
return contains(impl::narrow(key));
}
#endif // TOML_WINDOWS_COMPAT
TOML_API
TOML_EXTERNAL_LINKAGE
bool operator == (const table& lhs, const table& rhs) noexcept
{
if (&lhs == &rhs)
return true;
if (lhs.values.size() != rhs.values.size())
if (lhs.map.size() != rhs.map.size())
return false;
for (auto l = lhs.values.begin(), r = rhs.values.begin(), e = lhs.values.end(); l != e; l++, r++)
for (auto l = lhs.map.begin(), r = rhs.map.begin(), e = lhs.map.end(); l != e; l++, r++)
{
if (l->first != r->first)
return false;
@ -182,5 +352,5 @@ namespace toml
return !(lhs == rhs);
}
}
TOML_NAMESPACE_END
TOML_POP_WARNINGS // TOML_DISABLE_SUGGEST_WARNINGS

View File

@ -1,26 +1,15 @@
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
//# Copyright (c) 2019-2020 Mark Gillard <mark.gillard@outlook.com.au>
//# Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de> (utf8_decoder)
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT
#pragma once
#include "toml_utf8_generated.h"
#ifndef DOXYGEN
namespace toml::impl
TOML_IMPL_NAMESPACE_START
{
template <typename... T>
[[nodiscard]]
TOML_ATTR(const)
constexpr bool is_match(char32_t codepoint, T... vals) noexcept
{
static_assert((std::is_same_v<char32_t, T> && ...));
return ((codepoint == vals) || ...);
}
[[nodiscard]]
TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr bool is_ascii_whitespace(char32_t codepoint) noexcept
{
return codepoint == U'\t' || codepoint == U' ';
@ -28,7 +17,7 @@ namespace toml::impl
[[nodiscard]]
TOML_ATTR(const)
constexpr bool is_unicode_whitespace(char32_t codepoint) noexcept
constexpr bool is_non_ascii_whitespace(char32_t codepoint) noexcept
{
// see: https://en.wikipedia.org/wiki/Whitespace_character#Unicode
// (characters that don't say "is a line-break")
@ -46,13 +35,12 @@ namespace toml::impl
TOML_ATTR(const)
constexpr bool is_whitespace(char32_t codepoint) noexcept
{
return is_ascii_whitespace(codepoint) || is_unicode_whitespace(codepoint);
return is_ascii_whitespace(codepoint) || is_non_ascii_whitespace(codepoint);
}
template <bool IncludeCarriageReturn = true>
[[nodiscard]]
TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr bool is_ascii_line_break(char32_t codepoint) noexcept
{
constexpr auto low_range_end = IncludeCarriageReturn ? U'\r' : U'\f';
@ -61,7 +49,7 @@ namespace toml::impl
[[nodiscard]]
TOML_ATTR(const)
constexpr bool is_unicode_line_break(char32_t codepoint) noexcept
constexpr bool is_non_ascii_line_break(char32_t codepoint) noexcept
{
// see https://en.wikipedia.org/wiki/Whitespace_character#Unicode
// (characters that say "is a line-break")
@ -77,12 +65,11 @@ namespace toml::impl
TOML_ATTR(const)
constexpr bool is_line_break(char32_t codepoint) noexcept
{
return is_ascii_line_break<IncludeCarriageReturn>(codepoint) || is_unicode_line_break(codepoint);
return is_ascii_line_break<IncludeCarriageReturn>(codepoint) || is_non_ascii_line_break(codepoint);
}
[[nodiscard]]
TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr bool is_string_delimiter(char32_t codepoint) noexcept
{
return codepoint == U'"' || codepoint == U'\'';
@ -90,7 +77,6 @@ namespace toml::impl
[[nodiscard]]
TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr bool is_ascii_letter(char32_t codepoint) noexcept
{
return (codepoint >= U'a' && codepoint <= U'z')
@ -99,7 +85,6 @@ namespace toml::impl
[[nodiscard]]
TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr bool is_binary_digit(char32_t codepoint) noexcept
{
return codepoint == U'0' || codepoint == U'1';
@ -107,7 +92,6 @@ namespace toml::impl
[[nodiscard]]
TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr bool is_octal_digit(char32_t codepoint) noexcept
{
return (codepoint >= U'0' && codepoint <= U'7');
@ -115,16 +99,21 @@ namespace toml::impl
[[nodiscard]]
TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr bool is_decimal_digit(char32_t codepoint) noexcept
{
return (codepoint >= U'0' && codepoint <= U'9');
}
[[nodiscard]]
TOML_ATTR(const)
constexpr bool is_hexadecimal_digit(char32_t c) noexcept
{
return U'0' <= c && c <= U'f' && (1ull << (static_cast<uint_least64_t>(c) - 0x30u)) & 0x7E0000007E03FFull;
}
template <typename T>
[[nodiscard]]
TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr std::uint_least32_t hex_to_dec(const T codepoint) noexcept
{
if constexpr (std::is_same_v<remove_cvref_t<T>, std::uint_least32_t>)
@ -136,6 +125,730 @@ namespace toml::impl
return hex_to_dec(static_cast<std::uint_least32_t>(codepoint));
}
#if TOML_LANG_UNRELEASED // toml/issues/687 (unicode bare keys)
//# Returns true if a codepoint belongs to any of these categories:
//# Ll, Lm, Lo, Lt, Lu
[[nodiscard]]
TOML_ATTR(const)
constexpr bool is_non_ascii_letter(char32_t c) noexcept
{
if (U'\xAA' > c || c > U'\U0003134A')
return false;
const auto child_index_0 = (static_cast<uint_least64_t>(c) - 0xAAull) / 0xC4Bull;
if ((1ull << child_index_0) & 0x26180C0000ull)
return false;
if ((1ull << child_index_0) & 0x8A7FFC004001CFA0ull)
return true;
switch (child_index_0)
{
case 0x00: // [0] 00AA - 0CF4
{
if (c > U'\u0CF2')
return false;
TOML_ASSUME(U'\xAA' <= c);
constexpr uint_least64_t bitmask_table_1[] =
{
0xFFFFDFFFFFC10801u, 0xFFFFFFFFFFFFDFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0x07C000FFF0FFFFFFu, 0x0000000000000014u, 0x0000000000000000u, 0xFEFFFFF5D02F37C0u,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFEFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFF00FFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFC09FFFFFFFFFBFu, 0x000000007FFFFFFFu,
0xFFFFFFC000000000u, 0xFFC00000000001E1u, 0x00000001FFFFFFFFu, 0xFFFFFFFFFFFFFFB0u,
0x18000BFFFFFFFFFFu, 0xFFFFFF4000270030u, 0xFFFFFFF80000003Fu, 0x0FFFFFFFFFFFFFFFu,
0xFFFFFFFF00000080u, 0x44010FFFFFC10C01u, 0xFFC07FFFFFC00000u, 0xFFC0000000000001u,
0x000000003FFFF7FFu, 0xFFFFFFFFFC000000u, 0x00FFC0400008FFFFu, 0x7FFFFE67F87FFF80u,
0x00EC00100008F17Fu, 0x7FFFFE61F80400C0u, 0x001780000000DB7Fu, 0x7FFFFEEFF8000700u,
0x00C000400008FB7Fu, 0x7FFFFE67F8008000u, 0x00EC00000008FB7Fu, 0xC6358F71FA000080u,
0x000000400000FFF1u, 0x7FFFFF77F8000000u, 0x00C1C0000008FFFFu, 0x7FFFFF77F8400000u,
0x00D000000008FBFFu, 0x0000000000000180u,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0xAAull) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0xAAull) % 0x40ull));
// 1922 code units from 124 ranges (spanning a search area of 3145)
}
case 0x01: // [1] 0CF5 - 193F
{
if (U'\u0D04' > c || c > U'\u191E')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0x027FFFFFFFFFDDFFu, 0x0FC0000038070400u, 0xF2FFBFFFFFC7FFFEu, 0xE000000000000007u,
0xF000DFFFFFFFFFFFu, 0x6000000000000007u, 0xF200DFFAFFFFFF7Du, 0x100000000F000005u,
0xF000000000000000u, 0x000001FFFFFFFFEFu, 0x00000000000001F0u, 0xF000000000000000u,
0x0800007FFFFFFFFFu, 0x3FFE1C0623C3F000u, 0xFFFFFFFFF0000400u, 0xFF7FFFFFFFFFF20Bu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFF3D7F3DFu, 0xD7F3DFFFFFFFF3DFu, 0xFFFFFFFFFFF7FFF3u,
0xFFFFFFFFFFF3DFFFu, 0xF0000000007FFFFFu, 0xFFFFFFFFF0000FFFu, 0xE3F3FFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xEFFFF9FFFFFFFFFFu, 0xFFFFFFFFF07FFFFFu, 0xF01FE07FFFFFFFFFu,
0xF0003FFFF0003DFFu, 0xF0001DFFF0003FFFu, 0x0000FFFFFFFFFFFFu, 0x0000000001080000u,
0xFFFFFFFFF0000000u, 0xF01FFFFFFFFFFFFFu, 0xFFFFF05FFFFFFFF9u, 0xF003FFFFFFFFFFFFu,
0x0000000007FFFFFFu,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0xD04ull) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0xD04ull) % 0x40ull));
// 2239 code units from 83 ranges (spanning a search area of 3099)
}
case 0x02: // [2] 1940 - 258A
{
if (U'\u1950' > c || c > U'\u2184')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0xFFFF001F3FFFFFFFu, 0x03FFFFFF0FFFFFFFu, 0xFFFF000000000000u, 0xFFFFFFFFFFFF007Fu,
0x000000000000001Fu, 0x0000000000800000u, 0xFFE0000000000000u, 0x0FE0000FFFFFFFFFu,
0xFFF8000000000000u, 0xFFFFFC00C001FFFFu, 0xFFFF0000003FFFFFu, 0xE0000000000FFFFFu,
0x01FF3FFFFFFFFC00u, 0x0000E7FFFFFFFFFFu, 0xFFFF046FDE000000u, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0x0000FFFFFFFFFFFFu, 0xFFFF000000000000u, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0x3F3FFFFFFFFF3F3Fu,
0xFFFF3FFFFFFFAAFFu, 0x1FDC5FDFFFFFFFFFu, 0x00001FDC1FFF0FCFu, 0x0000000000000000u,
0x0000800200000000u, 0x0000000000001FFFu, 0xFC84000000000000u, 0x43E0F3FFBD503E2Fu,
0x0018000000000000u,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x1950ull) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0x1950ull) % 0x40ull));
// 1184 code units from 59 ranges (spanning a search area of 2101)
}
case 0x03: // [3] 258B - 31D5
{
if (U'\u2C00' > c || c > U'\u31BF')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0xFFFF7FFFFFFFFFFFu, 0xFFFFFFFF7FFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0x000C781FFFFFFFFFu,
0xFFFF20BFFFFFFFFFu, 0x000080FFFFFFFFFFu, 0x7F7F7F7F007FFFFFu, 0x000000007F7F7F7Fu,
0x0000800000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x183E000000000060u, 0xFFFFFFFFFFFFFFFEu, 0xFFFFFFFEE07FFFFFu, 0xF7FFFFFFFFFFFFFFu,
0xFFFEFFFFFFFFFFE0u, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFF00007FFFu,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x2C00ull) / 0x40ull]
& (0x1ull << (static_cast<uint_least64_t>(c) % 0x40ull));
// 771 code units from 30 ranges (spanning a search area of 1472)
}
case 0x04: return (U'\u31F0' <= c && c <= U'\u31FF') || U'\u3400' <= c;
case 0x06: return c <= U'\u4DBF' || U'\u4E00' <= c;
case 0x0C: return c <= U'\u9FFC' || U'\uA000' <= c;
case 0x0D: // [13] A079 - ACC3
{
TOML_ASSUME(U'\uA079' <= c && c <= U'\uACC3');
constexpr uint_least64_t bitmask_table_1[] =
{
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0x00000000000FFFFFu, 0xFFFFFFFFFF800000u, 0xFFFFFFFFFFFFFF9Fu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0x0006007FFF8FFFFFu, 0x003FFFFFFFFFFF80u,
0xFFFFFF9FFFFFFFC0u, 0x00001FFFFFFFFFFFu, 0xFFFFFE7FC0000000u, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFCFFFFu, 0xF00000000003FE7Fu, 0x000003FFFFFBDDFFu, 0x07FFFFFFFFFFFF80u,
0x07FFFFFFFFFFFE00u, 0x7E00000000000000u, 0xFF801FFFFFFE0034u, 0xFFFFFF8000003FFFu,
0x03FFFFFFFFFFF80Fu, 0x007FEF8000400000u, 0x0000FFFFFFFFFFBEu, 0x3FFFFF800007FB80u,
0x317FFFFFFFFFFFE2u, 0x0E03FF9C0000029Fu, 0xFFBFBF803F3F3F00u, 0xFF81FFFBFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0x000003FFFFFFFFFFu, 0xFFFFFFFFFFFFFF80u, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0x00000000000007FFu,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0xA079ull) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0xA079ull) % 0x40ull));
// 2554 code units from 52 ranges (spanning a search area of 3147)
}
case 0x11: return c <= U'\uD7A3' || (U'\uD7B0' <= c && c <= U'\uD7C6') || (U'\uD7CB' <= c && c <= U'\uD7FB');
case 0x14: // [20] F686 - 102D0
{
if (U'\uF900' > c)
return false;
TOML_ASSUME(c <= U'\U000102D0');
constexpr uint_least64_t bitmask_table_1[] =
{
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFF3FFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0x0000000003FFFFFFu,
0x5F7FFDFFA0F8007Fu, 0xFFFFFFFFFFFFFFDBu, 0x0003FFFFFFFFFFFFu, 0xFFFFFFFFFFF80000u,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0x3FFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFF0000u, 0xFFFFFFFFFFFCFFFFu, 0x0FFF0000000000FFu,
0x0000000000000000u, 0xFFDF000000000000u, 0xFFFFFFFFFFFFFFFFu, 0x1FFFFFFFFFFFFFFFu,
0x07FFFFFE00000000u, 0xFFFFFFC007FFFFFEu, 0x7FFFFFFFFFFFFFFFu, 0x000000001CFCFCFCu,
0xB7FFFF7FFFFFEFFFu, 0x000000003FFF3FFFu, 0xFFFFFFFFFFFFFFFFu, 0x07FFFFFFFFFFFFFFu,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0xFFFFFFFF1FFFFFFFu, 0x000000000001FFFFu,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0xF900ull) / 0x40ull]
& (0x1ull << (static_cast<uint_least64_t>(c) % 0x40ull));
// 1710 code units from 34 ranges (spanning a search area of 2513)
}
case 0x15: // [21] 102D1 - 10F1B
{
if (U'\U00010300' > c)
return false;
TOML_ASSUME(c <= U'\U00010F1B');
constexpr uint_least64_t bitmask_table_1[] =
{
0xFFFFE000FFFFFFFFu, 0x003FFFFFFFFF03FDu, 0xFFFFFFFF3FFFFFFFu, 0x000000000000FF0Fu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFF00003FFFFFFFu, 0x0FFFFFFFFF0FFFFFu,
0xFFFF00FFFFFFFFFFu, 0x0000000FFFFFFFFFu, 0x0000000000000000u, 0x0000000000000000u,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0x007FFFFFFFFFFFFFu, 0x000000FF003FFFFFu, 0x0000000000000000u, 0x0000000000000000u,
0x91BFFFFFFFFFFD3Fu, 0x007FFFFF003FFFFFu, 0x000000007FFFFFFFu, 0x0037FFFF00000000u,
0x03FFFFFF003FFFFFu, 0x0000000000000000u, 0xC0FFFFFFFFFFFFFFu, 0x0000000000000000u,
0x003FFFFFFEEF0001u, 0x1FFFFFFF00000000u, 0x000000001FFFFFFFu, 0x0000001FFFFFFEFFu,
0x003FFFFFFFFFFFFFu, 0x0007FFFF003FFFFFu, 0x000000000003FFFFu, 0x0000000000000000u,
0xFFFFFFFFFFFFFFFFu, 0x00000000000001FFu, 0x0007FFFFFFFFFFFFu, 0x0007FFFFFFFFFFFFu,
0x0000000FFFFFFFFFu, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x000303FFFFFFFFFFu, 0x0000000000000000u,
0x000000000FFFFFFFu,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x10300ull) / 0x40ull]
& (0x1ull << (static_cast<uint_least64_t>(c) % 0x40ull));
// 1620 code units from 48 ranges (spanning a search area of 3100)
}
case 0x16: // [22] 10F1C - 11B66
{
if (c > U'\U00011AF8')
return false;
TOML_ASSUME(U'\U00010F1C' <= c);
constexpr uint_least64_t bitmask_table_1[] =
{
0x000003FFFFF00801u, 0x0000000000000000u, 0x000001FFFFF00000u, 0xFFFFFF8007FFFFF0u,
0x000000000FFFFFFFu, 0xFFFFFF8000000000u, 0xFFF00000000FFFFFu, 0xFFFFFF8000001FFFu,
0xFFF00900000007FFu, 0xFFFFFF80047FFFFFu, 0x400001E0007FFFFFu, 0xFFBFFFF000000001u,
0x000000000000FFFFu, 0xFFFBD7F000000000u, 0xFFFFFFFFFFF01FFBu, 0xFF99FE0000000007u,
0x001000023EDFDFFFu, 0x000000000000003Eu, 0x0000000000000000u, 0xFFFFFFF000000000u,
0x0000780001FFFFFFu, 0xFFFFFFF000000038u, 0x00000B00000FFFFFu, 0x0000000000000000u,
0x0000000000000000u, 0xFFFFFFF000000000u, 0xF00000000007FFFFu, 0xFFFFFFF000000000u,
0x00000100000FFFFFu, 0xFFFFFFF000000000u, 0x0000000010007FFFu, 0x7FFFFFF000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0xFFFFFFF000000000u,
0x000000000000FFFFu, 0x0000000000000000u, 0xFFFFFFFFFFFFFFF0u, 0xF6FF27F80000000Fu,
0x00000028000FFFFFu, 0x0000000000000000u, 0x001FFFFFFFFFCFF0u, 0xFFFF8010000000A0u,
0x00100000407FFFFFu, 0x00003FFFFFFFFFFFu, 0xFFFFFFF000000002u, 0x000000001FFFFFFFu,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x10F1Cull) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0x10F1Cull) % 0x40ull));
// 1130 code units from 67 ranges (spanning a search area of 3037)
}
case 0x17: // [23] 11B67 - 127B1
{
if (U'\U00011C00' > c || c > U'\U00012543')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0x00007FFFFFFFFDFFu, 0xFFFC000000000001u, 0x000000000000FFFFu, 0x0000000000000000u,
0x0001FFFFFFFFFB7Fu, 0xFFFFFDBF00000040u, 0x00000000010003FFu, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0007FFFF00000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0001000000000000u, 0x0000000000000000u,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0x0000000003FFFFFFu, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0x000000000000000Fu,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x11C00ull) / 0x40ull]
& (0x1ull << (static_cast<uint_least64_t>(c) % 0x40ull));
// 1304 code units from 16 ranges (spanning a search area of 2372)
}
case 0x18: return U'\U00013000' <= c;
case 0x19: return c <= U'\U0001342E';
case 0x1A: return U'\U00014400' <= c && c <= U'\U00014646';
case 0x1D: // [29] 16529 - 17173
{
if (U'\U00016800' > c)
return false;
TOML_ASSUME(c <= U'\U00017173');
constexpr uint_least64_t bitmask_table_1[] =
{
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0x01FFFFFFFFFFFFFFu, 0x000000007FFFFFFFu, 0x0000000000000000u, 0x00003FFFFFFF0000u,
0x0000FFFFFFFFFFFFu, 0xE0FFFFF80000000Fu, 0x000000000000FFFFu, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0xFFFFFFFFFFFFFFFFu, 0x0000000000000000u, 0x0000000000000000u,
0xFFFFFFFFFFFFFFFFu, 0x00000000000107FFu, 0x00000000FFF80000u, 0x0000000B00000000u,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0x000FFFFFFFFFFFFFu,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x16800ull) / 0x40ull]
& (0x1ull << (static_cast<uint_least64_t>(c) % 0x40ull));
// 1250 code units from 14 ranges (spanning a search area of 2420)
}
case 0x1F: return c <= U'\U000187F7' || U'\U00018800' <= c;
case 0x20: return c <= U'\U00018CD5' || (U'\U00018D00' <= c && c <= U'\U00018D08');
case 0x23: // [35] 1AEEB - 1BB35
{
if (U'\U0001B000' > c || c > U'\U0001B2FB')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0x000000007FFFFFFFu, 0xFFFF00F000070000u, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0x0FFFFFFFFFFFFFFFu,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x1B000ull) / 0x40ull]
& (0x1ull << (static_cast<uint_least64_t>(c) % 0x40ull));
// 690 code units from 4 ranges (spanning a search area of 764)
}
case 0x24: // [36] 1BB36 - 1C780
{
if (U'\U0001BC00' > c || c > U'\U0001BC99')
return false;
switch ((static_cast<uint_least64_t>(c) - 0x1BC00ull) / 0x40ull)
{
case 0x01: return c <= U'\U0001BC7C' && (1ull << (static_cast<uint_least64_t>(c) - 0x1BC40u)) & 0x1FFF07FFFFFFFFFFull;
case 0x02: return (1u << (static_cast<uint_least32_t>(c) - 0x1BC80u)) & 0x3FF01FFu;
default: return true;
}
// 139 code units from 4 ranges (spanning a search area of 154)
TOML_UNREACHABLE;
}
case 0x26: // [38] 1D3CC - 1E016
{
if (U'\U0001D400' > c || c > U'\U0001D7CB')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFDFFFFFu, 0xEBFFDE64DFFFFFFFu, 0xFFFFFFFFFFFFFFEFu,
0x7BFFFFFFDFDFE7BFu, 0xFFFFFFFFFFFDFC5Fu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFF3FFFFFFFFFu, 0xF7FFFFFFF7FFFFFDu,
0xFFDFFFFFFFDFFFFFu, 0xFFFF7FFFFFFF7FFFu, 0xFFFFFDFFFFFFFDFFu, 0x0000000000000FF7u,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x1D400ull) / 0x40ull]
& (0x1ull << (static_cast<uint_least64_t>(c) % 0x40ull));
// 936 code units from 30 ranges (spanning a search area of 972)
}
case 0x27: // [39] 1E017 - 1EC61
{
if (U'\U0001E100' > c || c > U'\U0001E94B')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0x3F801FFFFFFFFFFFu, 0x0000000000004000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x00000FFFFFFFFFFFu,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0x000000000000001Fu,
0xFFFFFFFFFFFFFFFFu, 0x000000000000080Fu,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x1E100ull) / 0x40ull]
& (0x1ull << (static_cast<uint_least64_t>(c) % 0x40ull));
// 363 code units from 7 ranges (spanning a search area of 2124)
}
case 0x28: // [40] 1EC62 - 1F8AC
{
if (U'\U0001EE00' > c || c > U'\U0001EEBB')
return false;
switch ((static_cast<uint_least64_t>(c) - 0x1EE00ull) / 0x40ull)
{
case 0x00: return c <= U'\U0001EE3B' && (1ull << (static_cast<uint_least64_t>(c) - 0x1EE00u)) & 0xAF7FE96FFFFFFEFull;
case 0x01: return U'\U0001EE42' <= c && c <= U'\U0001EE7E'
&& (1ull << (static_cast<uint_least64_t>(c) - 0x1EE42u)) & 0x17BDFDE5AAA5BAA1ull;
case 0x02: return (1ull << (static_cast<uint_least64_t>(c) - 0x1EE80u)) & 0xFFFFBEE0FFFFBFFull;
TOML_NO_DEFAULT_CASE;
}
// 141 code units from 33 ranges (spanning a search area of 188)
TOML_UNREACHABLE;
}
case 0x29: return U'\U00020000' <= c;
case 0x37: return c <= U'\U0002A6DD' || U'\U0002A700' <= c;
case 0x38: return c <= U'\U0002B734' || (U'\U0002B740' <= c && c <= U'\U0002B81D') || U'\U0002B820' <= c;
case 0x3A: return c <= U'\U0002CEA1' || U'\U0002CEB0' <= c;
case 0x3C: return c <= U'\U0002EBE0';
case 0x3D: return U'\U0002F800' <= c && c <= U'\U0002FA1D';
case 0x3E: return U'\U00030000' <= c;
TOML_NO_DEFAULT_CASE;
}
// 131189 code units from 620 ranges (spanning a search area of 201377)
TOML_UNREACHABLE;
}
//# Returns true if a codepoint belongs to any of these categories:
//# Nd, Nl
[[nodiscard]]
TOML_ATTR(const)
constexpr bool is_non_ascii_number(char32_t c) noexcept
{
if (U'\u0660' > c || c > U'\U0001FBF9')
return false;
const auto child_index_0 = (static_cast<uint_least64_t>(c) - 0x660ull) / 0x7D7ull;
if ((1ull << child_index_0) & 0x47FFDFE07FCFFFD0ull)
return false;
switch (child_index_0)
{
case 0x00: // [0] 0660 - 0E36
{
if (c > U'\u0DEF')
return false;
TOML_ASSUME(U'\u0660' <= c);
constexpr uint_least64_t bitmask_table_1[] =
{
0x00000000000003FFu, 0x0000000000000000u, 0x0000000003FF0000u, 0x0000000000000000u,
0x0000000000000000u, 0x000003FF00000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x000000000000FFC0u, 0x0000000000000000u, 0x000000000000FFC0u, 0x0000000000000000u,
0x000000000000FFC0u, 0x0000000000000000u, 0x000000000000FFC0u, 0x0000000000000000u,
0x000000000000FFC0u, 0x0000000000000000u, 0x000000000000FFC0u, 0x0000000000000000u,
0x000000000000FFC0u, 0x0000000000000000u, 0x000000000000FFC0u, 0x0000000000000000u,
0x000000000000FFC0u, 0x0000000000000000u, 0x000000000000FFC0u,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x660ull) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0x660ull) % 0x40ull));
// 130 code units from 13 ranges (spanning a search area of 1936)
}
case 0x01: // [1] 0E37 - 160D
{
if (U'\u0E50' > c || c > U'\u1099')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0x00000000000003FFu, 0x0000000000000000u, 0x00000000000003FFu, 0x0000000003FF0000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x03FF000000000000u,
0x0000000000000000u, 0x00000000000003FFu,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0xE50ull) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0xE50ull) % 0x40ull));
// 50 code units from 5 ranges (spanning a search area of 586)
}
case 0x02: // [2] 160E - 1DE4
{
if (U'\u16EE' > c || c > U'\u1C59')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0x0000000000000007u, 0x0000000000000000u, 0x0000000000000000u, 0x0FFC000000000000u,
0x00000FFC00000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x00000003FF000000u, 0x0000000000000000u, 0x00000FFC00000000u,
0x0000000000000000u, 0x0000000000000000u, 0x00000FFC0FFC0000u, 0x0000000000000000u,
0x0000000000000000u, 0x00000FFC00000000u, 0x0000000000000000u, 0x0000000000000FFCu,
0x0000000000000000u, 0x00000FFC0FFC0000u,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x16EEull) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0x16EEull) % 0x40ull));
// 103 code units from 11 ranges (spanning a search area of 1388)
}
case 0x03: return U'\u2160' <= c && c <= U'\u2188' && (1ull << (static_cast<uint_least64_t>(c) - 0x2160u)) & 0x1E7FFFFFFFFull;
case 0x05: return U'\u3007' <= c && c <= U'\u303A' && (1ull << (static_cast<uint_least64_t>(c) - 0x3007u)) & 0xE0007FC000001ull;
case 0x14: // [20] A32C - AB02
{
if (U'\uA620' > c || c > U'\uAA59')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0x00000000000003FFu, 0x0000000000000000u, 0x0000000000000000u, 0x000000000000FFC0u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x03FF000000000000u, 0x000003FF00000000u,
0x0000000000000000u, 0x0000000000000000u, 0x03FF000000000000u, 0x0000000003FF0000u,
0x03FF000000000000u,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0xA620ull) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0xA620ull) % 0x40ull));
// 70 code units from 7 ranges (spanning a search area of 1082)
}
case 0x15: return U'\uABF0' <= c && c <= U'\uABF9';
case 0x1F: return U'\uFF10' <= c && c <= U'\uFF19';
case 0x20: // [32] 10140 - 10916
{
if (c > U'\U000104A9')
return false;
TOML_ASSUME(U'\U00010140' <= c);
constexpr uint_least64_t bitmask_table_1[] =
{
0x001FFFFFFFFFFFFFu, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000402u, 0x0000000000000000u, 0x00000000003E0000u, 0x0000000000000000u,
0x0000000000000000u, 0x000003FF00000000u,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x10140ull) / 0x40ull]
& (0x1ull << (static_cast<uint_least64_t>(c) % 0x40ull));
// 70 code units from 5 ranges (spanning a search area of 874)
}
case 0x21: return (U'\U00010D30' <= c && c <= U'\U00010D39') || (U'\U00011066' <= c && c <= U'\U0001106F');
case 0x22: // [34] 110EE - 118C4
{
if (U'\U000110F0' > c || c > U'\U00011739')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0x00000000000003FFu, 0x000000000000FFC0u, 0x0000000000000000u, 0x000003FF00000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x00000000000003FFu, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x000003FF00000000u, 0x0000000000000000u, 0x000003FF00000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x000003FF00000000u, 0x0000000000000000u, 0x0000000003FF0000u,
0x0000000000000000u, 0x00000000000003FFu,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x110F0ull) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0x110F0ull) % 0x40ull));
// 90 code units from 9 ranges (spanning a search area of 1610)
}
case 0x23: // [35] 118C5 - 1209B
{
if (U'\U000118E0' > c || c > U'\U00011DA9')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0x00000000000003FFu, 0x03FF000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x03FF000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x03FF000000000000u, 0x0000000000000000u, 0x00000000000003FFu,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x118E0ull) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0x118E0ull) % 0x40ull));
// 50 code units from 5 ranges (spanning a search area of 1226)
}
case 0x24: return U'\U00012400' <= c && c <= U'\U0001246E';
case 0x2D: return (U'\U00016A60' <= c && c <= U'\U00016A69') || (U'\U00016B50' <= c && c <= U'\U00016B59');
case 0x3B: return U'\U0001D7CE' <= c && c <= U'\U0001D7FF';
case 0x3C: return (U'\U0001E140' <= c && c <= U'\U0001E149') || (U'\U0001E2F0' <= c && c <= U'\U0001E2F9');
case 0x3D: return U'\U0001E950' <= c && c <= U'\U0001E959';
case 0x3F: return U'\U0001FBF0' <= c;
TOML_NO_DEFAULT_CASE;
}
// 876 code units from 72 ranges (spanning a search area of 128410)
TOML_UNREACHABLE;
}
//# Returns true if a codepoint belongs to any of these categories:
//# Mn, Mc
[[nodiscard]]
TOML_ATTR(const)
constexpr bool is_combining_mark(char32_t c) noexcept
{
if (U'\u0300' > c || c > U'\U000E01EF')
return false;
const auto child_index_0 = (static_cast<uint_least64_t>(c) - 0x300ull) / 0x37FCull;
if ((1ull << child_index_0) & 0x7FFFFFFFFFFFFE02ull)
return false;
switch (child_index_0)
{
case 0x00: // [0] 0300 - 3AFB
{
if (c > U'\u309A')
return false;
TOML_ASSUME(U'\u0300' <= c);
constexpr uint_least64_t bitmask_table_1[] =
{
0xFFFFFFFFFFFFFFFFu, 0x0000FFFFFFFFFFFFu, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x00000000000000F8u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0xBFFFFFFFFFFE0000u, 0x00000000000000B6u,
0x0000000007FF0000u, 0x00010000FFFFF800u, 0x0000000000000000u, 0x00003D9F9FC00000u,
0xFFFF000000020000u, 0x00000000000007FFu, 0x0001FFC000000000u, 0x200FF80000000000u,
0x00003EEFFBC00000u, 0x000000000E000000u, 0x0000000000000000u, 0xFFFFFFFBFFF80000u,
0xDC0000000000000Fu, 0x0000000C00FEFFFFu, 0xD00000000000000Eu, 0x4000000C0080399Fu,
0xD00000000000000Eu, 0x0023000000023987u, 0xD00000000000000Eu, 0xFC00000C00003BBFu,
0xD00000000000000Eu, 0x0000000C00E0399Fu, 0xC000000000000004u, 0x0000000000803DC7u,
0xC00000000000001Fu, 0x0000000C00603DDFu, 0xD00000000000000Eu, 0x0000000C00603DDFu,
0xD80000000000000Fu, 0x0000000C00803DDFu, 0x000000000000000Eu, 0x000C0000FF5F8400u,
0x07F2000000000000u, 0x0000000000007F80u, 0x1FF2000000000000u, 0x0000000000003F00u,
0xC2A0000003000000u, 0xFFFE000000000000u, 0x1FFFFFFFFEFFE0DFu, 0x0000000000000040u,
0x7FFFF80000000000u, 0x001E3F9DC3C00000u, 0x000000003C00BFFCu, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x00000000E0000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x001C0000001C0000u, 0x000C0000000C0000u, 0xFFF0000000000000u, 0x00000000200FFFFFu,
0x0000000000003800u, 0x0000000000000000u, 0x0000020000000060u, 0x0000000000000000u,
0x0FFF0FFF00000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x000000000F800000u, 0x9FFFFFFF7FE00000u, 0xBFFF000000000000u, 0x0000000000000001u,
0xFFF000000000001Fu, 0x000FF8000000001Fu, 0x00003FFE00000007u, 0x000FFFC000000000u,
0x00FFFFF000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x039021FFFFF70000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0xFBFFFFFFFFFFFFFFu,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0001FFE21FFF0000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0003800000000000u,
0x0000000000000000u, 0x8000000000000000u, 0x0000000000000000u, 0xFFFFFFFF00000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000FC0000000000u, 0x0000000000000000u, 0x0000000006000000u,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x300ull) / 0x40ull]
& (0x1ull << (static_cast<uint_least64_t>(c) % 0x40ull));
// 1106 code units from 156 ranges (spanning a search area of 11675)
}
case 0x02: // [2] 72F8 - AAF3
{
if (U'\uA66F' > c || c > U'\uAAEF')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0x0001800000007FE1u, 0x0000000000000000u, 0x0000000000000006u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x21F0000010880000u, 0x0000000000000000u,
0x0000000000060000u, 0xFFFE0000007FFFE0u, 0x7F80000000010007u, 0x0000001FFF000000u,
0x00000000001E0000u, 0x004000000003FFF0u, 0xFC00000000000000u, 0x00000000601000FFu,
0x0000000000007000u, 0xF00000000005833Au, 0x0000000000000001u,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0xA66Full) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0xA66Full) % 0x40ull));
// 137 code units from 28 ranges (spanning a search area of 1153)
}
case 0x03: return (U'\uAAF5' <= c && c <= U'\uAAF6') || (U'\uABE3' <= c && c <= U'\uABEA') || (U'\uABEC' <= c && c <= U'\uABED');
case 0x04: // [4] E2F0 - 11AEB
{
if (U'\uFB1E' > c || c > U'\U00011A99')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0x0000000000000001u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0003FFFC00000000u,
0x000000000003FFFCu, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000080000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000004u,
0x0000000000000000u, 0x000000001F000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0003C1B800000000u,
0x000000021C000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000180u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x00000000000003C0u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000006000u, 0x0000000000000000u,
0x0007FF0000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000001C00000000u,
0x000001FFFC000000u, 0x0000001E00000000u, 0x000000001FFC0000u, 0x0000001C00000000u,
0x00000180007FFE00u, 0x0000001C00200000u, 0x00037807FFE00000u, 0x0000000000000000u,
0x0000000103FFC000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000003C00001FFEu,
0x0200E67F60000000u, 0x00000000007C7F30u, 0x0000000000000000u, 0x0000000000000000u,
0x000001FFFF800000u, 0x0000000000000001u, 0x0000003FFFFC0000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0xC0000007FCFE0000u, 0x0000000000000000u,
0x00000007FFFC0000u, 0x0000000000000000u, 0x0000000003FFE000u, 0x8000000000000000u,
0x0000000000003FFFu, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x000000001FFFC000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x00000035E6FC0000u, 0x0000000000000000u, 0xF3F8000000000000u, 0x00001FF800000047u,
0x3FF80201EFE00000u, 0x0FFFF00000000000u,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0xFB1Eull) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0xFB1Eull) % 0x40ull));
// 402 code units from 63 ranges (spanning a search area of 8060)
}
case 0x05: // [5] 11AEC - 152E7
{
if (U'\U00011C2F' > c || c > U'\U00011EF6')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0x000000000001FEFFu, 0xFDFFFFF800000000u, 0x00000000000000FFu, 0x0000000000000000u,
0x00000000017F68FCu, 0x000001F6F8000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x00000000000000F0u,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x11C2Full) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0x11C2Full) % 0x40ull));
// 85 code units from 13 ranges (spanning a search area of 712)
}
case 0x06: // [6] 152E8 - 18AE3
{
if (U'\U00016AF0' > c || c > U'\U00016FF1')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0x000000000000001Fu, 0x000000000000007Fu, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0xFFFFFFFE80000000u, 0x0000000780FFFFFFu, 0x0010000000000000u,
0x0000000000000003u,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x16AF0ull) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0x16AF0ull) % 0x40ull));
// 75 code units from 7 ranges (spanning a search area of 1282)
}
case 0x07: return U'\U0001BC9D' <= c && c <= U'\U0001BC9E';
case 0x08: // [8] 1C2E0 - 1FADB
{
if (U'\U0001D165' > c || c > U'\U0001E94A')
return false;
constexpr uint_least64_t bitmask_table_1[] =
{
0x0000007F3FC03F1Fu, 0x00000000000001E0u, 0x0000000000000000u, 0x00000000E0000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0xFFFFFFFFF8000000u, 0xFFFFFFFFFFC3FFFFu,
0xF7C00000800100FFu, 0x00000000000007FFu, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0xDFCFFFFBF8000000u, 0x000000000000003Eu,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x000000000003F800u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000780u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
0x0000000000000000u, 0x0003F80000000000u, 0x0000000000000000u, 0x0000003F80000000u,
};
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x1D165ull) / 0x40ull]
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0x1D165ull) % 0x40ull));
// 223 code units from 21 ranges (spanning a search area of 6118)
}
case 0x3F: return U'\U000E0100' <= c;
TOML_NO_DEFAULT_CASE;
}
// 2282 code units from 293 ranges (spanning a search area of 917232)
TOML_UNREACHABLE;
}
#endif // TOML_LANG_UNRELEASED
[[nodiscard]]
TOML_ATTR(const)
constexpr bool is_bare_key_character(char32_t codepoint) noexcept
@ -146,9 +859,9 @@ namespace toml::impl
|| codepoint == U'_'
#if TOML_LANG_UNRELEASED // toml/issues/644 ('+' in bare keys) & toml/issues/687 (unicode bare keys)
|| codepoint == U'+'
|| is_unicode_letter(codepoint)
|| is_unicode_number(codepoint)
|| is_unicode_combining_mark(codepoint)
|| is_non_ascii_letter(codepoint)
|| is_non_ascii_number(codepoint)
|| is_combining_mark(codepoint)
#endif
;
}
@ -163,14 +876,13 @@ namespace toml::impl
|| codepoint == U'}'
|| codepoint == U','
|| codepoint == U'#'
|| is_unicode_line_break(codepoint)
|| is_unicode_whitespace(codepoint)
|| is_non_ascii_line_break(codepoint)
|| is_non_ascii_whitespace(codepoint)
;
}
[[nodiscard]]
TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr bool is_control_character(char32_t codepoint) noexcept
{
return codepoint <= U'\u001F' || codepoint == U'\u007F';
@ -178,7 +890,6 @@ namespace toml::impl
[[nodiscard]]
TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr bool is_nontab_control_character(char32_t codepoint) noexcept
{
return codepoint <= U'\u0008'
@ -188,7 +899,6 @@ namespace toml::impl
[[nodiscard]]
TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr bool is_unicode_surrogate(char32_t codepoint) noexcept
{
return codepoint >= 0xD800u && codepoint <= 0xDFFF;
@ -196,6 +906,9 @@ namespace toml::impl
struct utf8_decoder final
{
// utf8_decoder based on this: https://bjoern.hoehrmann.de/utf-8/decoder/dfa/
// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
uint_least32_t state{};
char32_t codepoint{};
@ -217,19 +930,19 @@ namespace toml::impl
12,36,12,12,12,12,12,12,12,12,12,12
};
[[nodiscard]] TOML_ALWAYS_INLINE
[[nodiscard]]
constexpr bool error() const noexcept
{
return state == uint_least32_t{ 12u };
}
[[nodiscard]] TOML_ALWAYS_INLINE
[[nodiscard]]
constexpr bool has_code_point() const noexcept
{
return state == uint_least32_t{};
}
[[nodiscard]] TOML_ALWAYS_INLINE
[[nodiscard]]
constexpr bool needs_more_input() const noexcept
{
return state > uint_least32_t{} && state != uint_least32_t{ 12u };
@ -251,4 +964,6 @@ namespace toml::impl
}
};
}
TOML_IMPL_NAMESPACE_END
#endif // !DOXYGEN

View File

@ -1,756 +0,0 @@
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
//# Copyright (c) 2019-2020 Mark Gillard <mark.gillard@outlook.com.au>
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT
//#-----
//# this file was generated by generate_unicode_functions.py - do not modify it directly
#pragma once
#include "toml_preprocessor.h"
namespace toml::impl
{
//# Returns true if a codepoint matches any of:
//# 0 - 9, A - F, a - f
[[nodiscard]]
TOML_ATTR(const)
constexpr bool is_hexadecimal_digit(char32_t cp) noexcept
{
using ui64 = std::uint_least64_t;
return cp >= U'0' && cp <= U'f' && (1ull << (static_cast<ui64>(cp) - 0x30ull)) & 0x7E0000007E03FFull;
}
#if TOML_LANG_UNRELEASED // toml/issues/687 (unicode bare keys)
//# Returns true if a codepoint belongs to any of these categories:
//# Ll, Lm, Lo, Lt, Lu
[[nodiscard]]
TOML_ATTR(const)
constexpr bool is_unicode_letter(char32_t cp) noexcept
{
using ui64 = std::uint_least64_t;
using ui32 = std::uint_least32_t;
if (cp < U'\u00AA' || cp > U'\U00031349')
return false;
const auto child_index_0 = (static_cast<ui64>(cp) - 0xAAull) / 0xC4Bull;
if ((1ull << child_index_0) & 0x8A7FFC004001CFA0ull)
return true;
if ((1ull << child_index_0) & 0x26180C0000ull)
return false;
switch (child_index_0)
{
case 0x00: // [0] 00AA - 0CF4
{
if (cp > U'\u0CF2')
return false;
TOML_ASSUME(cp >= U'\u00AA');
constexpr ui64 bitmask_table_1[] =
{
0xFFFFDFFFFFC10801ull, 0xFFFFFFFFFFFFDFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0x07C000FFF0FFFFFFull, 0x0000000000000014ull, 0x0000000000000000ull, 0xFEFFFFF5D02F37C0ull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFEFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00FFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFC09FFFFFFFFFBFull, 0x000000007FFFFFFFull,
0xFFFFFFC000000000ull, 0xFFC00000000001E1ull, 0x00000001FFFFFFFFull, 0xFFFFFFFFFFFFFFB0ull,
0x18000BFFFFFFFFFFull, 0xFFFFFF4000270030ull, 0xFFFFFFF80000003Full, 0x0FFFFFFFFFFFFFFFull,
0xFFFFFFFF00000080ull, 0x44010FFFFFC10C01ull, 0xFFC07FFFFFC00000ull, 0xFFC0000000000001ull,
0x000000003FFFF7FFull, 0xFFFFFFFFFC000000ull, 0x00FFC0400008FFFFull, 0x7FFFFE67F87FFF80ull,
0x00EC00100008F17Full, 0x7FFFFE61F80400C0ull, 0x001780000000DB7Full, 0x7FFFFEEFF8000700ull,
0x00C000400008FB7Full, 0x7FFFFE67F8008000ull, 0x00EC00000008FB7Full, 0xC6358F71FA000080ull,
0x000000400000FFF1ull, 0x7FFFFF77F8000000ull, 0x00C1C0000008FFFFull, 0x7FFFFF77F8400000ull,
0x00D000000008FBFFull, 0x0000000000000180ull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0xAAull) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0xAAull) % 0x40ull));
//# chunk summary: 1922 codepoints from 124 ranges (spanning a search area of 3147)
}
case 0x01: // [1] 0CF5 - 193F
{
if (cp < U'\u0D04' || cp > U'\u191E')
return false;
constexpr ui64 bitmask_table_1[] =
{
0x027FFFFFFFFFDDFFull, 0x0FC0000038070400ull, 0xF2FFBFFFFFC7FFFEull, 0xE000000000000007ull,
0xF000DFFFFFFFFFFFull, 0x6000000000000007ull, 0xF200DFFAFFFFFF7Dull, 0x100000000F000005ull,
0xF000000000000000ull, 0x000001FFFFFFFFEFull, 0x00000000000001F0ull, 0xF000000000000000ull,
0x0800007FFFFFFFFFull, 0x3FFE1C0623C3F000ull, 0xFFFFFFFFF0000400ull, 0xFF7FFFFFFFFFF20Bull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFF3D7F3DFull, 0xD7F3DFFFFFFFF3DFull, 0xFFFFFFFFFFF7FFF3ull,
0xFFFFFFFFFFF3DFFFull, 0xF0000000007FFFFFull, 0xFFFFFFFFF0000FFFull, 0xE3F3FFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xEFFFF9FFFFFFFFFFull, 0xFFFFFFFFF07FFFFFull, 0xF01FE07FFFFFFFFFull,
0xF0003FFFF0003DFFull, 0xF0001DFFF0003FFFull, 0x0000FFFFFFFFFFFFull, 0x0000000001080000ull,
0xFFFFFFFFF0000000ull, 0xF01FFFFFFFFFFFFFull, 0xFFFFF05FFFFFFFF9ull, 0xF003FFFFFFFFFFFFull,
0x0000000007FFFFFFull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0xD04ull) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0xD04ull) % 0x40ull));
//# chunk summary: 2239 codepoints from 83 ranges (spanning a search area of 3147)
}
case 0x02: // [2] 1940 - 258A
{
if (cp < U'\u1950' || cp > U'\u2184')
return false;
constexpr ui64 bitmask_table_1[] =
{
0xFFFF001F3FFFFFFFull, 0x03FFFFFF0FFFFFFFull, 0xFFFF000000000000ull, 0xFFFFFFFFFFFF007Full,
0x000000000000001Full, 0x0000000000800000ull, 0xFFE0000000000000ull, 0x0FE0000FFFFFFFFFull,
0xFFF8000000000000ull, 0xFFFFFC00C001FFFFull, 0xFFFF0000003FFFFFull, 0xE0000000000FFFFFull,
0x01FF3FFFFFFFFC00ull, 0x0000E7FFFFFFFFFFull, 0xFFFF046FDE000000ull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0x0000FFFFFFFFFFFFull, 0xFFFF000000000000ull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0x3F3FFFFFFFFF3F3Full,
0xFFFF3FFFFFFFAAFFull, 0x1FDC5FDFFFFFFFFFull, 0x00001FDC1FFF0FCFull, 0x0000000000000000ull,
0x0000800200000000ull, 0x0000000000001FFFull, 0xFC84000000000000ull, 0x43E0F3FFBD503E2Full,
0x0018000000000000ull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x1950ull) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0x1950ull) % 0x40ull));
//# chunk summary: 1184 codepoints from 59 ranges (spanning a search area of 3147)
}
case 0x03: // [3] 258B - 31D5
{
if (cp < U'\u2C00' || cp > U'\u31BF')
return false;
constexpr ui64 bitmask_table_1[] =
{
0xFFFF7FFFFFFFFFFFull, 0xFFFFFFFF7FFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0x000C781FFFFFFFFFull,
0xFFFF20BFFFFFFFFFull, 0x000080FFFFFFFFFFull, 0x7F7F7F7F007FFFFFull, 0x000000007F7F7F7Full,
0x0000800000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x183E000000000060ull, 0xFFFFFFFFFFFFFFFEull, 0xFFFFFFFEE07FFFFFull, 0xF7FFFFFFFFFFFFFFull,
0xFFFEFFFFFFFFFFE0ull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00007FFFull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x2C00ull) / 0x40ull]
& (0x1ull << (static_cast<ui64>(cp) % 0x40ull));
//# chunk summary: 771 codepoints from 30 ranges (spanning a search area of 3147)
}
case 0x04: return (cp >= U'\u31F0' && cp <= U'\u31FF') || (cp >= U'\u3400' && cp <= U'\u3E20');
case 0x06: return (cp >= U'\u4A6C' && cp <= U'\u4DBE') || (cp >= U'\u4E00' && cp <= U'\u56B6');
case 0x0C: return (cp >= U'\u942E' && cp <= U'\u9FFB') || (cp >= U'\uA000' && cp <= U'\uA078');
case 0x0D: // [13] A079 - ACC3
{
TOML_ASSUME(cp >= U'\uA079' && cp <= U'\uACC3');
constexpr ui64 bitmask_table_1[] =
{
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0x00000000000FFFFFull, 0xFFFFFFFFFF800000ull, 0xFFFFFFFFFFFFFF9Full, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0x0006007FFF8FFFFFull, 0x003FFFFFFFFFFF80ull,
0xFFFFFF9FFFFFFFC0ull, 0x00001FFFFFFFFFFFull, 0xFFFFFE7FC0000000ull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFCFFFFull, 0xF00000000003FE7Full, 0x000003FFFFFBDDFFull, 0x07FFFFFFFFFFFF80ull,
0x07FFFFFFFFFFFE00ull, 0x7E00000000000000ull, 0xFF801FFFFFFE0034ull, 0xFFFFFF8000003FFFull,
0x03FFFFFFFFFFF80Full, 0x007FEF8000400000ull, 0x0000FFFFFFFFFFBEull, 0x3FFFFF800007FB80ull,
0x317FFFFFFFFFFFE2ull, 0x0E03FF9C0000029Full, 0xFFBFBF803F3F3F00ull, 0xFF81FFFBFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0x000003FFFFFFFFFFull, 0xFFFFFFFFFFFFFF80ull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0x00000000000007FFull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0xA079ull) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0xA079ull) % 0x40ull));
//# chunk summary: 2554 codepoints from 52 ranges (spanning a search area of 3147)
}
case 0x11: return (cp >= U'\uD1A5' && cp <= U'\uD7A2') || (cp >= U'\uD7B0' && cp <= U'\uD7C6')
|| (cp >= U'\uD7CB' && cp <= U'\uD7FB');
case 0x14: // [20] F686 - 102D0
{
if (cp < U'\uF900')
return false;
TOML_ASSUME(cp <= U'\U000102D0');
constexpr ui64 bitmask_table_1[] =
{
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFF3FFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0x0000000003FFFFFFull,
0x5F7FFDFFA0F8007Full, 0xFFFFFFFFFFFFFFDBull, 0x0003FFFFFFFFFFFFull, 0xFFFFFFFFFFF80000ull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0x3FFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFF0000ull, 0xFFFFFFFFFFFCFFFFull, 0x0FFF0000000000FFull,
0x0000000000000000ull, 0xFFDF000000000000ull, 0xFFFFFFFFFFFFFFFFull, 0x1FFFFFFFFFFFFFFFull,
0x07FFFFFE00000000ull, 0xFFFFFFC007FFFFFEull, 0x7FFFFFFFFFFFFFFFull, 0x000000001CFCFCFCull,
0xB7FFFF7FFFFFEFFFull, 0x000000003FFF3FFFull, 0xFFFFFFFFFFFFFFFFull, 0x07FFFFFFFFFFFFFFull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0xFFFFFFFF1FFFFFFFull, 0x000000000001FFFFull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0xF900ull) / 0x40ull]
& (0x1ull << (static_cast<ui64>(cp) % 0x40ull));
//# chunk summary: 1710 codepoints from 34 ranges (spanning a search area of 3147)
}
case 0x15: // [21] 102D1 - 10F1B
{
if (cp < U'\U00010300')
return false;
TOML_ASSUME(cp <= U'\U00010F1B');
constexpr ui64 bitmask_table_1[] =
{
0xFFFFE000FFFFFFFFull, 0x003FFFFFFFFF03FDull, 0xFFFFFFFF3FFFFFFFull, 0x000000000000FF0Full,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFF00003FFFFFFFull, 0x0FFFFFFFFF0FFFFFull,
0xFFFF00FFFFFFFFFFull, 0x0000000FFFFFFFFFull, 0x0000000000000000ull, 0x0000000000000000ull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0x007FFFFFFFFFFFFFull, 0x000000FF003FFFFFull, 0x0000000000000000ull, 0x0000000000000000ull,
0x91BFFFFFFFFFFD3Full, 0x007FFFFF003FFFFFull, 0x000000007FFFFFFFull, 0x0037FFFF00000000ull,
0x03FFFFFF003FFFFFull, 0x0000000000000000ull, 0xC0FFFFFFFFFFFFFFull, 0x0000000000000000ull,
0x003FFFFFFEEF0001ull, 0x1FFFFFFF00000000ull, 0x000000001FFFFFFFull, 0x0000001FFFFFFEFFull,
0x003FFFFFFFFFFFFFull, 0x0007FFFF003FFFFFull, 0x000000000003FFFFull, 0x0000000000000000ull,
0xFFFFFFFFFFFFFFFFull, 0x00000000000001FFull, 0x0007FFFFFFFFFFFFull, 0x0007FFFFFFFFFFFFull,
0x0000000FFFFFFFFFull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x000303FFFFFFFFFFull, 0x0000000000000000ull,
0x000000000FFFFFFFull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x10300ull) / 0x40ull]
& (0x1ull << (static_cast<ui64>(cp) % 0x40ull));
//# chunk summary: 1620 codepoints from 48 ranges (spanning a search area of 3147)
}
case 0x16: // [22] 10F1C - 11B66
{
if (cp > U'\U00011AF8')
return false;
TOML_ASSUME(cp >= U'\U00010F1C');
constexpr ui64 bitmask_table_1[] =
{
0x000003FFFFF00801ull, 0x0000000000000000ull, 0x000001FFFFF00000ull, 0xFFFFFF8007FFFFF0ull,
0x000000000FFFFFFFull, 0xFFFFFF8000000000ull, 0xFFF00000000FFFFFull, 0xFFFFFF8000001FFFull,
0xFFF00900000007FFull, 0xFFFFFF80047FFFFFull, 0x400001E0007FFFFFull, 0xFFBFFFF000000001ull,
0x000000000000FFFFull, 0xFFFBD7F000000000ull, 0xFFFFFFFFFFF01FFBull, 0xFF99FE0000000007ull,
0x001000023EDFDFFFull, 0x000000000000003Eull, 0x0000000000000000ull, 0xFFFFFFF000000000ull,
0x0000780001FFFFFFull, 0xFFFFFFF000000038ull, 0x00000B00000FFFFFull, 0x0000000000000000ull,
0x0000000000000000ull, 0xFFFFFFF000000000ull, 0xF00000000007FFFFull, 0xFFFFFFF000000000ull,
0x00000100000FFFFFull, 0xFFFFFFF000000000ull, 0x0000000010007FFFull, 0x7FFFFFF000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0xFFFFFFF000000000ull,
0x000000000000FFFFull, 0x0000000000000000ull, 0xFFFFFFFFFFFFFFF0ull, 0xF6FF27F80000000Full,
0x00000028000FFFFFull, 0x0000000000000000ull, 0x001FFFFFFFFFCFF0ull, 0xFFFF8010000000A0ull,
0x00100000407FFFFFull, 0x00003FFFFFFFFFFFull, 0xFFFFFFF000000002ull, 0x000000001FFFFFFFull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x10F1Cull) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0x10F1Cull) % 0x40ull));
//# chunk summary: 1130 codepoints from 67 ranges (spanning a search area of 3147)
}
case 0x17: // [23] 11B67 - 127B1
{
if (cp < U'\U00011C00' || cp > U'\U00012543')
return false;
constexpr ui64 bitmask_table_1[] =
{
0x00007FFFFFFFFDFFull, 0xFFFC000000000001ull, 0x000000000000FFFFull, 0x0000000000000000ull,
0x0001FFFFFFFFFB7Full, 0xFFFFFDBF00000040ull, 0x00000000010003FFull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0007FFFF00000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0001000000000000ull, 0x0000000000000000ull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0x0000000003FFFFFFull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0x000000000000000Full,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x11C00ull) / 0x40ull]
& (0x1ull << (static_cast<ui64>(cp) % 0x40ull));
//# chunk summary: 1304 codepoints from 16 ranges (spanning a search area of 3147)
}
case 0x18: return cp >= U'\U00013000';
case 0x19: return cp <= U'\U0001342E';
case 0x1A: return cp >= U'\U00014400' && cp <= U'\U00014646';
case 0x1D: // [29] 16529 - 17173
{
if (cp < U'\U00016800')
return false;
TOML_ASSUME(cp <= U'\U00017173');
constexpr ui64 bitmask_table_1[] =
{
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0x01FFFFFFFFFFFFFFull, 0x000000007FFFFFFFull, 0x0000000000000000ull, 0x00003FFFFFFF0000ull,
0x0000FFFFFFFFFFFFull, 0xE0FFFFF80000000Full, 0x000000000000FFFFull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0xFFFFFFFFFFFFFFFFull, 0x0000000000000000ull, 0x0000000000000000ull,
0xFFFFFFFFFFFFFFFFull, 0x00000000000107FFull, 0x00000000FFF80000ull, 0x0000000B00000000ull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0x000FFFFFFFFFFFFFull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x16800ull) / 0x40ull]
& (0x1ull << (static_cast<ui64>(cp) % 0x40ull));
//# chunk summary: 1250 codepoints from 14 ranges (spanning a search area of 3147)
}
case 0x1F: return (cp >= U'\U00017DBF' && cp <= U'\U000187F6') || (cp >= U'\U00018800' && cp <= U'\U00018A09');
case 0x20: return (cp >= U'\U00018A0A' && cp <= U'\U00018CD5') || (cp >= U'\U00018D00' && cp <= U'\U00018D07');
case 0x23: // [35] 1AEEB - 1BB35
{
if (cp < U'\U0001B000' || cp > U'\U0001B2FB')
return false;
constexpr ui64 bitmask_table_1[] =
{
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0x000000007FFFFFFFull, 0xFFFF00F000070000ull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0x0FFFFFFFFFFFFFFFull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x1B000ull) / 0x40ull]
& (0x1ull << (static_cast<ui64>(cp) % 0x40ull));
//# chunk summary: 690 codepoints from 4 ranges (spanning a search area of 3147)
}
case 0x24: // [36] 1BB36 - 1C780
{
if (cp < U'\U0001BC00' || cp > U'\U0001BC99')
return false;
switch ((static_cast<ui64>(cp) - 0x1BC00ull) / 0x40ull)
{
case 0x01: return cp <= U'\U0001BC7C'
&& (1ull << (static_cast<ui64>(cp) - 0x1BC40ull)) & 0x1FFF07FFFFFFFFFFull;
case 0x02: return (1u << (static_cast<ui32>(cp) - 0x1BC80u)) & 0x3FF01FFu;
default: return true;
}
//# chunk summary: 139 codepoints from 4 ranges (spanning a search area of 3147)
}
case 0x26: // [38] 1D3CC - 1E016
{
if (cp < U'\U0001D400' || cp > U'\U0001D7CB')
return false;
constexpr ui64 bitmask_table_1[] =
{
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFDFFFFFull, 0xEBFFDE64DFFFFFFFull, 0xFFFFFFFFFFFFFFEFull,
0x7BFFFFFFDFDFE7BFull, 0xFFFFFFFFFFFDFC5Full, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFF3FFFFFFFFFull, 0xF7FFFFFFF7FFFFFDull,
0xFFDFFFFFFFDFFFFFull, 0xFFFF7FFFFFFF7FFFull, 0xFFFFFDFFFFFFFDFFull, 0x0000000000000FF7ull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x1D400ull) / 0x40ull]
& (0x1ull << (static_cast<ui64>(cp) % 0x40ull));
//# chunk summary: 936 codepoints from 30 ranges (spanning a search area of 3147)
}
case 0x27: // [39] 1E017 - 1EC61
{
if (cp < U'\U0001E100' || cp > U'\U0001E94B')
return false;
constexpr ui64 bitmask_table_1[] =
{
0x3F801FFFFFFFFFFFull, 0x0000000000004000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x00000FFFFFFFFFFFull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0x000000000000001Full,
0xFFFFFFFFFFFFFFFFull, 0x000000000000080Full,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x1E100ull) / 0x40ull]
& (0x1ull << (static_cast<ui64>(cp) % 0x40ull));
//# chunk summary: 363 codepoints from 7 ranges (spanning a search area of 3147)
}
case 0x28: // [40] 1EC62 - 1F8AC
{
if (cp < U'\U0001EE00' || cp > U'\U0001EEBB')
return false;
switch ((static_cast<ui64>(cp) - 0x1EE00ull) / 0x40ull)
{
case 0x00: return cp <= U'\U0001EE3B'
&& (1ull << (static_cast<ui64>(cp) - 0x1EE00ull)) & 0xAF7FE96FFFFFFEFull;
case 0x01: return cp >= U'\U0001EE42' && cp <= U'\U0001EE7E'
&& (1ull << (static_cast<ui64>(cp) - 0x1EE42ull)) & 0x17BDFDE5AAA5BAA1ull;
case 0x02: return (1ull << (static_cast<ui64>(cp) - 0x1EE80ull)) & 0xFFFFBEE0FFFFBFFull;
TOML_NO_DEFAULT_CASE;
}
//# chunk summary: 141 codepoints from 33 ranges (spanning a search area of 3147)
}
case 0x29: return cp >= U'\U00020000';
case 0x37: return (cp >= U'\U0002A4C7' && cp <= U'\U0002A6DC') || (cp >= U'\U0002A700' && cp <= U'\U0002B111');
case 0x38: return (cp >= U'\U0002B112' && cp <= U'\U0002B733') || (cp >= U'\U0002B740' && cp <= U'\U0002B81C')
|| (cp >= U'\U0002B820' && cp <= U'\U0002BD5C');
case 0x3A: return (cp >= U'\U0002C9A8' && cp <= U'\U0002CEA0') || (cp >= U'\U0002CEB0' && cp <= U'\U0002D5F2');
case 0x3C: return cp <= U'\U0002EBDF';
case 0x3D: return cp >= U'\U0002F800' && cp <= U'\U0002FA1D';
case 0x3E: return cp >= U'\U00030000';
TOML_NO_DEFAULT_CASE;
}
//# chunk summary: 131178 codepoints from 620 ranges (spanning a search area of 201376)
}
//# Returns true if a codepoint belongs to any of these categories:
//# Nd, Nl
[[nodiscard]]
TOML_ATTR(const)
constexpr bool is_unicode_number(char32_t cp) noexcept
{
using ui64 = std::uint_least64_t;
if (cp < U'\u0660' || cp > U'\U0001FBF9')
return false;
const auto child_index_0 = (static_cast<ui64>(cp) - 0x660ull) / 0x7D7ull;
if ((1ull << child_index_0) & 0x47FFDFE07FCFFFD0ull)
return false;
switch (child_index_0)
{
case 0x00: // [0] 0660 - 0E36
{
if (cp > U'\u0DEF')
return false;
TOML_ASSUME(cp >= U'\u0660');
constexpr ui64 bitmask_table_1[] =
{
0x00000000000003FFull, 0x0000000000000000ull, 0x0000000003FF0000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x000003FF00000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x000000000000FFC0ull, 0x0000000000000000ull, 0x000000000000FFC0ull, 0x0000000000000000ull,
0x000000000000FFC0ull, 0x0000000000000000ull, 0x000000000000FFC0ull, 0x0000000000000000ull,
0x000000000000FFC0ull, 0x0000000000000000ull, 0x000000000000FFC0ull, 0x0000000000000000ull,
0x000000000000FFC0ull, 0x0000000000000000ull, 0x000000000000FFC0ull, 0x0000000000000000ull,
0x000000000000FFC0ull, 0x0000000000000000ull, 0x000000000000FFC0ull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x660ull) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0x660ull) % 0x40ull));
//# chunk summary: 130 codepoints from 13 ranges (spanning a search area of 2007)
}
case 0x01: // [1] 0E37 - 160D
{
if (cp < U'\u0E50' || cp > U'\u1099')
return false;
constexpr ui64 bitmask_table_1[] =
{
0x00000000000003FFull, 0x0000000000000000ull, 0x00000000000003FFull, 0x0000000003FF0000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x03FF000000000000ull,
0x0000000000000000ull, 0x00000000000003FFull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0xE50ull) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0xE50ull) % 0x40ull));
//# chunk summary: 50 codepoints from 5 ranges (spanning a search area of 2007)
}
case 0x02: // [2] 160E - 1DE4
{
if (cp < U'\u16EE' || cp > U'\u1C59')
return false;
constexpr ui64 bitmask_table_1[] =
{
0x0000000000000007ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0FFC000000000000ull,
0x00000FFC00000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x00000003FF000000ull, 0x0000000000000000ull, 0x00000FFC00000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x00000FFC0FFC0000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x00000FFC00000000ull, 0x0000000000000000ull, 0x0000000000000FFCull,
0x0000000000000000ull, 0x00000FFC0FFC0000ull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x16EEull) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0x16EEull) % 0x40ull));
//# chunk summary: 103 codepoints from 11 ranges (spanning a search area of 2007)
}
case 0x03: return cp >= U'\u2160' && cp <= U'\u2188'
&& (1ull << (static_cast<ui64>(cp) - 0x2160ull)) & 0x1E7FFFFFFFFull;
case 0x05: return cp >= U'\u3007' && cp <= U'\u303A'
&& (1ull << (static_cast<ui64>(cp) - 0x3007ull)) & 0xE0007FC000001ull;
case 0x14: // [20] A32C - AB02
{
if (cp < U'\uA620' || cp > U'\uAA59')
return false;
constexpr ui64 bitmask_table_1[] =
{
0x00000000000003FFull, 0x0000000000000000ull, 0x0000000000000000ull, 0x000000000000FFC0ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x03FF000000000000ull, 0x000003FF00000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x03FF000000000000ull, 0x0000000003FF0000ull,
0x03FF000000000000ull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0xA620ull) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0xA620ull) % 0x40ull));
//# chunk summary: 70 codepoints from 7 ranges (spanning a search area of 2007)
}
case 0x15: return cp >= U'\uABF0' && cp <= U'\uABF9';
case 0x1F: return cp >= U'\uFF10' && cp <= U'\uFF19';
case 0x20: // [32] 10140 - 10916
{
if (cp > U'\U000104A9')
return false;
TOML_ASSUME(cp >= U'\U00010140');
constexpr ui64 bitmask_table_1[] =
{
0x001FFFFFFFFFFFFFull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000402ull, 0x0000000000000000ull, 0x00000000003E0000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x000003FF00000000ull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x10140ull) / 0x40ull]
& (0x1ull << (static_cast<ui64>(cp) % 0x40ull));
//# chunk summary: 70 codepoints from 5 ranges (spanning a search area of 2007)
}
case 0x21: return (cp >= U'\U00010D30' && cp <= U'\U00010D39') || (cp >= U'\U00011066' && cp <= U'\U0001106F');
case 0x22: // [34] 110EE - 118C4
{
if (cp < U'\U000110F0' || cp > U'\U00011739')
return false;
constexpr ui64 bitmask_table_1[] =
{
0x00000000000003FFull, 0x000000000000FFC0ull, 0x0000000000000000ull, 0x000003FF00000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x00000000000003FFull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x000003FF00000000ull, 0x0000000000000000ull, 0x000003FF00000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x000003FF00000000ull, 0x0000000000000000ull, 0x0000000003FF0000ull,
0x0000000000000000ull, 0x00000000000003FFull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x110F0ull) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0x110F0ull) % 0x40ull));
//# chunk summary: 90 codepoints from 9 ranges (spanning a search area of 2007)
}
case 0x23: // [35] 118C5 - 1209B
{
if (cp < U'\U000118E0' || cp > U'\U00011DA9')
return false;
constexpr ui64 bitmask_table_1[] =
{
0x00000000000003FFull, 0x03FF000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x03FF000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x03FF000000000000ull, 0x0000000000000000ull, 0x00000000000003FFull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x118E0ull) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0x118E0ull) % 0x40ull));
//# chunk summary: 50 codepoints from 5 ranges (spanning a search area of 2007)
}
case 0x24: return cp >= U'\U00012400' && cp <= U'\U0001246E';
case 0x2D: return (cp >= U'\U00016A60' && cp <= U'\U00016A69') || (cp >= U'\U00016B50' && cp <= U'\U00016B59');
case 0x3B: return cp >= U'\U0001D7CE' && cp <= U'\U0001D7FF';
case 0x3C: return (cp >= U'\U0001E140' && cp <= U'\U0001E149') || (cp >= U'\U0001E2F0' && cp <= U'\U0001E2F9');
case 0x3D: return cp >= U'\U0001E950' && cp <= U'\U0001E959';
case 0x3F: return cp >= U'\U0001FBF0';
TOML_NO_DEFAULT_CASE;
}
//# chunk summary: 876 codepoints from 72 ranges (spanning a search area of 128410)
}
//# Returns true if a codepoint belongs to any of these categories:
//# Mn, Mc
[[nodiscard]]
TOML_ATTR(const)
constexpr bool is_unicode_combining_mark(char32_t cp) noexcept
{
using ui64 = std::uint_least64_t;
if (cp < U'\u0300' || cp > U'\U000E01EF')
return false;
const auto child_index_0 = (static_cast<ui64>(cp) - 0x300ull) / 0x37FCull;
if ((1ull << child_index_0) & 0x7FFFFFFFFFFFFE02ull)
return false;
switch (child_index_0)
{
case 0x00: // [0] 0300 - 3AFB
{
if (cp > U'\u309A')
return false;
TOML_ASSUME(cp >= U'\u0300');
constexpr ui64 bitmask_table_1[] =
{
0xFFFFFFFFFFFFFFFFull, 0x0000FFFFFFFFFFFFull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x00000000000000F8ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0xBFFFFFFFFFFE0000ull, 0x00000000000000B6ull,
0x0000000007FF0000ull, 0x00010000FFFFF800ull, 0x0000000000000000ull, 0x00003D9F9FC00000ull,
0xFFFF000000020000ull, 0x00000000000007FFull, 0x0001FFC000000000ull, 0x200FF80000000000ull,
0x00003EEFFBC00000ull, 0x000000000E000000ull, 0x0000000000000000ull, 0xFFFFFFFBFFF80000ull,
0xDC0000000000000Full, 0x0000000C00FEFFFFull, 0xD00000000000000Eull, 0x4000000C0080399Full,
0xD00000000000000Eull, 0x0023000000023987ull, 0xD00000000000000Eull, 0xFC00000C00003BBFull,
0xD00000000000000Eull, 0x0000000C00E0399Full, 0xC000000000000004ull, 0x0000000000803DC7ull,
0xC00000000000001Full, 0x0000000C00603DDFull, 0xD00000000000000Eull, 0x0000000C00603DDFull,
0xD80000000000000Full, 0x0000000C00803DDFull, 0x000000000000000Eull, 0x000C0000FF5F8400ull,
0x07F2000000000000ull, 0x0000000000007F80ull, 0x1FF2000000000000ull, 0x0000000000003F00ull,
0xC2A0000003000000ull, 0xFFFE000000000000ull, 0x1FFFFFFFFEFFE0DFull, 0x0000000000000040ull,
0x7FFFF80000000000ull, 0x001E3F9DC3C00000ull, 0x000000003C00BFFCull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x00000000E0000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x001C0000001C0000ull, 0x000C0000000C0000ull, 0xFFF0000000000000ull, 0x00000000200FFFFFull,
0x0000000000003800ull, 0x0000000000000000ull, 0x0000020000000060ull, 0x0000000000000000ull,
0x0FFF0FFF00000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x000000000F800000ull, 0x9FFFFFFF7FE00000ull, 0xBFFF000000000000ull, 0x0000000000000001ull,
0xFFF000000000001Full, 0x000FF8000000001Full, 0x00003FFE00000007ull, 0x000FFFC000000000ull,
0x00FFFFF000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x039021FFFFF70000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0xFBFFFFFFFFFFFFFFull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0001FFE21FFF0000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0003800000000000ull,
0x0000000000000000ull, 0x8000000000000000ull, 0x0000000000000000ull, 0xFFFFFFFF00000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000FC0000000000ull, 0x0000000000000000ull, 0x0000000006000000ull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x300ull) / 0x40ull]
& (0x1ull << (static_cast<ui64>(cp) % 0x40ull));
//# chunk summary: 1106 codepoints from 156 ranges (spanning a search area of 14332)
}
case 0x02: // [2] 72F8 - AAF3
{
if (cp < U'\uA66F' || cp > U'\uAAEF')
return false;
constexpr ui64 bitmask_table_1[] =
{
0x0001800000007FE1ull, 0x0000000000000000ull, 0x0000000000000006ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x21F0000010880000ull, 0x0000000000000000ull,
0x0000000000060000ull, 0xFFFE0000007FFFE0ull, 0x7F80000000010007ull, 0x0000001FFF000000ull,
0x00000000001E0000ull, 0x004000000003FFF0ull, 0xFC00000000000000ull, 0x00000000601000FFull,
0x0000000000007000ull, 0xF00000000005833Aull, 0x0000000000000001ull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0xA66Full) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0xA66Full) % 0x40ull));
//# chunk summary: 137 codepoints from 28 ranges (spanning a search area of 14332)
}
case 0x03: return cp == U'\uAAF5' || cp == U'\uAAF6' || (cp >= U'\uABE3' && cp <= U'\uABEA') || cp == U'\uABEC'
|| cp == U'\uABED';
case 0x04: // [4] E2F0 - 11AEB
{
if (cp < U'\uFB1E' || cp > U'\U00011A99')
return false;
constexpr ui64 bitmask_table_1[] =
{
0x0000000000000001ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0003FFFC00000000ull,
0x000000000003FFFCull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000080000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000004ull,
0x0000000000000000ull, 0x000000001F000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0003C1B800000000ull,
0x000000021C000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000180ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x00000000000003C0ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000006000ull, 0x0000000000000000ull,
0x0007FF0000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000001C00000000ull,
0x000001FFFC000000ull, 0x0000001E00000000ull, 0x000000001FFC0000ull, 0x0000001C00000000ull,
0x00000180007FFE00ull, 0x0000001C00200000ull, 0x00037807FFE00000ull, 0x0000000000000000ull,
0x0000000103FFC000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000003C00001FFEull,
0x0200E67F60000000ull, 0x00000000007C7F30ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x000001FFFF800000ull, 0x0000000000000001ull, 0x0000003FFFFC0000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0xC0000007FCFE0000ull, 0x0000000000000000ull,
0x00000007FFFC0000ull, 0x0000000000000000ull, 0x0000000003FFE000ull, 0x8000000000000000ull,
0x0000000000003FFFull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x000000001FFFC000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x00000035E6FC0000ull, 0x0000000000000000ull, 0xF3F8000000000000ull, 0x00001FF800000047ull,
0x3FF80201EFE00000ull, 0x0FFFF00000000000ull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0xFB1Eull) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0xFB1Eull) % 0x40ull));
//# chunk summary: 402 codepoints from 63 ranges (spanning a search area of 14332)
}
case 0x05: // [5] 11AEC - 152E7
{
if (cp < U'\U00011C2F' || cp > U'\U00011EF6')
return false;
constexpr ui64 bitmask_table_1[] =
{
0x000000000001FEFFull, 0xFDFFFFF800000000ull, 0x00000000000000FFull, 0x0000000000000000ull,
0x00000000017F68FCull, 0x000001F6F8000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x00000000000000F0ull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x11C2Full) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0x11C2Full) % 0x40ull));
//# chunk summary: 85 codepoints from 13 ranges (spanning a search area of 14332)
}
case 0x06: // [6] 152E8 - 18AE3
{
if (cp < U'\U00016AF0' || cp > U'\U00016FF1')
return false;
constexpr ui64 bitmask_table_1[] =
{
0x000000000000001Full, 0x000000000000007Full, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0xFFFFFFFE80000000ull, 0x0000000780FFFFFFull, 0x0010000000000000ull,
0x0000000000000003ull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x16AF0ull) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0x16AF0ull) % 0x40ull));
//# chunk summary: 75 codepoints from 7 ranges (spanning a search area of 14332)
}
case 0x07: return cp >= U'\U0001BC9D' && cp <= U'\U0001BC9E';
case 0x08: // [8] 1C2E0 - 1FADB
{
if (cp < U'\U0001D165' || cp > U'\U0001E94A')
return false;
constexpr ui64 bitmask_table_1[] =
{
0x0000007F3FC03F1Full, 0x00000000000001E0ull, 0x0000000000000000ull, 0x00000000E0000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0xFFFFFFFFF8000000ull, 0xFFFFFFFFFFC3FFFFull,
0xF7C00000800100FFull, 0x00000000000007FFull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0xDFCFFFFBF8000000ull, 0x000000000000003Eull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x000000000003F800ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000780ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull,
0x0000000000000000ull, 0x0003F80000000000ull, 0x0000000000000000ull, 0x0000003F80000000ull,
};
return bitmask_table_1[(static_cast<ui64>(cp) - 0x1D165ull) / 0x40ull]
& (0x1ull << ((static_cast<ui64>(cp) - 0x1D165ull) % 0x40ull));
//# chunk summary: 223 codepoints from 21 ranges (spanning a search area of 14332)
}
case 0x3F: return cp >= U'\U000E0100';
TOML_NO_DEFAULT_CASE;
}
//# chunk summary: 2282 codepoints from 293 ranges (spanning a search area of 917232)
}
#endif // TOML_LANG_UNRELEASED
} // toml::impl

View File

@ -13,10 +13,7 @@
#include "toml_utf8.h"
#include "toml_parse_error.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
namespace toml::impl
TOML_IMPL_NAMESPACE_START
{
template <typename T>
class utf8_byte_stream;
@ -24,7 +21,7 @@ namespace toml::impl
inline constexpr auto utf8_byte_order_mark = "\xEF\xBB\xBF"sv;
template <typename Char>
class utf8_byte_stream<std::basic_string_view<Char>> final
class TOML_API utf8_byte_stream<std::basic_string_view<Char>> final
{
static_assert(sizeof(Char) == 1_sz);
@ -37,7 +34,8 @@ namespace toml::impl
: source{ sv }
{
// trim trailing nulls
size_t actual_len = source.length();
const size_t initial_len = source.length();
size_t actual_len = initial_len;
for (size_t i = actual_len; i --> 0_sz;)
{
if (source[i] != Char{}) // not '\0'
@ -46,27 +44,30 @@ namespace toml::impl
break;
}
}
if (source.length() != actual_len) // not '\0'
if (initial_len != actual_len)
source = source.substr(0_sz, actual_len);
// skip bom
if (source.length() >= 3_sz && memcmp(utf8_byte_order_mark.data(), source.data(), 3_sz) == 0)
if (actual_len >= 3_sz && memcmp(utf8_byte_order_mark.data(), source.data(), 3_sz) == 0)
position += 3_sz;
}
[[nodiscard]] TOML_ALWAYS_INLINE
[[nodiscard]]
TOML_ALWAYS_INLINE
constexpr bool eof() const noexcept
{
return position >= source.length();
}
[[nodiscard]] TOML_ALWAYS_INLINE
[[nodiscard]]
TOML_ALWAYS_INLINE
constexpr bool peek_eof() const noexcept
{
return eof();
}
[[nodiscard]] TOML_ALWAYS_INLINE
[[nodiscard]]
TOML_ALWAYS_INLINE
constexpr bool error() const noexcept
{
return false;
@ -82,7 +83,7 @@ namespace toml::impl
};
template <typename Char>
class utf8_byte_stream<std::basic_istream<Char>> final
class TOML_API utf8_byte_stream<std::basic_istream<Char>> final
{
static_assert(sizeof(Char) == 1_sz);
@ -103,23 +104,26 @@ namespace toml::impl
return;
source->clear();
source->seekg(initial_pos, std::ios::beg);
source->seekg(initial_pos, std::basic_istream<Char>::beg);
}
[[nodiscard]] TOML_ALWAYS_INLINE
[[nodiscard]]
TOML_ALWAYS_INLINE
bool eof() const noexcept
{
return source->eof();
}
[[nodiscard]] TOML_ALWAYS_INLINE
[[nodiscard]]
TOML_ALWAYS_INLINE
bool peek_eof() const
{
using stream_traits = typename std::remove_pointer_t<decltype(source)>::traits_type;
return eof() || source->peek() == stream_traits::eof();
}
[[nodiscard]] TOML_ALWAYS_INLINE
[[nodiscard]]
TOML_ALWAYS_INLINE
bool error() const noexcept
{
return !(*source);
@ -135,75 +139,41 @@ namespace toml::impl
}
};
#if TOML_LARGE_FILES
TOML_ABI_NAMESPACE_START(impl_lf)
#else
TOML_ABI_NAMESPACE_START(impl_sf)
#endif
TOML_ABI_NAMESPACE_BOOL(TOML_LARGE_FILES, lf, sf)
struct utf8_codepoint final
{
char32_t value;
string_char bytes[4];
char bytes[4];
source_position position;
template <typename Char = string_char>
[[nodiscard]]
TOML_ALWAYS_INLINE
std::basic_string_view<Char> as_view() const noexcept
std::string_view as_view() const noexcept
{
static_assert(
sizeof(Char) == 1,
"The string view's underlying character type must be 1 byte in size."
);
return bytes[3]
? std::basic_string_view<Char>{ reinterpret_cast<const Char*>(bytes), 4_sz }
: std::basic_string_view<Char>{ reinterpret_cast<const Char*>(bytes) };
? std::string_view{ bytes, 4_sz }
: std::string_view{ bytes };
}
[[nodiscard]]
TOML_ATTR(pure)
TOML_ALWAYS_INLINE
constexpr operator char32_t& () noexcept
{
return value;
}
[[nodiscard]]
TOML_ATTR(pure)
TOML_ALWAYS_INLINE
constexpr operator const char32_t& () const noexcept
{
return value;
}
[[nodiscard]]
TOML_ATTR(pure)
TOML_ALWAYS_INLINE
constexpr const char32_t& operator* () const noexcept
{
return value;
}
[[nodiscard]] TOML_ATTR(pure) constexpr operator char32_t& () noexcept { return value; }
[[nodiscard]] TOML_ATTR(pure) constexpr operator const char32_t& () const noexcept { return value; }
[[nodiscard]] TOML_ATTR(pure) constexpr const char32_t& operator* () const noexcept { return value; }
};
static_assert(std::is_trivial_v<utf8_codepoint>);
static_assert(std::is_standard_layout_v<utf8_codepoint>);
TOML_ABI_NAMESPACE_END // TOML_LARGE_FILES
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex)
#if TOML_EXCEPTIONS
#define TOML_ERROR_CHECK (void)0
#define TOML_ERROR throw parse_error
TOML_ABI_NAMESPACE_START(impl_ex)
#else
#define TOML_ERROR_CHECK if (err) return nullptr
#define TOML_ERROR err.emplace
TOML_ABI_NAMESPACE_START(impl_noex)
#endif
TOML_PUSH_WARNINGS
TOML_DISABLE_VTABLE_WARNINGS
struct TOML_INTERFACE utf8_reader_interface
{
[[nodiscard]]
@ -226,7 +196,7 @@ namespace toml::impl
};
template <typename T>
class TOML_EMPTY_BASES utf8_reader final
class TOML_EMPTY_BASES TOML_API utf8_reader final
: public utf8_reader_interface
{
private:
@ -329,7 +299,7 @@ namespace toml::impl
TOML_ERROR_CHECK;
auto& current = codepoints[cp_idx % 2_sz];
current.bytes[current_byte_count++] = static_cast<string_char>(next_byte);
current.bytes[current_byte_count++] = static_cast<char>(next_byte);
if (decoder.has_code_point())
{
//store codepoint
@ -369,22 +339,14 @@ namespace toml::impl
template <typename Char>
utf8_reader(std::basic_string_view<Char>, std::string_view) -> utf8_reader<std::basic_string_view<Char>>;
template <typename Char>
utf8_reader(std::basic_istream<Char>&, std::string_view) -> utf8_reader<std::basic_istream<Char>>;
template <typename Char>
utf8_reader(std::basic_string_view<Char>, std::string&&) -> utf8_reader<std::basic_string_view<Char>>;
template <typename Char>
utf8_reader(std::basic_istream<Char>&, std::string_view) -> utf8_reader<std::basic_istream<Char>>;
template <typename Char>
utf8_reader(std::basic_istream<Char>&, std::string&&) -> utf8_reader<std::basic_istream<Char>>;
#if !TOML_EXCEPTIONS
#undef TOML_ERROR_CHECK
#define TOML_ERROR_CHECK if (reader.error()) return nullptr
#endif
class TOML_EMPTY_BASES utf8_buffered_reader final
class TOML_EMPTY_BASES TOML_API utf8_buffered_reader final
: public utf8_reader_interface
{
public:
@ -404,91 +366,16 @@ namespace toml::impl
size_t negative_offset = {};
public:
explicit utf8_buffered_reader(utf8_reader_interface& reader_) noexcept
: reader{ reader_ }
{}
[[nodiscard]]
const source_path_ptr& source_path() const noexcept override
{
return reader.source_path();
}
[[nodiscard]]
const utf8_codepoint* read_next() override
{
TOML_ERROR_CHECK;
if (negative_offset)
{
negative_offset--;
// an entry negative offset of 1 just means "replay the current head"
if (!negative_offset)
return head;
// otherwise step back into the history buffer
else
return history.buffer + ((history.first + history.count - negative_offset) % history_buffer_size);
}
else
{
// first character read from stream
if TOML_UNLIKELY(!history.count && !head)
head = reader.read_next();
// subsequent characters and not eof
else if (head)
{
if TOML_UNLIKELY(history.count < history_buffer_size)
history.buffer[history.count++] = *head;
else
history.buffer[(history.first++ + history_buffer_size) % history_buffer_size] = *head;
head = reader.read_next();
}
return head;
}
}
[[nodiscard]]
const utf8_codepoint* step_back(size_t count) noexcept
{
TOML_ERROR_CHECK;
TOML_ASSERT(history.count);
TOML_ASSERT(negative_offset + count <= history.count);
negative_offset += count;
return negative_offset
? history.buffer + ((history.first + history.count - negative_offset) % history_buffer_size)
: head;
}
[[nodiscard]]
bool peek_eof() const override
{
return reader.peek_eof();
}
explicit utf8_buffered_reader(utf8_reader_interface& reader_) noexcept;
const source_path_ptr& source_path() const noexcept override;
const utf8_codepoint* read_next() override;
const utf8_codepoint* step_back(size_t count) noexcept;
bool peek_eof() const override;
#if !TOML_EXCEPTIONS
[[nodiscard]]
optional<parse_error>&& error() noexcept override
{
return reader.error();
}
optional<parse_error>&& error() noexcept override;
#endif
};
#undef TOML_ERROR_CHECK
#undef TOML_ERROR
TOML_ABI_NAMESPACE_END // TOML_EXCEPTIONS
TOML_POP_WARNINGS
}
TOML_POP_WARNINGS // TOML_DISABLE_PADDING_WARNINGS
TOML_IMPL_NAMESPACE_END

110
deps/toml++/toml_utf8_streams.hpp vendored Normal file
View File

@ -0,0 +1,110 @@
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
//# Copyright (c) 2019-2020 Mark Gillard <mark.gillard@outlook.com.au>
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT
#pragma once
//# {{
#include "toml_preprocessor.h"
#if !TOML_IMPLEMENTATION
#error This is an implementation-only header.
#endif
#if !TOML_PARSER
#error This header cannot not be included when TOML_PARSER is disabled.
#endif
//# }}
#include "toml_utf8_streams.h"
#if !TOML_EXCEPTIONS
#undef TOML_ERROR_CHECK
#define TOML_ERROR_CHECK if (reader.error()) return nullptr
#endif
TOML_IMPL_NAMESPACE_START
{
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex)
TOML_EXTERNAL_LINKAGE
utf8_buffered_reader::utf8_buffered_reader(utf8_reader_interface& reader_) noexcept
: reader{ reader_ }
{}
TOML_EXTERNAL_LINKAGE
const source_path_ptr& utf8_buffered_reader::source_path() const noexcept
{
return reader.source_path();
}
TOML_EXTERNAL_LINKAGE
const utf8_codepoint* utf8_buffered_reader::read_next()
{
TOML_ERROR_CHECK;
if (negative_offset)
{
negative_offset--;
// an entry negative offset of 1 just means "replay the current head"
if (!negative_offset)
return head;
// otherwise step back into the history buffer
else
return history.buffer + ((history.first + history.count - negative_offset) % history_buffer_size);
}
else
{
// first character read from stream
if TOML_UNLIKELY(!history.count && !head)
head = reader.read_next();
// subsequent characters and not eof
else if (head)
{
if TOML_UNLIKELY(history.count < history_buffer_size)
history.buffer[history.count++] = *head;
else
history.buffer[(history.first++ + history_buffer_size) % history_buffer_size] = *head;
head = reader.read_next();
}
return head;
}
}
TOML_EXTERNAL_LINKAGE
const utf8_codepoint* utf8_buffered_reader::step_back(size_t count) noexcept
{
TOML_ERROR_CHECK;
TOML_ASSERT(history.count);
TOML_ASSERT(negative_offset + count <= history.count);
negative_offset += count;
return negative_offset
? history.buffer + ((history.first + history.count - negative_offset) % history_buffer_size)
: head;
}
TOML_EXTERNAL_LINKAGE
bool utf8_buffered_reader::peek_eof() const
{
return reader.peek_eof();
}
#if !TOML_EXCEPTIONS
TOML_EXTERNAL_LINKAGE
optional<parse_error>&& utf8_buffered_reader::error() noexcept
{
return reader.error();
}
#endif
TOML_ABI_NAMESPACE_END // TOML_EXCEPTIONS
}
TOML_IMPL_NAMESPACE_END
#undef TOML_ERROR_CHECK
#undef TOML_ERROR

File diff suppressed because it is too large Load Diff

View File

@ -5,9 +5,9 @@
#pragma once
#define TOML_LIB_MAJOR 1
#define TOML_LIB_MINOR 3
#define TOML_LIB_PATCH 3
#define TOML_LIB_MAJOR 2
#define TOML_LIB_MINOR 2
#define TOML_LIB_PATCH 0
#define TOML_LANG_MAJOR 1
#define TOML_LANG_MINOR 0

View File

@ -165,7 +165,7 @@ void Client::run(server_handle* const localHandle) {
reports.tris_count += pass(buffer, model, glm::vec4(pos, std::get<1>(area)), std::get<2>(area));
};
if (options.culling > 0) {
state.contouring->getModels(draw, player.position, options.camera.far, occlusion, offset, options.voxel_density, true);
state.contouring->getModels(draw, player.position, options.camera.far_dist, occlusion, offset, options.voxel_density, true);
} else {
state.contouring->getModels(draw, frustum, offset, options.voxel_density, true);
}
@ -196,7 +196,7 @@ void Client::run(server_handle* const localHandle) {
reports.tris_count += pass(buffer, model, glm::vec4(pos, std::get<1>(area)), std::get<2>(area));
};
if (options.culling > 0) {
state.contouring->getModels(draw, player.position, options.camera.far, occlusion, offset, options.voxel_density, false);
state.contouring->getModels(draw, player.position, options.camera.far_dist, occlusion, offset, options.voxel_density, false);
} else {
state.contouring->getModels(draw, frustum, offset, options.voxel_density, false);
}

View File

@ -17,7 +17,13 @@ constexpr auto MIN_HEIGHT = 480;
constexpr auto APP_NAME = "Univerxel";
static void glfw_error_callback(int error, const char* description) {
LOG_E("[GLFW] " << error << ": " << description);
}
Window::Window() : ptr(nullptr), targetFPS(60) {
glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit()) {
FATAL("Failed to initialize GLFW");
}
@ -60,10 +66,11 @@ bool Window::create(const CreateInfo &opt) {
LOG_E("Failed to open GLFW window");
return false;
}
glfwMakeContextCurrent(ptr);
if (opt.client.type == CreateInfo::Client::Type::GL)
glfwMakeContextCurrent(ptr);
// Hide the mouse and enable unlimited mouvement
glfwSetInputMode(ptr, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// glfwSetInputMode(ptr, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Set the mouse at the center of the screen
// TODO: move to input manager

View File

@ -6,14 +6,6 @@
typedef struct GLFWwindow GLFWwindow;
typedef void (*GLFWframebuffersizefun)(GLFWwindow*, int, int);
struct windowOptions {
int targetFPS = 60;
int sampling = -1;
bool fullscreen = false;
constexpr int getSamples() const { return sampling > 0 ? (1 << (sampling - 1)) : sampling; }
};
/// GLFW context and window
class Window {
public:
@ -63,3 +55,16 @@ private:
bool fullscreen;
double frameStart;
};
struct windowOptions {
#ifdef _WINDOWS
//NOTE: prefer vsync due to clock inaccuracy
int targetFPS = Window::MIN_FPS - 1;
#else
int targetFPS = 60;
#endif
int sampling = -1;
bool fullscreen = false;
constexpr int getSamples() const { return sampling > 0 ? (1 << (sampling - 1)) : sampling; }
};

View File

@ -55,8 +55,8 @@ public:
contouring = config["contouring"].value_or(std::string(""));
camera.far = config["camera"]["far"].value_or(camera.far);
camera.near = config["camera"]["near"].value_or(camera.near);
camera.far_dist = config["camera"]["far"].value_or(camera.far_dist);
camera.near_dist = config["camera"]["near"].value_or(camera.near_dist);
camera.fov = config["camera"]["fov"].value_or(camera.fov);
control.sensibility = config["control"]["sensibility"].value_or(control.sensibility);
control.speed = config["control"]["speed"].value_or(control.speed);
@ -132,8 +132,8 @@ public:
}));
config.insert_or_assign("contouring", contouring);
config.insert_or_assign("camera", toml::table({
{"far", camera.far},
{"near", camera.near},
{"far", camera.far_dist},
{"near", camera.near_dist},
{"fov", camera.fov}
}));
config.insert_or_assign("control", toml::table({

View File

@ -39,7 +39,7 @@ namespace contouring {
virtual void onEntityUnload(size_t id) = 0;
/// Get options
virtual std::string getOptions() const = 0;
/// Get camera recommended far range
/// Get camera recommended far_dist range
virtual std::pair<float, float> getFarRange() const = 0;
/// Get pending elements
@ -53,7 +53,7 @@ namespace contouring {
virtual void getModels(draw_call draw, const std::optional<geometry::Frustum>& frustum, const glm::llvec3& offset, int density, bool solid) = 0;
/// Get buffers hitting occlusion rays with model matrices
/// @note buffers invalidated after update
virtual void getModels(draw_call draw, const glm::ifvec3 &from, float far, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density, bool solid) = 0;
virtual void getModels(draw_call draw, const glm::ifvec3 &from, float far_dist, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density, bool solid) = 0;
/// Get buffer corresponding to entity idx
virtual render::Model* getEntityModel(size_t) = 0;

View File

@ -42,7 +42,7 @@ namespace contouring {
loadedLevels.push_back(LEVELS[i]);
}
for (size_t i = 1; i <= std::max<uint>(1, std::thread::hardware_concurrency() / 2 - 1); i++) {
for (size_t i = 1; i <= std::max<size_t>(1, std::thread::hardware_concurrency() / 2 - 1); i++) {
workers.emplace_back([&] {
#if TRACY_ENABLE
tracy::SetThreadName("Contouring");
@ -52,7 +52,7 @@ namespace contouring {
if (entity_area_job_t job; entityLoadQueue.pop(job)) {
ZoneScopedN("Entity");
render::Model::Data data;
typeof(render::Model::Data::indices) idx;
render::Model::Data::indices_t idx;
for (uint8_t x = 0; x < job.size.x; x++) {
for (uint8_t y = 0; y < job.size.y; y++) {
for (uint8_t z = 0; z < job.size.z; z++) {
@ -302,7 +302,7 @@ namespace contouring {
}
}
void FlatDualMC::render(const surrounding::corners &surrounding, typeof(render::Model::Data::indices) &out, std::vector<render::VertexData> &tmp, Layer layer) const {
void FlatDualMC::render(const surrounding::corners &surrounding, render::Model::Data::indices_t &out, std::vector<render::VertexData> &tmp, Layer layer) const {
const int SIZE = CHUNK_LENGTH + 3;
std::array<dualmc::DualMC<float>::Point, SIZE * SIZE * SIZE> grid;
{
@ -338,13 +338,13 @@ namespace contouring {
std::vector<dualmc::Tri> dmc_tris;
dualmc::DualMC<float> builder;
builder.buildTris(&grid.front(), SIZE, SIZE, SIZE, iso, world::materials::textures_map.cbegin(), world::materials::roughness.cbegin(),
builder.buildTris(&grid.front(), SIZE, SIZE, SIZE, iso, world::materials::textures_map.data(), world::materials::roughness.data(),
manifold, dmc_vertices, dmc_tris);
tmp.clear();
tmp.reserve(dmc_vertices.size());
constexpr auto HALF_MANTISSA = 10;
std::transform(dmc_vertices.begin(), dmc_vertices.end(), std::back_inserter(tmp), [](const dualmc::Vertex &v) {
constexpr auto HALF_MANTISSA = 10;
return render::VertexData(glm::vec3(meshopt_quantizeFloat(v.x, HALF_MANTISSA),meshopt_quantizeFloat(v.y, HALF_MANTISSA),
meshopt_quantizeFloat(v.z, HALF_MANTISSA)), v.w, glm::vec3(0));
});
@ -395,10 +395,10 @@ namespace contouring {
}}
}
void FlatDualMC::getModels(draw_call out, const glm::ifvec3& from, float far, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density, bool solid) {
void FlatDualMC::getModels(draw_call out, const glm::ifvec3& from, float far_dist, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density, bool solid) {
const auto scaling = glm::scale(glm::mat4(1), glm::vec3(1.f / density));
const auto start = glm::ifvec3(glm::divide(from.as_voxel(density)));
const auto dist = far * density / CHUNK_LENGTH;
const auto dist = far_dist * density / CHUNK_LENGTH;
for (const auto [_, area] : buffers) {
const auto area_offset = glm::divide(std::get<0>(area.first).as_voxel());
robin_hood::unordered_set<chunk_pos> done;

View File

@ -43,7 +43,7 @@ namespace contouring {
void getModels(draw_call draw, const std::optional<geometry::Frustum> &frustum, const glm::llvec3 &offset, int density, bool solid) override;
/// Get buffers hitting occlusion rays with model matrices
/// @note buffers invalidated after update
void getModels(draw_call draw, const glm::ifvec3 &from, float far, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density, bool solid) override;
void getModels(draw_call draw, const glm::ifvec3 &from, float far_dist, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density, bool solid) override;
render::Model* getEntityModel(size_t) override;
@ -64,8 +64,8 @@ namespace contouring {
void enqueue(const area_<chunk_pos> &, const chunk_pos &offset, const world::ChunkContainer &);
ushort loadDistance = 3;
ushort keepDistance = 4;
uint16_t loadDistance = 3;
uint16_t keepDistance = 4;
bool transparency = false;
float iso = .1f;
bool manifold = true;
@ -85,7 +85,7 @@ namespace contouring {
return static_cast<int>(a) & static_cast<int>(b);
}
void render(const surrounding::corners &surrounding, typeof(render::Model::Data::indices)& idx, std::vector<render::VertexData>& ver, Layer layer) const;
void render(const surrounding::corners &surrounding, render::Model::Data::indices_t& idx, std::vector<render::VertexData>& ver, Layer layer) const;
void render(const surrounding::corners &surrounding, render::LodModel::LodData& out, std::vector<render::VertexData>& tmp, Layer layer) const;
};
}

View File

@ -21,7 +21,7 @@ namespace dualmc {
typedef float VertexComponentsType;
typedef uint PropertyType;
typedef uint32_t PropertyType;
typedef uint32_t QuadIndexType;
typedef uint32_t TriIndexType;
@ -37,7 +37,10 @@ struct Vertex {
Vertex(Vertex const & v);
// components
VertexComponentsType x,y,z;
VertexComponentsType x;
VertexComponentsType y;
VertexComponentsType z;
// texture
PropertyType w;
};
@ -51,7 +54,9 @@ struct Tri {
Tri(TriIndexType i0, TriIndexType i1, TriIndexType i2);
// tri indices
TriIndexType i0, i1, i2;
TriIndexType i0;
TriIndexType i1;
TriIndexType i2;
};
@ -101,7 +106,7 @@ public:
Point const *data,
int32_t const dimX, int32_t const dimY, int32_t const dimZ,
VolumeDataType const iso,
ushort const *textures_map,
uint16_t const *textures_map,
float const *roughness,
bool const generateManifold,
std::vector<Vertex> &vertices,
@ -188,7 +193,7 @@ protected:
Point const *data;
/// point to vertex property table
ushort const *textures_map;
uint16_t const *textures_map;
/// property roughness table
float const *roughness;
@ -543,7 +548,7 @@ void DualMC<T>::buildTris(
Point const * data,
int32_t const dimX, int32_t const dimY, int32_t const dimZ,
VolumeDataType const iso,
ushort const * textures_map,
uint16_t const * textures_map,
float const * roughness,
bool const generateManifold,
std::vector<Vertex> & vertices,

View File

@ -1,6 +1,8 @@
#pragma once
#include "../../core/world/forward.h"
#include <memory>
#include <array>
namespace contouring::surrounding {
typedef std::array<std::shared_ptr<const world::client::EdittableChunk>, 8> corners;

View File

@ -9,7 +9,7 @@ Camera::Camera(const Controllable* origin, const Camera::options& opt): origin(o
Camera::~Camera() { }
void Camera::updateProjection() {
ProjectionMatrix = glm::perspective(o.fov, Window::RATIO, o.near, o.far);
ProjectionMatrix = glm::perspective(o.fov, Window::RATIO, o.near_dist, o.far_dist);
}
void Camera::update() {

View File

@ -9,8 +9,8 @@ class Camera {
public:
struct options {
float fov = glm::radians(70.f);
float near = 0.1;
float far = 64;
float near_dist = 0.1;
float far_dist = 64;
};
Camera(const Controllable*, const options&);
@ -26,11 +26,11 @@ public:
}
inline geometry::Frustum getFrustum() const { return geometry::Frustum(ViewMatrix, ProjectionMatrix); }
inline geometry::Ray getRay() const { return geometry::Ray(origin->position, origin->getDirection(), o.far); }
inline geometry::Ray getRay() const { return geometry::Ray(origin->position, origin->getDirection(), o.far_dist); }
constexpr glm::mat4 getViewMatrix() const { return ViewMatrix; }
constexpr glm::mat4 getProjectionMatrix() const { return ProjectionMatrix; }
constexpr float getDepth() const { return o.far; }
constexpr float getDepth() const { return o.far_dist; }
private:
const Controllable* origin;

View File

@ -17,8 +17,8 @@ namespace net::client {
}
}
Client::Client(const address& ct,
std::function<bool(const data::out_view&, PacketFlags)> onPacket):
Client::Client(const net::address& ct,
std::function<bool(const data::out_view&, net::PacketFlags)> onPacket):
Context(nullptr, nullptr), Connection(nullptr, true, queue::count), onPacket(onPacket)
{
const char *sni = NULL;

View File

@ -89,7 +89,7 @@ public:
virtual void setClearColor(glm::vec4) = 0;
virtual void reloadShaders(const passOptions &) = 0;
virtual void reloadTextures(const std::string &, float mipMapLOD, float anisotropy) = 0;
virtual void reloadTextures(const std::string &, float mipMapLOD, int anisotropy) = 0;
virtual void setFillMode(bool wireframe) = 0;
virtual void setVSync(bool vSync) = 0;

View File

@ -20,7 +20,7 @@ UI::UI() {
for(auto file: std::filesystem::directory_iterator("content/textures/")) {
if(file.is_directory() && file.path().filename() != "ui")
texturePacks.push_back(file.path().filename());
texturePacks.push_back(file.path().filename().string());
}
}
UI::~UI() {
@ -76,6 +76,10 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons
if (ImGui::SliderInt("FPS", &options.window.targetFPS, Window::MIN_FPS-1, Window::MAX_FPS+1, options.window.targetFPS > Window::MIN_FPS ? (options.window.targetFPS < Window::MAX_FPS ? "%d" : "UNLIMITED") : "VSYNC")){
actions |= Actions::FPS;
}
#ifdef _WINDOWS
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Due to windows clock inaccuracy prefer vsync or unlimited.");
#endif
if (ImGui::Checkbox("Fullscreen", &options.window.fullscreen)){
actions |= Actions::FullScreen;
@ -187,17 +191,17 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons
{
bool changePerspective = false;
changePerspective |= ImGui::SliderAngle("FoV", &options.camera.fov, 30, 110);
changePerspective |= ImGui::SliderFloat("Near", &options.camera.near, 0.01, 10);
changePerspective |= ImGui::SliderFloat("Far", &options.camera.far, farRange.first / options.voxel_density, farRange.second / options.voxel_density);
changePerspective |= ImGui::SliderFloat("Near", &options.camera.near_dist, 0.01, 10);
changePerspective |= ImGui::SliderFloat("Far", &options.camera.far_dist, farRange.first / options.voxel_density, farRange.second / options.voxel_density);
if(changePerspective) {
actions |= Actions::Camera;
}
}
ImGui::End();
}
const auto far = std::clamp(options.camera.far, farRange.first / options.voxel_density, farRange.second / options.voxel_density);
if(far != options.camera.far) {
options.camera.far = far;
const auto far_dist = std::clamp(options.camera.far_dist, farRange.first / options.voxel_density, farRange.second / options.voxel_density);
if(far_dist != options.camera.far_dist) {
options.camera.far_dist = far_dist;
actions |= Actions::Camera;
}
}

View File

@ -9,6 +9,7 @@ std::unique_ptr<TextureArray> (*TextureArray::loadFunc)(const std::vector<std::s
#include <stdio.h>
#include <string.h>
#include <string>
#include <algorithm>
#define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII
#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
@ -66,7 +67,7 @@ std::optional<Image::properties> Image::Read(const std::string& imagepath, std::
return {};
}
//WONT-FIX: miplevels with size < block size (2 last) are corrupted
const uint maxMipmapLevels = 1 + std::floor(std::log2(std::max(info.size.height, info.size.width))) - 2;
const uint32_t maxMipmapLevels = 1 + std::floor(std::log2(std::max(info.size.height, info.size.width))) - 2;
info.mipmapLevels = std::min(maxMipmapLevels, info.mipmapLevels);
return info;

View File

@ -75,7 +75,8 @@ void indexVBO(const std::vector<PackedVertexData> &in_vertices, std::vector<glm:
std::map<PackedVertexData, glm::u16> VertexToOutIndex;
auto getSimilarVertexIndex_fast = [&] (const PackedVertexData &packed, glm::u16 &out) {
if (auto it = VertexToOutIndex.find(packed); it == VertexToOutIndex.end()) {
auto it = VertexToOutIndex.find(packed);
if (it == VertexToOutIndex.end()) {
return false;
}else{
out = it->second;
@ -85,7 +86,8 @@ void indexVBO(const std::vector<PackedVertexData> &in_vertices, std::vector<glm:
out_indices.reserve(in_vertices.size());
for (const auto& vertex: in_vertices) {
if (glm::u16 index; getSimilarVertexIndex_fast(vertex, index)) {
glm::u16 index;
if (getSimilarVertexIndex_fast(vertex, index)) {
out_indices.push_back(index);
} else {
out_vertices.push_back(vertex);

View File

@ -64,11 +64,12 @@ public:
/// Preindexed buffer data
struct Data {
std::vector<glm::u16> indices;
using indices_t = std::vector<glm::u16>;
indices_t indices;
std::vector<PackedVertexData> vertices;
Data() { }
Data(const std::vector<PackedVertexData> &vertices, const std::vector<glm::u16> &indices);
Data(const std::vector<PackedVertexData> &vertices, const indices_t &indices);
Data(const std::vector<PackedVertexData> &vertices) { index(vertices); }
Data(std::istream &in);

View File

@ -12,12 +12,16 @@
using namespace render::gl;
constexpr auto GL_MAJOR = 4;
#if GL_OLD
constexpr auto GL_MINOR = 2;
#else
constexpr auto GL_MINOR = 6;
#endif
#define CONTENT_DIR "content/"
#define TEXTURES_DIR CONTENT_DIR "textures/"
Renderer::Renderer(const renderOptions& options):
Renderer::Renderer(const render::renderOptions& options):
IndicatorCubeBuffer(Shape::LINE_CUBE), IndicatorSphereBuffer(Shape::LINE_SPHERE)
{
glGenVertexArrays(1, &VertexArrayID);
@ -43,7 +47,7 @@ void framebuffer_size_callback(GLFWwindow *, int width, int height) {
glViewport(0, 0, width, height);
}
bool Renderer::Load(Window& window, const renderOptions& opt, const windowOptions& windOpt) {
bool Renderer::Load(Window& window, const render::renderOptions& opt, const windowOptions& windOpt) {
Window::CreateInfo windowInfo;
windowInfo.pfnResize = framebuffer_size_callback;
windowInfo.client = {Window::CreateInfo::Client::Type::GL, GL_MAJOR, GL_MINOR};
@ -74,7 +78,6 @@ bool Renderer::Load(Window& window, const renderOptions& opt, const windowOption
glCullFace(GL_BACK);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
GLint smp;
glGetIntegerv(GL_SAMPLES, &smp);
@ -105,6 +108,8 @@ void Renderer::beginFrame() {
}
std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> Renderer::beginWorldPass(bool solid) {
if (!solid)
glEnable(GL_BLEND);
WorldPass->useIt();
WorldPass->start(this);
return [&](render::LodModel *const buf, glm::mat4 model, glm::vec4 sph, float curv) {
@ -133,6 +138,7 @@ std::function<size_t(glm::mat4, world::action::Shape, glm::vec4)> Renderer::begi
void Renderer::postProcess() {
glDisable(GL_FRAMEBUFFER_SRGB);
glDisable(GL_BLEND);
if(SkyEnable) {
SkyPass->draw(this);
}
@ -146,15 +152,10 @@ void Renderer::swapBuffer(Window& w) {
}
void Renderer::reloadShaders(const pass::VoxelProgram::options& options) {
if (options.transparency) {
glEnable(GL_BLEND);
} else {
glDisable(GL_BLEND);
}
WorldPass = std::make_unique<pass::WorldProgram>(options);
EntityPass = std::make_unique<pass::EntityProgram>(options);
}
void Renderer::reloadTextures(const std::string& texturePath, float mipMapLOD, float anisotropy) {
void Renderer::reloadTextures(const std::string& texturePath, float mipMapLOD, int anisotropy) {
unloadTextures();
loadTextures(texturePath, mipMapLOD, anisotropy);
}
@ -164,7 +165,7 @@ void Renderer::unloadTextures() {
NormalAtlas.reset();
TextureAtlas.reset();
}
void Renderer::loadTextures(const std::string& texturePath, float mipMapLOD, float anisotropy) {
void Renderer::loadTextures(const std::string& texturePath, float mipMapLOD, int anisotropy) {
std::vector<std::string> terrainTextures;
auto makePaths = [&](const std::string& suffix) {
terrainTextures.clear();

View File

@ -56,7 +56,7 @@ public:
/// Apply camera matrices
void lookFrom(const Camera&) override;
void reloadShaders(const pass::VoxelProgram::options &) override;
void reloadTextures(const std::string &, float mipMapLOD, float anisotropy) override;
void reloadTextures(const std::string &, float mipMapLOD, int anisotropy) override;
void setFillMode(bool wireframe) override;
void setVSync(bool vSync) override;
@ -87,7 +87,7 @@ private:
/// Draw skybox
bool SkyEnable;
void loadTextures(const std::string &, float mipMapLOD, float anisotropy);
void loadTextures(const std::string &, float mipMapLOD, int anisotropy);
void unloadTextures();
};
}

View File

@ -2,6 +2,7 @@
#include "../../../../core/utils/logger.hpp"
#include <algorithm>
#include <string>
#include <array>
using namespace render::gl;
@ -75,7 +76,9 @@ void applySampler(GLuint textureID, const Texture::sampling& props) {
glTextureParameteri(textureID, GL_TEXTURE_MAG_FILTER, getFilter(props.magLinear, props.mipmap));
glTextureParameteri(textureID, GL_TEXTURE_MIN_FILTER, getFilter(props.minLinear, props.mipmap));
glTextureParameterf(textureID, GL_TEXTURE_LOD_BIAS, props.mipmapLod);
#if !GL_OLD
glTextureParameterf(textureID, GL_TEXTURE_MAX_ANISOTROPY, props.anisotropy);
#endif
glTextureParameteri(textureID, GL_TEXTURE_WRAP_S, wrap);
glTextureParameteri(textureID, GL_TEXTURE_WRAP_T, wrap);
glTextureParameteri(textureID, GL_TEXTURE_WRAP_R, wrap);
@ -116,7 +119,7 @@ std::unique_ptr<TextureCube> TextureCube::LoadFromFiles(const std::array<std::st
glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &textureID);
glTextureStorage2D(textureID, 1, format, header.size.width, header.size.height);
ushort layer = 0;
uint16_t layer = 0;
for (auto imagepath = paths.begin(); imagepath != paths.end(); ++imagepath, ++layer) {
data.clear();
if (!render::Image::Read(*imagepath, data).has_value()) {
@ -163,7 +166,7 @@ std::unique_ptr<TextureArray> TextureArray::LoadFromFiles(const std::vector<std:
glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &textureID);
glTextureStorage3D(textureID, header.mipmapLevels, format, header.size.width, header.size.height, paths.size());
ushort layer = 0;
uint16_t layer = 0;
for (auto imagepath = paths.begin(); imagepath != paths.end(); ++imagepath, ++layer) {
data.clear();
if (!render::Image::Read(*imagepath, data).has_value()) {
@ -172,7 +175,7 @@ std::unique_ptr<TextureArray> TextureArray::LoadFromFiles(const std::vector<std:
GLuint subTextureID = createImage(req, data);
auto width = header.size.width;
auto height = header.size.height;
for (uint level = 0; level < header.mipmapLevels; level++) {
for (uint32_t level = 0; level < header.mipmapLevels; level++) {
glCopyImageSubData(subTextureID, GL_TEXTURE_2D, level, 0, 0, 0, textureID, GL_TEXTURE_2D_ARRAY, level, 0, 0, layer, width, height, 1);
width /= 2;
height /= 2;

View File

@ -314,16 +314,16 @@ std::optional<uint32_t> Allocator::findMemory(uint32_t typeFilter, VkMemoryPrope
return {};
}
void memory::area::write(const void* data, size_t data_size, size_t write_offset) {
void render::vk::memory::area::write(const void* data, VkDeviceSize data_size, VkDeviceSize write_offset) {
assert(ptr != nullptr && size >= write_offset + data_size);
memcpy(static_cast<uint8_t*>(ptr) + write_offset, data, data_size);
}
void memory::area::read(void* data, size_t data_size, size_t read_offset) {
void render::vk::memory::area::read(void* data, VkDeviceSize data_size, VkDeviceSize read_offset) {
assert(ptr != nullptr && size >= read_offset + data_size);
memcpy(data, static_cast<uint8_t*>(ptr) + read_offset, data_size);
}
void memory::Deleter::operator()(memory::area* area) {
void render::vk::memory::Deleter::operator()(render::vk::memory::area* area) {
assert(area != nullptr && "Deleting null area");
if(owner != nullptr) {
for (auto it = owner->areas.begin(); it != owner->areas.end(); ++it) {

View File

@ -10,7 +10,7 @@ using namespace render::vk;
#define CONTENT_DIR "content/"
#define TEXTURES_DIR CONTENT_DIR "textures/"
CommandCenter::CommandCenter(VkDevice device, const PhysicalDeviceInfo &info, const renderOptions &opt): device(device) {
CommandCenter::CommandCenter(VkDevice device, const PhysicalDeviceInfo &info, const render::renderOptions &opt): device(device) {
{ // Graphics command pool
vkGetDeviceQueue(device, info.queueIndices.graphicsFamily.value(), 0, &graphicsQueue);
VkCommandPoolCreateInfo poolInfo{};

View File

@ -10,7 +10,7 @@
using namespace render::vk;
Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const renderOptions &options): device(device) {
Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render::renderOptions &options): device(device) {
const auto hasSamples = info.samples > 1;
{ // Render pass
VkAttachmentDescription colorAttachment{};

View File

@ -6,7 +6,7 @@ namespace render::vk {
struct Subpass {
VkShaderModule vsShader;
VkShaderModule gsShader = nullptr;
VkShaderModule gsShader = NULL;
VkShaderModule fsShader;
VkPipelineLayout layout;
VkPipeline pipeline;

View File

@ -30,7 +30,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debugValidationCallback(
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
void *pUserData);
Renderer::Renderer(VkInstance instance, VkDevice device, const PhysicalDeviceInfo& info, const renderOptions& opt):
Renderer::Renderer(VkInstance instance, VkDevice device, const PhysicalDeviceInfo& info, const render::renderOptions& opt):
options(opt), instance(instance), surface(info.surface), device(device),
physicalInfo(std::make_unique<PhysicalDeviceInfo>(info)) {
if constexpr(VALIDATION_LAYER) {
@ -163,7 +163,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debugValidationCallback(VkDebugUtilsMessageSeveri
return VK_FALSE;
}
bool Renderer::Load(Window& window, const renderOptions& opt, const windowOptions& windOpt) {
bool Renderer::Load(Window& window, const render::renderOptions& opt, const windowOptions& windOpt) {
Window::CreateInfo windowInfo;
windowInfo.pfnResize = on_resize_callback;
windowInfo.client = {Window::CreateInfo::Client::Type::VK, 0, 0};
@ -297,9 +297,9 @@ bool Renderer::Load(Window& window, const renderOptions& opt, const windowOption
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
uint bestScore = 0;
uint32_t bestScore = 0;
for(const auto& device: devices) {
uint score = 1;
uint32_t score = 1;
auto infos = PhysicalDeviceInfo(window.getPtr(), device, surface, windOpt.getSamples(), windOpt.targetFPS < Window::MIN_FPS);
{
@ -517,11 +517,11 @@ void Renderer::swapBuffer(Window&) {
vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
}
void Renderer::reloadShaders(const passOptions& opt) {
void Renderer::reloadShaders(const render::passOptions& opt) {
options.voxel = opt;
recreateSwapChain();
}
void Renderer::reloadTextures(const std::string& textures, float mipmap, float anisotropy) {
void Renderer::reloadTextures(const std::string& textures, float mipmap, int anisotropy) {
vkDeviceWaitIdle(device);
commandCenter->free();
commandCenter->loadAtlases(textures, anisotropy, mipmap);

View File

@ -35,7 +35,7 @@ public:
/// Apply camera matrices
void lookFrom(const Camera &) override;
void reloadShaders(const passOptions &) override;
void reloadTextures(const std::string &, float mipMapLOD, float anisotropy) override;
void reloadTextures(const std::string &, float mipMapLOD, int anisotropy) override;
void setFillMode(bool wireframe) override;
void setVSync(bool vSync) override;

View File

@ -1,6 +1,7 @@
#include "Buffers.hpp"
#include "../Allocator.hpp"
#include "../../../../core/utils/logger.hpp"
#include <algorithm>
using namespace render::vk;
@ -110,7 +111,7 @@ memory::ptr render::vk::createBuffers(const std::vector<Buffer::requirement>& re
VkDeviceSize stagingSize = 0;
for (auto& requirement: requirements)
if (requirement.view)
stagingSize = std::max(stagingSize, requirement.size);
stagingSize = std::max<VkDeviceSize>(stagingSize, requirement.size);
// Copy views
// MAYBE: allow single copy
@ -141,15 +142,15 @@ memory::ptr render::vk::createBuffers(const std::vector<Buffer::requirement>& re
void Buffer::MakeDefault() { }
std::unique_ptr<WritableBuffer> WritableBuffer::Create(size_t size, Usage usage, const data_view write) {
std::unique_ptr<WritableBuffer> WritableBuffer::Create(size_t size, Usage usage, const render::data_view write) {
vk::Buffer::info tmp;
auto mem = createBuffer(size, static_cast<int>(usage), memory::HOST_EASILY_WRITABLE, write, tmp);
return std::unique_ptr<WritableBuffer>(new WritableBuffer(tmp.ref, std::move(mem), tmp.offset));
}
void WritableBuffer::write(const data_view view, size_t offset) {
void WritableBuffer::write(const render::data_view view, size_t offset) {
memory->write(view.ptr, view.size, memOffset + offset);
}
void WritableBuffer::read(data_ref ref, size_t offset) {
void WritableBuffer::read(render::data_ref ref, size_t offset) {
memory->read(ref.ptr, ref.size, memOffset + offset);
}
@ -172,7 +173,7 @@ void ShortIndexedVertexBuffer::ClearUnused(uint32_t image) {
}
}
std::unique_ptr<ShortIndexedVertexBuffer> ShortIndexedVertexBuffer::Create(const data_view vertices, const data_view indices) {
std::unique_ptr<ShortIndexedVertexBuffer> ShortIndexedVertexBuffer::Create(const render::data_view vertices, const render::data_view indices) {
std::vector<vk::Buffer::info> tmp;
auto mem = createBuffers({{vertices.size, Usage::VERTEX, vertices}, {indices.size, Usage::INDEX, indices}}, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, tmp);
return std::unique_ptr<ShortIndexedVertexBuffer>(new ShortIndexedVertexBuffer(tmp.at(0).ref, tmp.at(1).ref, std::move(mem)));
@ -193,6 +194,6 @@ void BufferGroup::free() {
refs.clear();
memory = memory::GetNull();
}
void BufferGroup::write(size_t i, const data_view view) {
void BufferGroup::write(size_t i, const render::data_view view) {
memory->write(view.ptr, view.size, refs.at(i).offset);
}

View File

@ -16,7 +16,7 @@ public:
static void MakeDefault();
struct info {
VkBuffer ref = nullptr;
VkBuffer ref = NULL;
VkDeviceSize offset = 0;
};

View File

@ -14,8 +14,8 @@ public:
static void MakeDefault();
struct info {
VkImage ref = nullptr;
VkImageView view = nullptr;
VkImage ref = NULL;
VkImageView view = NULL;
VkDeviceSize offset = 0;
};

View File

@ -1,6 +1,7 @@
#pragma once
#include "../forward.hpp"
#include <memory>
#include <array>
namespace render::vk { struct Allocation; }
namespace render::vk::memory {

View File

@ -10,6 +10,7 @@
#include "../../core/utils/logger.hpp"
#include "Chunk.hpp"
#include <random>
#include <algorithm>
using namespace world::client;
@ -31,7 +32,7 @@ void DistantUniverse::update(voxel_pos pos, float deltaTime) {
{ // Update alive areas
ZoneScopedN("World");
auto rng = std::mt19937(std::rand());
const auto contouringThreshold = rng.max() / (1 + contouring->getQueueSize());
const auto contouringThreshold = UINT32_MAX / (1 + contouring->getQueueSize());
for (auto& area: areas) {
ZoneScopedN("Area");
const bool chunkChangeArea = (false && area.second->move(glm::vec3(deltaTime))) || chunkChange; // TODO: area.velocity
@ -59,7 +60,7 @@ void DistantUniverse::update(voxel_pos pos, float deltaTime) {
std::vector<long> missingDist;
const auto cl_area = std::dynamic_pointer_cast<Area>(area.second);
//TODO: use easy sphere fill
const int queryDistance = std::min(options.loadDistance, serverDistance);
const auto queryDistance = std::min<int>(options.loadDistance, serverDistance);
for (int x = -queryDistance; x <= queryDistance; x++) {
for (int y = -queryDistance; y <= queryDistance; y++) {
for (int z = -queryDistance; z <= queryDistance; z++) {
@ -225,8 +226,8 @@ bool DistantUniverse::onPacket(const data::out_view& buf, net::PacketFlags) {
}
// MAYBE: use Voxel swag bit to flag full void/air chunks to avoiding MISSING_CHUNKS
// MAYBE: then create virtual or non chunk of single material
ushort full = 0;
ushort total = 0;
uint16_t full = 0;
uint16_t total = 0;
while (!packet.isFull()) {
region_chunk_pos cpos;
Voxel voxel;
@ -455,12 +456,12 @@ bool DistantUniverse::onPacket(const data::out_view& buf, net::PacketFlags) {
return true;
}
void DistantUniverse::emit(const action::packet &action) {
if(const auto move = std::get_if<action::Move>(&action)) {
void DistantUniverse::emit(const world::action::packet &action) {
if(const auto move = std::get_if<world::action::Move>(&action)) {
peer.send(net::PacketWriter::Of(net::client_packet_type::MOVE, move->pos), net::client::queue::MOVE, 1);
} else if(const auto message = std::get_if<action::Message>(&action)) {
} else if(const auto message = std::get_if<world::action::Message>(&action)) {
peer.send(net::PacketWriter::Of(net::client_packet_type::MESSAGE, message->text.data(), message->text.size()));
} else if(const auto fill = std::get_if<action::FillShape>(&action)) {
} else if(const auto fill = std::get_if<world::action::FillShape>(&action)) {
peer.send(net::PacketWriter::Of(net::client_packet_type::FILL_SHAPE, *fill));
if (options.editPrediction) {
ZoneScopedN("Fill");

View File

@ -60,7 +60,7 @@ namespace world::client {
uint64_t moveCounter = 0;
options options;
ushort serverDistance;
uint16_t serverDistance;
size_t floodfillLimit = CHUNK_SIZE;
net::client::Client peer;

View File

@ -67,7 +67,7 @@ void LocalUniverse::update(voxel_pos pos, float) {
contouring->update(pos, *handle->areas);
}
void LocalUniverse::emit(const action::packet &packet) {
void LocalUniverse::emit(const world::action::packet &packet) {
handle->emit(packet);
}
Universe::ray_result LocalUniverse::raycast(const geometry::Ray& ray) const {

View File

@ -31,7 +31,7 @@ namespace world::client {
bool editHandling = true;
};
struct connection: net::address {
connection(): net::address{"localhost", 4242} { }
connection(): net::address{"127.0.0.1", 4242} { }
};
/// Update edits and contouring

View File

@ -2,7 +2,7 @@
#include "math.hpp"
using namespace glm;
ifvec3::ifvec3(const llvec3 &pos, uint density) {
ifvec3::ifvec3(const llvec3 &pos, u32 density) {
const auto d = IDX_LENGTH2 * density;
raw = glm::divide(pos, glm::uvec3(d));
offset = glm::vec3(rem(pos.x, d), rem(pos.y, d), rem(pos.z, d));
@ -22,6 +22,6 @@ void ifvec3::center() {
double ifvec3::dist(const ifvec3& p) const {
return glm::length(glm::dvec3(raw - p.raw)) + glm::length(offset - p.offset);
}
ifvec3 ifvec3::divide(uint m) const {
ifvec3 ifvec3::divide(u32 m) const {
return ifvec3(glm::divide(raw, glm::ucvec3(m)), glm::divide(offset, glm::uvec3(m)), false);
}

View File

@ -5,7 +5,7 @@
namespace glm {
typedef vec<3, long long> llvec3;
typedef vec<3, long> lvec3;
typedef vec<3, ushort> usvec3;
typedef vec<3, uint16_t> usvec3;
typedef vec<3, unsigned char> ucvec3;
const auto IDX_LENGTH = 32;
@ -23,7 +23,7 @@ namespace glm {
ifvec3(const raw_t &raw, const offset_t &offset, bool recenter = true) : raw(raw), offset(offset) {
if(recenter) center();
}
ifvec3(const glm::llvec3 &pos, uint density = 1);
ifvec3(const glm::llvec3 &pos, glm::u32 density = 1);
raw_t raw;
offset_t offset;
@ -33,7 +33,7 @@ namespace glm {
glm::llvec3 raw_as_long() const;
double dist(const ifvec3 &p) const;
ifvec3 divide(uint m = IDX_LENGTH) const;
ifvec3 divide(glm::u32 m = IDX_LENGTH) const;
inline const ifvec3 &operator+=(const offset_t &v) {
offset += v;

View File

@ -26,13 +26,13 @@ namespace glm {
return glm::abs(glm::abs(a) - glm::abs(b));
}
constexpr uint inline rem(long long value, uint m) {
constexpr glm::u32 inline rem(long long value, glm::u32 m) {
return value < 0 ? ((value+1) % (long long)m) + m - 1 : value % (long long)m;
}
constexpr long inline div(long long value, uint m) {
constexpr long inline div(long long value, glm::u32 m) {
return value < 0 ? ((value+1) / (long long)m) - 1 : value / (long long)m;
}
constexpr float inline div(float value, uint m) {
constexpr float inline div(float value, glm::u32 m) {
return value < 0 ? ((value+1) / m) - 1 : value / m;
}
constexpr ucvec3 inline modulo(const llvec3& value, const ucvec3& m = ucvec3(IDX_LENGTH)) {

View File

@ -1,6 +1,7 @@
#pragma once
#include "Box.hpp"
#include <algorithm>
namespace geometry {
/// Bounding frustum
@ -72,9 +73,9 @@ namespace geometry {
for (int i = 0; i<6; i++) {
//pick closest point to plane and check if it behind the plane
//if yes - object outside frustum
float d = std::max(box.Min.x * planes[i].x, box.Max.x * planes[i].x)
+ std::max(box.Min.y * planes[i].y, box.Max.y * planes[i].y)
+ std::max(box.Min.z * planes[i].z, box.Max.z * planes[i].z)
float d = std::max<float>(box.Min.x * planes[i].x, box.Max.x * planes[i].x)
+ std::max<float>(box.Min.y * planes[i].y, box.Max.y * planes[i].y)
+ std::max<float>(box.Min.z * planes[i].z, box.Max.z * planes[i].z)
+ planes[i].w;
inside &= d > 0;
//return false; //with flag works faster

View File

@ -46,7 +46,7 @@ enum class server_packet_type: uint8_t {
/// empty: all sent
CHUNK = 18,
/// Uncompressed chunk changes
/// {area_id, {chunk_pos, ushort(count), Chunk::Edit[]}[]}
/// {area_id, {chunk_pos, uint16_t(count), Chunk::Edit[]}[]}
RAW_EDITS = 19,
/// Chunk changes instruction
/// action::FillShape
@ -68,7 +68,7 @@ enum class server_packet_type: uint8_t {
/// zstd dict
COMPRESSION = 64,
/// Server capabilities
/// ushort(loadDistance), bool(predictable), (if predictable) size_t(floodfillLimit)
/// uint16_t(loadDistance), bool(predictable), (if predictable) size_t(floodfillLimit)
//MAYBE: use uint8_t flags
CAPABILITIES = 65,

View File

@ -1,11 +0,0 @@
#include "logger.hpp"
#include <chrono>
#include <ctime>
namespace logger {
std::_Put_time<char> now() {
const auto tp = std::chrono::system_clock::now();
const auto timet = std::chrono::system_clock::to_time_t(tp);
return std::put_time(std::localtime(&timet), "%Y-%m-%d %X");
}
}

View File

@ -1,8 +1,11 @@
#pragma once
#include "colors.h"
#include <sstream>
#include <iostream>
#include <iomanip>
#include <chrono>
#include <ctime>
#define _OUT(expr) {std::ostringstream oss; oss << expr << std::endl; std::cout << oss.str();}
#define LOG(expr) _OUT("[" << BOLD << logger::now() << END_COLOR << "] " << BOLD << expr << END_COLOR)
@ -22,5 +25,9 @@
#define FATAL(expr) LOG_E(expr); exit(EXIT_FAILURE)
namespace logger {
std::_Put_time<char> now();
inline auto now() {
const auto tp = std::chrono::system_clock::now();
const auto timet = std::chrono::system_clock::to_time_t(tp);
return std::put_time(std::localtime(&timet), "%Y-%m-%d %X");
}
}

View File

@ -8,9 +8,9 @@ using namespace world;
Chunk::Chunk(std::istream& str, bool rle) {
if(rle) {
ushort i = 0;
uint16_t i = 0;
while(!str.eof()) {
ushort count;
uint16_t count;
Voxel voxel;
str.read(reinterpret_cast<char *>(&count), sizeof(count));
str.read(reinterpret_cast<char *>(&voxel), sizeof(voxel));

View File

@ -29,7 +29,7 @@ std::optional<Faces> EdittableChunk::update(float deltaTime, bool animate) {
}
}
void EdittableChunk::invalidate(ushort idx) {
void EdittableChunk::invalidate(uint16_t idx) {
invalidate(
((!getNeighborIdx(idx, Face::Up).has_value()) & Faces::Up) |
((!getNeighborIdx(idx, Face::Down).has_value()) & Faces::Down) |

View File

@ -16,9 +16,9 @@ namespace world {
/// Distance management
struct options {
/// Radius in chunks to load if missing
ushort loadDistance = 5;
uint16_t loadDistance = 5;
/// Radius in chunks to keep in memory
ushort keepDistance = 6;
uint16_t keepDistance = 6;
};
/// Universe voxel ray intersection

View File

@ -33,7 +33,7 @@ namespace world {
return (value & MATERIAL_MASK) >> 3;
}
/// Texture idx
constexpr inline ushort texture() const {
constexpr inline uint16_t texture() const {
return materials::textures_map[material()];
}

View File

@ -179,8 +179,10 @@ public:
private:
const uint16_t radius;
const uint max_i, max_j;
uint i, j;
const uint32_t max_i;
const uint32_t max_j;
uint32_t i;
uint32_t j;
};
/// Anti-aliased sphere

View File

@ -11,7 +11,7 @@ namespace world::materials {
std::string texture;
float roughness;
bool solid;
//ushort break_to
//uint16_t break_to
};
//MAYBE: index name enum
@ -24,11 +24,11 @@ namespace world::materials {
/// Materials count
static const auto count = 9;
static_assert(count < (USHRT_MAX >> 4)); //NOTE: for byte packing see Voxel
static_assert(count < (USHRT_MAX >> 4), "for byte packing see Voxel");
/// Materials names
static const std::array<std::string, count> names = {{"Air", "Dirt", "Grass", "Sand", "Rock", "Wall", "Path", "Alien metal", "Water"}};
/// Materials textures
static const std::array<ushort, count> textures_map = {{0, 2, 9, 1, 7, 6, 3, 8, 12}};
static const std::array<uint16_t, count> textures_map = {{0, 2, 9, 1, 7, 6, 3, 8, 12}};
/// Materials roughness.
/// -1: slope, 0: normal, 1: cube
static const std::array<float, count> roughness = {{0, 0, 0, 0, 0, 0, -1, .8, 0}};

View File

@ -23,8 +23,12 @@ int main(int argc, char *argv[]){
auto options = config::options(argc > 1 ? argv[1] : config::DEFAULT_FILE);
options.save();
std::optional<Server> server = options.hasServer() ? std::make_optional<Server>(options.getServer()) : std::nullopt;
std::optional<Client> client = options.hasClient() ? std::make_optional<Client>(options.getClient()) : std::nullopt;
std::optional<Server> server;
if (options.hasServer())
server.emplace(options.getServer());
std::optional<Client> client;
if (options.hasClient())
client.emplace(options.getClient());
const auto serverTask = [&] {
#if TRACY_ENABLE

View File

@ -25,7 +25,7 @@ public:
world.loadDistance = config["world"]["load_distance"].value_or(world.loadDistance);
world.keepDistance = config["world"]["keep_distance"].value_or(world.keepDistance);
world.folderPath = config["world"]["path"].value_or(world.folderPath);
world.floodFillLimit = config["world"]["max_part_size"].value_or<int64_t>(world.floodFillLimit);
world.floodFillLimit = config["world"]["max_part_size"].value_or((int64_t)world.floodFillLimit);
}
toml::table save() {

View File

@ -25,10 +25,10 @@ namespace net::server {
}
}
Server::Server(const exposure& ct,
Server::Server(const net::exposure& ct,
std::function<std::optional<uint16_t>(Peer*)> onConnect,
std::function<bool(Peer*, bool, uint16_t)> onDisconnect,
std::function<bool(Peer*, const data::out_view&, PacketFlags)> onPacket):
std::function<bool(Peer*, const data::out_view&, net::PacketFlags)> onPacket):
Context(ct.max_connections, ct.cert.c_str(), ct.key.c_str(), connection_callback, this),
onConnect(onConnect), onDisconnect(onDisconnect), onPacket(onPacket), max_connections(ct.max_connections)
{

View File

@ -6,7 +6,7 @@
using namespace world::server;
Chunk::Chunk(const chunk_pos& pos, const std::unique_ptr<generator::Abstract>& rnd): world::Chunk() {
Chunk::Chunk(const chunk_pos& pos, const std::unique_ptr<world::generator::Abstract>& rnd): world::Chunk() {
rnd->generate(pos, voxels);
}
#include <iostream>
@ -15,7 +15,7 @@ Chunk::~Chunk() { }
world::Voxel Chunk::write(std::ostream& str, bool rle) const {
Voxel::material_t majMat = UINT16_MAX;
ushort majCounter = 1;
uint16_t majCounter = 1;
size_t visibleDensity = 0;
const auto doMaj = [&](const Voxel& current) {
if (current.material() == majMat) {
@ -30,8 +30,8 @@ world::Voxel Chunk::write(std::ostream& str, bool rle) const {
visibleDensity += current.density() * current.is_visible();
};
if (rle) {
const auto *it = voxels.begin();
ushort counter = 1;
auto it = voxels.begin();
uint16_t counter = 1;
Voxel current = *it;
while(true) {
++it;
@ -61,14 +61,14 @@ world::Voxel Chunk::write(std::ostream& str, bool rle) const {
return Voxel(majMat, visibleDensity / CHUNK_SIZE);
}
void Chunk::set(ushort idx, const Voxel& val) {
void Chunk::set(uint16_t idx, const world::Voxel& val) {
modified = modified || (voxels[idx].value != val.value);
voxels[idx] = val;
}
void Chunk::setAt(const chunk_voxel_pos& pos, const Voxel& val) {
void Chunk::setAt(const chunk_voxel_pos& pos, const world::Voxel& val) {
set(glm::toIdx(pos), val);
}
std::optional<world::Item> Chunk::replace(chunk_voxel_idx idx, const Voxel& val, float) {
std::optional<world::Item> Chunk::replace(chunk_voxel_idx idx, const world::Voxel& val, float) {
const auto res = voxels[idx];
set(idx, val);
return {world::Item{res.density(), res.material()}};

View File

@ -56,7 +56,7 @@ void SharedUniverse::broadcastEntities() {
Universe::broadcastEntities();
}
std::shared_ptr<Chunk> SharedUniverse::createChunk(const chunk_pos &pos, const std::unique_ptr<generator::Abstract> &rnd) const {
std::shared_ptr<Chunk> SharedUniverse::createChunk(const chunk_pos &pos, const std::unique_ptr<world::generator::Abstract> &rnd) const {
return std::make_shared<SharedChunk>(pos, rnd);
}
std::shared_ptr<Chunk> SharedUniverse::createChunk(std::istream &str) const {

View File

@ -11,6 +11,7 @@
#include "../../core/world/actions.hpp"
#include "../../core/world/models.hpp"
#include "../../core/net/io.hpp"
#include <glm/common.hpp>
using namespace world::server;
@ -72,7 +73,7 @@ Universe::Universe(const Universe::options &options): host(options.connection,
}
// Workers
for (size_t i = 0; i < std::max<uint>(1, std::thread::hardware_concurrency() / 2 - 1); i++) {
for (size_t i = 0; i < std::max<size_t>(1, std::thread::hardware_concurrency() / 2 - 1); i++) {
workers.emplace_back([&] {
#if TRACY_ENABLE
tracy::SetThreadName("Chunks");
@ -471,7 +472,7 @@ std::optional<uint16_t> Universe::onConnect(net::server::Peer* peer) {
peer->ctx = client;
{
auto packet = PacketWriter(server_packet_type::CAPABILITIES, sizeof(loadDistance) + sizeof(bool));
auto packet = PacketWriter(server_packet_type::CAPABILITIES, sizeof(loadDistance) + sizeof(bool) + sizeof(floodFillLimit) * PREDICTABLE);
packet.write(loadDistance);
packet.write(PREDICTABLE);
if constexpr (PREDICTABLE) {
@ -741,7 +742,7 @@ bool Universe::isAreaFree(const area_<voxel_pos> &pos, const geometry::Shape sha
return false;
}
world::ItemList Universe::set(const area_<voxel_pos>& pos, int radius, action::Shape shape, const Voxel& val) {
world::ItemList Universe::set(const area_<voxel_pos>& pos, int radius, world::action::Shape shape, const world::Voxel& val) {
ZoneScopedN("Fill");
ItemList list;
const bool stupidClient = host.anyPeer([&](net::server::Peer *peer) {
@ -764,8 +765,8 @@ world::ItemList Universe::set(const area_<voxel_pos>& pos, int radius, action::S
voxel_pos min = voxel_pos(INT64_MAX);
voxel_pos max = voxel_pos(INT64_MIN);
for(auto full: part) {
min = glm::min(min, full);
max = glm::max(max, full);
min = glm::min<3, long long>(min, full);
max = glm::max<3, long long>(max, full);
}
const auto size = max - min;
const chunk_pos scale = chunk_pos(1) + glm::divide(size);
@ -877,7 +878,7 @@ bool Universe::movePlayer(data::generational::id id, glm::ifvec3 pos) {
return false;
}
std::shared_ptr<Chunk> Universe::createChunk(const chunk_pos &pos, const std::unique_ptr<generator::Abstract> &rnd) const {
std::shared_ptr<Chunk> Universe::createChunk(const chunk_pos &pos, const std::unique_ptr<world::generator::Abstract> &rnd) const {
return std::make_shared<Chunk>(pos, rnd);
}
std::shared_ptr<Chunk> Universe::createChunk(std::istream &str) const {

View File

@ -111,8 +111,8 @@ namespace world::server {
using save_task_t = std::pair<area_it_t, robin_hood::pair<chunk_pos, std::shared_ptr<world::server::Chunk>>>;
data::safe_queue<save_task_t> saveQueue; //NOTE: consider Area and Chunk const
ushort loadDistance;
ushort keepDistance;
uint16_t loadDistance;
uint16_t keepDistance;
std::string folderPath;
size_t floodFillLimit;

View File

@ -1,6 +1,7 @@
#include "File.hpp"
#include <filesystem>
#include <optional>
using namespace world::server;
@ -24,7 +25,7 @@ void FileRegion::load() {
return;
}
// Read header
ushort chunkCount; //NOTE: pretty useless
uint16_t chunkCount; //NOTE: pretty useless
file.read(reinterpret_cast<char *>(&chunkCount), sizeof(chunkCount));
while (!file.eof()) {
@ -44,7 +45,7 @@ void FileRegion::load() {
}
// Read size
ushort size = 0;
uint16_t size = 0;
if (!(flags & Flags::EMPTY)) {
file.read(reinterpret_cast<char *>(&size), sizeof(size));
}
@ -88,7 +89,7 @@ bool FileRegion::read(const region_chunk_pos& pos, const zstd::read_ctx& ctx, st
}
return true;
}
void FileRegion::write(const region_chunk_pos& pos, const zstd::write_ctx& ctx, const std::string_view& in, const std::optional<Voxel>& avg) {
void FileRegion::write(const region_chunk_pos& pos, const zstd::write_ctx& ctx, const std::string_view& in, const std::optional<world::Voxel>& avg) {
std::unique_ptr<std::vector<char>> buffer = nullptr;
if (!in.empty()) {
buffer = std::make_unique<std::vector<char>>();
@ -113,7 +114,7 @@ void FileRegion::save(std::optional<to_save> added) {
}
{ // Write header
ushort size = index.size() + (added.has_value() ? 1 : 0);
uint16_t size = index.size() + (added.has_value() ? 1 : 0);
tmpFile.write(reinterpret_cast<char *>(&size), sizeof(size));
}

View File

@ -52,10 +52,10 @@ namespace world::server {
std::shared_mutex mutex;
std::ifstream file;
struct node {
node(const std::optional<Voxel>& a, ushort s, std::streampos o):
node(const std::optional<Voxel>& a, uint16_t s, std::streampos o):
average(a), size(s), offset(o) { }
std::optional<Voxel> average;
ushort size;
uint16_t size;
std::streampos offset;
};
robin_hood::unordered_map<region_chunk_pos, node> index;

View File

@ -1,5 +1,7 @@
#include "Memory.hpp"
#include <optional>
using namespace world::server;
#define REMOVE_CORRUPTED 1
@ -26,7 +28,7 @@ void MemoryRegion::load() {
}
// Read header
ushort chunkCount; //NOTE: pretty useless
uint16_t chunkCount; //NOTE: pretty useless
file.read(reinterpret_cast<char *>(&chunkCount), sizeof(chunkCount));
while (!file.eof()) {
@ -47,7 +49,7 @@ void MemoryRegion::load() {
}
// Read size
ushort size = 0;
uint16_t size = 0;
if (!(flags & Flags::EMPTY)) {
file.read(reinterpret_cast<char *>(&size), sizeof(size));
}
@ -94,7 +96,7 @@ bool MemoryRegion::read(const region_chunk_pos& pos, const zstd::read_ctx& ctx,
}
return true;
}
void MemoryRegion::write(const region_chunk_pos& pos, const zstd::write_ctx& ctx, const std::string_view& in, const std::optional<Voxel>& avg) {
void MemoryRegion::write(const region_chunk_pos& pos, const zstd::write_ctx& ctx, const std::string_view& in, const std::optional<world::Voxel>& avg) {
std::unique_ptr<std::vector<char>> buffer = nullptr;
if (!in.empty()) {
buffer = std::make_unique<std::vector<char>>();
@ -134,7 +136,7 @@ void MemoryRegion::save(bool force) {
}
{ // Write header
ushort size = (ushort)content.size();
uint16_t size = (uint16_t)content.size();
file.write(reinterpret_cast<char *>(&size), sizeof(size));
}
@ -160,7 +162,7 @@ void MemoryRegion::save(bool force) {
if (!(flags & Flags::EMPTY)) {
assert(chunk.second.data->size() < USHRT_MAX);
auto size = (ushort)chunk.second.data->size();
auto size = (uint16_t)chunk.second.data->size();
const auto out = chunk.second.data->data();
// Write size