project-wide refactoring
- moved implementation-only headers to `/impl` - replaced `[[nodiscard]]` with `TOML_NODISCARD` - added `.clang-format` + applied to all files also: - added support for Unicode 14.0 - fixed minor documentation issues - version bump (pre-emptive for next release)
This commit is contained in:
parent
fe28ec8d24
commit
ca76e5d571
@ -8,6 +8,10 @@ jobs:
|
||||
resource_class: large
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Installing dependencies
|
||||
command: |
|
||||
pip3 install --upgrade -r tools/requirements.txt
|
||||
- run:
|
||||
name: Checking toml.hpp
|
||||
command: |
|
||||
@ -28,10 +32,6 @@ jobs:
|
||||
resource_class: large
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Checking toml.hpp
|
||||
command: |
|
||||
cd tools && python3 ci_single_header_check.py
|
||||
- run:
|
||||
name: Pulling submodules
|
||||
command: |
|
||||
@ -83,7 +83,7 @@ jobs:
|
||||
- run:
|
||||
name: Installing dependencies
|
||||
command: |
|
||||
pip3 install -r tools/requirements.txt
|
||||
pip3 install --upgrade -r tools/requirements.txt
|
||||
- run:
|
||||
name: Generating documentation
|
||||
command: |
|
||||
|
185
.clang-format
Normal file
185
.clang-format
Normal file
@ -0,0 +1,185 @@
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: Consecutive
|
||||
AlignConsecutiveAssignments: Consecutive
|
||||
AlignConsecutiveBitFields: Consecutive
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: AlignAfterOperator
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AttributeMacros:
|
||||
- TOML_ABSTRACT_BASE
|
||||
- TOML_EMPTY_BASES
|
||||
- TOML_TRIVIAL_ABI
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: Always
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
BeforeLambdaBody: true
|
||||
BeforeWhile: true
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeConceptDeclarations: true
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: '^([/*!#]|\s*(===|---|clang-format))'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: false
|
||||
DeriveLineEnding: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: false
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: true
|
||||
IndentCaseBlocks: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: BeforeHash
|
||||
IndentExternBlock: Indent
|
||||
IndentRequires: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertTrailingCommas: None
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: All
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 1
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 1000000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
BitFieldColonSpacing: Both
|
||||
Standard: Latest
|
||||
StatementMacros:
|
||||
- TOML_ALWAYS_INLINE
|
||||
- TOML_API
|
||||
- TOML_ATTR
|
||||
- TOML_CONSTEVAL
|
||||
- TOML_EXTERNAL_LINKAGE
|
||||
- TOML_INTERNAL_LINKAGE
|
||||
- TOML_MEMBER_ATTR
|
||||
- TOML_NEVER_INLINE
|
||||
- TOML_NODISCARD
|
||||
- TOML_NODISCARD_CTOR
|
||||
- TOML_RETURNS_BY_THROWING
|
||||
TabWidth: 4
|
||||
TypenameMacros:
|
||||
UseCRLF: false
|
||||
UseTab: Always
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
- BOOST_PP_STRINGIZE
|
||||
- TOML_ATTR
|
||||
- TOML_CONCAT
|
||||
- TOML_LIKELY
|
||||
- TOML_MAKE_RAW_STRING
|
||||
- TOML_MAKE_STRING
|
||||
- TOML_MAKE_STRING_VIEW
|
||||
- TOML_PRAGMA_CLANG
|
||||
- TOML_PRAGMA_GCC
|
||||
- TOML_PRAGMA_MSVC
|
||||
- TOML_UNLIKELY
|
||||
...
|
||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(
|
||||
tomlplusplus
|
||||
VERSION 2.5.0
|
||||
VERSION 2.6.0
|
||||
DESCRIPTION "Header-only TOML config file parser and serializer for C++17 (and later!)"
|
||||
HOMEPAGE_URL "https://marzer.github.io/tomlplusplus/"
|
||||
LANGUAGES CXX
|
||||
|
6
cpp.hint
6
cpp.hint
@ -7,8 +7,10 @@
|
||||
#define TOML_EMPTY_BASES
|
||||
#define TOML_MAY_THROW
|
||||
#define TOML_CONSTEVAL constexpr
|
||||
#define TOML_LIKELY(...) (__VA_ARGS__)
|
||||
#define TOML_UNLIKELY(...) (__VA_ARGS__)
|
||||
#define TOML_CONSTRAINED_TEMPLATE(condition, ...) template <__VA_ARGS__>
|
||||
#define TOML_LIKELY(...) (__VA_ARGS__)
|
||||
#define TOML_UNLIKELY(...) (__VA_ARGS__)
|
||||
#define TOML_NODISCARD
|
||||
#define TOML_NODISCARD_CTOR
|
||||
#define TOML_EXTERNAL_LINKAGE
|
||||
#define TOML_INTERNAL_LINKAGE
|
||||
|
1116
include/toml++/impl/array.h
Normal file
1116
include/toml++/impl/array.h
Normal file
File diff suppressed because it is too large
Load Diff
283
include/toml++/impl/array_impl.h
Normal file
283
include/toml++/impl/array_impl.h
Normal file
@ -0,0 +1,283 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "array.h"
|
||||
|
||||
/// \cond
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array() noexcept
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_ARRAY_CREATED;
|
||||
#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
|
||||
TOML_ARRAY_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(array && other) noexcept //
|
||||
: node(std::move(other)),
|
||||
elements{ std::move(other.elements) }
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_ARRAY_CREATED;
|
||||
#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
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
elements = std::move(rhs.elements);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
TOML_ATTR(pure)
|
||||
const node& array::operator[](size_t index) const noexcept
|
||||
{
|
||||
return *elements[index];
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
TOML_ATTR(pure)
|
||||
node& array::operator[](size_t index) noexcept
|
||||
{
|
||||
return *elements[index];
|
||||
}
|
||||
|
||||
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
|
||||
TOML_ATTR(pure)
|
||||
node* array::get(size_t index) noexcept
|
||||
{
|
||||
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 < elements.size() ? elements[index].get() : nullptr;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool operator==(const array& lhs, const array& rhs) noexcept
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.elements.size() != rhs.elements.size())
|
||||
return false;
|
||||
for (size_t i = 0, e = lhs.elements.size(); i < e; 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.elements[i]->visit(
|
||||
[&](const auto& lhs_) noexcept
|
||||
{ return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_); });
|
||||
if (!equal)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool operator!=(const array& lhs, const array& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
size_t array::total_leaf_count() const noexcept
|
||||
{
|
||||
size_t leaves{};
|
||||
for (size_t i = 0, e = elements.size(); i < e; i++)
|
||||
{
|
||||
auto arr = elements[i]->as_array();
|
||||
leaves += arr ? arr->total_leaf_count() : 1_sz;
|
||||
}
|
||||
return leaves;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::flatten_child(array && child, size_t & dest_index) noexcept
|
||||
{
|
||||
for (size_t i = 0, e = child.size(); i < e; i++)
|
||||
{
|
||||
auto type = child.elements[i]->type();
|
||||
if (type == node_type::array)
|
||||
{
|
||||
array& arr = *reinterpret_cast<array*>(child.elements[i].get());
|
||||
if (!arr.empty())
|
||||
flatten_child(std::move(arr), dest_index);
|
||||
}
|
||||
else
|
||||
elements[dest_index++] = std::move(child.elements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::flatten()&
|
||||
{
|
||||
if (elements.empty())
|
||||
return *this;
|
||||
|
||||
bool requires_flattening = false;
|
||||
size_t size_after_flattening = elements.size();
|
||||
for (size_t i = elements.size(); i-- > 0_sz;)
|
||||
{
|
||||
auto arr = elements[i]->as_array();
|
||||
if (!arr)
|
||||
continue;
|
||||
size_after_flattening--; // discount the array itself
|
||||
const auto leaf_count = arr->total_leaf_count();
|
||||
if (leaf_count > 0_sz)
|
||||
{
|
||||
requires_flattening = true;
|
||||
size_after_flattening += leaf_count;
|
||||
}
|
||||
else
|
||||
elements.erase(elements.cbegin() + static_cast<ptrdiff_t>(i));
|
||||
}
|
||||
|
||||
if (!requires_flattening)
|
||||
return *this;
|
||||
|
||||
elements.reserve(size_after_flattening);
|
||||
|
||||
size_t i = 0;
|
||||
while (i < elements.size())
|
||||
{
|
||||
auto arr = elements[i]->as_array();
|
||||
if (!arr)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
flatten_child(std::move(*arr), i); // increments i
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
/// \endcond
|
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "toml_common.h"
|
||||
#include "common.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
@ -19,59 +19,53 @@ TOML_NAMESPACE_START
|
||||
uint8_t day;
|
||||
|
||||
/// \brief Equality operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator == (date lhs, date rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator==(date lhs, date rhs) noexcept
|
||||
{
|
||||
return lhs.year == rhs.year
|
||||
&& lhs.month == rhs.month
|
||||
&& lhs.day == rhs.day;
|
||||
return lhs.year == rhs.year && lhs.month == rhs.month && lhs.day == rhs.day;
|
||||
}
|
||||
|
||||
/// \brief Inequality operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator != (date lhs, date rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator!=(date lhs, date rhs) noexcept
|
||||
{
|
||||
return lhs.year != rhs.year
|
||||
|| lhs.month != rhs.month
|
||||
|| lhs.day != rhs.day;
|
||||
return lhs.year != rhs.year || lhs.month != rhs.month || lhs.day != rhs.day;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
static constexpr uint32_t pack(date d) noexcept
|
||||
private:
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
static constexpr uint32_t pack(const date& d) noexcept
|
||||
{
|
||||
return static_cast<uint32_t>(d.year) << 16
|
||||
| static_cast<uint32_t>(d.month) << 8
|
||||
| static_cast<uint32_t>(d.day);
|
||||
return (static_cast<uint32_t>(d.year) << 16) | (static_cast<uint32_t>(d.month) << 8)
|
||||
| static_cast<uint32_t>(d.day);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
public:
|
||||
/// \brief Less-than operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator < (date lhs, date rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator<(date lhs, date rhs) noexcept
|
||||
{
|
||||
return pack(lhs) < pack(rhs);
|
||||
}
|
||||
|
||||
/// \brief Less-than-or-equal-to operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator <= (date lhs, date rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator<=(date lhs, date rhs) noexcept
|
||||
{
|
||||
return pack(lhs) <= pack(rhs);
|
||||
}
|
||||
|
||||
/// \brief Greater-than operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator > (date lhs, date rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator>(date lhs, date rhs) noexcept
|
||||
{
|
||||
return pack(lhs) > pack(rhs);
|
||||
}
|
||||
|
||||
/// \brief Greater-than-or-equal-to operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator >= (date lhs, date rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator>=(date lhs, date rhs) noexcept
|
||||
{
|
||||
return pack(lhs) >= pack(rhs);
|
||||
}
|
||||
@ -81,20 +75,21 @@ TOML_NAMESPACE_START
|
||||
/// \detail \cpp
|
||||
/// std::cout << toml::date{ 1987, 3, 16 } << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
///
|
||||
/// \out
|
||||
/// 1987-03-16
|
||||
/// \eout
|
||||
template <typename Char>
|
||||
inline 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 !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API std::ostream& operator << (std::ostream&, const date&);
|
||||
#endif
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const date&);
|
||||
#endif
|
||||
|
||||
/// \brief A local time-of-day.
|
||||
struct TOML_TRIVIAL_ABI time
|
||||
@ -109,60 +104,54 @@ TOML_NAMESPACE_START
|
||||
uint32_t nanosecond;
|
||||
|
||||
/// \brief Equality operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator == (const time& lhs, const time& rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator==(const time& lhs, const time& rhs) noexcept
|
||||
{
|
||||
return lhs.hour == rhs.hour
|
||||
&& lhs.minute == rhs.minute
|
||||
&& lhs.second == rhs.second
|
||||
return lhs.hour == rhs.hour && lhs.minute == rhs.minute && lhs.second == rhs.second
|
||||
&& lhs.nanosecond == rhs.nanosecond;
|
||||
}
|
||||
|
||||
/// \brief Inequality operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator != (const time& lhs, const time& rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator!=(const time& lhs, const time& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
[[nodiscard]]
|
||||
private:
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
static constexpr uint64_t pack(time t) noexcept
|
||||
{
|
||||
return static_cast<uint64_t>(t.hour) << 48
|
||||
| static_cast<uint64_t>(t.minute) << 40
|
||||
| static_cast<uint64_t>(t.second) << 32
|
||||
| static_cast<uint64_t>(t.nanosecond);
|
||||
return static_cast<uint64_t>(t.hour) << 48 | static_cast<uint64_t>(t.minute) << 40
|
||||
| static_cast<uint64_t>(t.second) << 32 | static_cast<uint64_t>(t.nanosecond);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
public:
|
||||
/// \brief Less-than operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator < (time lhs, time rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator<(time lhs, time rhs) noexcept
|
||||
{
|
||||
return pack(lhs) < pack(rhs);
|
||||
}
|
||||
|
||||
/// \brief Less-than-or-equal-to operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator <= (time lhs, time rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator<=(time lhs, time rhs) noexcept
|
||||
{
|
||||
return pack(lhs) <= pack(rhs);
|
||||
}
|
||||
|
||||
/// \brief Greater-than operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator > (time lhs, time rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator>(time lhs, time rhs) noexcept
|
||||
{
|
||||
return pack(lhs) > pack(rhs);
|
||||
}
|
||||
|
||||
/// \brief Greater-than-or-equal-to operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator >= (time lhs, time rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator>=(time lhs, time rhs) noexcept
|
||||
{
|
||||
return pack(lhs) >= pack(rhs);
|
||||
}
|
||||
@ -173,21 +162,22 @@ TOML_NAMESPACE_START
|
||||
/// std::cout << toml::time{ 10, 20, 34 } << "\n";
|
||||
/// std::cout << toml::time{ 10, 20, 34, 500000000 } << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
///
|
||||
/// \out
|
||||
/// 10:20:34
|
||||
/// 10:20:34.5
|
||||
/// \eout
|
||||
template <typename Char>
|
||||
inline 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 !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API std::ostream& operator << (std::ostream&, const time&);
|
||||
#endif
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const time&);
|
||||
#endif
|
||||
|
||||
/// \brief A timezone offset.
|
||||
struct TOML_TRIVIAL_ABI time_offset
|
||||
@ -197,7 +187,7 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// \brief Default-constructs a zero time-offset.
|
||||
TOML_NODISCARD_CTOR
|
||||
constexpr time_offset() noexcept
|
||||
constexpr time_offset() noexcept //
|
||||
: minutes{}
|
||||
{}
|
||||
|
||||
@ -208,61 +198,61 @@ TOML_NAMESPACE_START
|
||||
/// 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
|
||||
///
|
||||
///
|
||||
/// \out
|
||||
/// +02:30
|
||||
/// -01:30
|
||||
/// -02:30
|
||||
/// Z
|
||||
/// \eout
|
||||
///
|
||||
///
|
||||
/// \param h The total hours.
|
||||
/// \param m The total minutes.
|
||||
TOML_NODISCARD_CTOR
|
||||
constexpr time_offset(int8_t h, int8_t m) noexcept
|
||||
constexpr time_offset(int8_t h, int8_t m) noexcept //
|
||||
: minutes{ static_cast<int16_t>(h * 60 + m) }
|
||||
{}
|
||||
|
||||
/// \brief Equality operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator == (time_offset lhs, time_offset rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator==(time_offset lhs, time_offset rhs) noexcept
|
||||
{
|
||||
return lhs.minutes == rhs.minutes;
|
||||
}
|
||||
|
||||
/// \brief Inequality operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator != (time_offset lhs, time_offset rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator!=(time_offset lhs, time_offset rhs) noexcept
|
||||
{
|
||||
return lhs.minutes != rhs.minutes;
|
||||
}
|
||||
|
||||
/// \brief Less-than operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator < (time_offset lhs, time_offset rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator<(time_offset lhs, time_offset rhs) noexcept
|
||||
{
|
||||
return lhs.minutes < rhs.minutes;
|
||||
}
|
||||
|
||||
/// \brief Less-than-or-equal-to operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator <= (time_offset lhs, time_offset rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator<=(time_offset lhs, time_offset rhs) noexcept
|
||||
{
|
||||
return lhs.minutes <= rhs.minutes;
|
||||
}
|
||||
|
||||
/// \brief Greater-than operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator > (time_offset lhs, time_offset rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator>(time_offset lhs, time_offset rhs) noexcept
|
||||
{
|
||||
return lhs.minutes > rhs.minutes;
|
||||
}
|
||||
|
||||
/// \brief Greater-than-or-equal-to operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator >= (time_offset lhs, time_offset rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator>=(time_offset lhs, time_offset rhs) noexcept
|
||||
{
|
||||
return lhs.minutes >= rhs.minutes;
|
||||
}
|
||||
@ -276,7 +266,7 @@ TOML_NAMESPACE_START
|
||||
/// std::cout << toml::time_offset{ -2, 30 } << "\n";
|
||||
/// std::cout << toml::time_offset{ -2, -30 } << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
///
|
||||
/// \out
|
||||
/// +02:30
|
||||
/// +01:30
|
||||
@ -285,15 +275,16 @@ TOML_NAMESPACE_START
|
||||
/// -02:30
|
||||
/// \eout
|
||||
template <typename Char>
|
||||
inline 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 !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API std::ostream& operator << (std::ostream&, const time_offset&);
|
||||
#endif
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const time_offset&);
|
||||
#endif
|
||||
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_HAS_CUSTOM_OPTIONAL_TYPE, custopt, stdopt);
|
||||
|
||||
@ -311,10 +302,10 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// \brief Default-constructs a zero date-time.
|
||||
TOML_NODISCARD_CTOR
|
||||
constexpr date_time() noexcept
|
||||
constexpr date_time() noexcept //
|
||||
: date{},
|
||||
time{},
|
||||
offset{} // TINAE - icc bugfix
|
||||
time{},
|
||||
offset{} // TINAE - icc bugfix
|
||||
{}
|
||||
|
||||
/// \brief Constructs a local date-time.
|
||||
@ -322,10 +313,10 @@ TOML_NAMESPACE_START
|
||||
/// \param d The date component.
|
||||
/// \param t The time component.
|
||||
TOML_NODISCARD_CTOR
|
||||
constexpr date_time(toml::date d, toml::time t) noexcept
|
||||
constexpr date_time(toml::date d, toml::time t) noexcept //
|
||||
: date{ d },
|
||||
time{ t },
|
||||
offset{} // TINAE - icc bugfix
|
||||
time{ t },
|
||||
offset{} // TINAE - icc bugfix
|
||||
{}
|
||||
|
||||
/// \brief Constructs an offset date-time.
|
||||
@ -334,38 +325,36 @@ TOML_NAMESPACE_START
|
||||
/// \param t The time component.
|
||||
/// \param off The timezone offset.
|
||||
TOML_NODISCARD_CTOR
|
||||
constexpr date_time(toml::date d, toml::time t, toml::time_offset off) noexcept
|
||||
constexpr date_time(toml::date d, toml::time t, toml::time_offset off) noexcept
|
||||
: date{ d },
|
||||
time{ t },
|
||||
offset{ off }
|
||||
time{ t },
|
||||
offset{ off }
|
||||
{}
|
||||
|
||||
/// \brief Returns true if this date_time does not contain timezone offset information.
|
||||
[[nodiscard]]
|
||||
TOML_NODISCARD
|
||||
constexpr bool is_local() const noexcept
|
||||
{
|
||||
return !offset.has_value();
|
||||
}
|
||||
|
||||
/// \brief Equality operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator == (const date_time& lhs, const date_time& rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator==(const date_time& lhs, const date_time& rhs) noexcept
|
||||
{
|
||||
return lhs.date == rhs.date
|
||||
&& lhs.time == rhs.time
|
||||
&& lhs.offset == rhs.offset;
|
||||
return lhs.date == rhs.date && lhs.time == rhs.time && lhs.offset == rhs.offset;
|
||||
}
|
||||
|
||||
/// \brief Inequality operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator != (const date_time& lhs, const date_time& rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator!=(const date_time& lhs, const date_time& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
/// \brief Less-than operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator < (const date_time& lhs, const date_time& rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator<(const date_time& lhs, const date_time& rhs) noexcept
|
||||
{
|
||||
if (lhs.date != rhs.date)
|
||||
return lhs.date < rhs.date;
|
||||
@ -375,8 +364,8 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
|
||||
/// \brief Less-than-or-equal-to operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator <= (const date_time& lhs, const date_time& rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator<=(const date_time& lhs, const date_time& rhs) noexcept
|
||||
{
|
||||
if (lhs.date != rhs.date)
|
||||
return lhs.date < rhs.date;
|
||||
@ -386,15 +375,15 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
|
||||
/// \brief Greater-than operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator > (const date_time& lhs, const date_time& rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator>(const date_time& lhs, const date_time& rhs) noexcept
|
||||
{
|
||||
return !(lhs <= rhs);
|
||||
}
|
||||
|
||||
/// \brief Greater-than-or-equal-to operator.
|
||||
[[nodiscard]]
|
||||
friend constexpr bool operator >= (const date_time& lhs, const date_time& rhs) noexcept
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator>=(const date_time& lhs, const date_time& rhs) noexcept
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
@ -408,21 +397,22 @@ TOML_NAMESPACE_START
|
||||
/// 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
|
||||
/// 1987-03-16T10:20:34
|
||||
/// 1987-03-16T10:20:34-02:30
|
||||
/// 1987-03-16T10:20:34Z
|
||||
/// \eout
|
||||
template <typename Char>
|
||||
inline 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 !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API std::ostream& operator << (std::ostream&, const date_time&);
|
||||
#endif
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const date_time&);
|
||||
#endif
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
459
include/toml++/impl/default_formatter.h
Normal file
459
include/toml++/impl/default_formatter.h
Normal file
@ -0,0 +1,459 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "formatter.h"
|
||||
#include "table.h"
|
||||
#include "array.h"
|
||||
#include "utf8.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
|
||||
/// \cond
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
std::string default_formatter_make_key_segment(const std::string&) noexcept;
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
size_t default_formatter_inline_columns(const node&) noexcept;
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
bool default_formatter_forces_multiline(const node&, size_t = 0) noexcept;
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
/// \endcond
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \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
|
||||
/// operators of the TOML node types already print themselves out using this formatter.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::table{{
|
||||
/// { "description", "This is some TOML, yo." },
|
||||
/// { "fruit", toml::array{ "apple", "orange", "pear" } },
|
||||
/// { "numbers", toml::array{ 1, 2, 3, 4, 5 } },
|
||||
/// { "table", toml::table{{ { "foo", "bar" } }} }
|
||||
/// }};
|
||||
///
|
||||
/// // these two lines are equivalent:
|
||||
/// std::cout << toml::default_formatter{ tbl } << "\n";
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// description = "This is some TOML, yo."
|
||||
/// fruit = ["apple", "orange", "pear"]
|
||||
/// numbers = [1, 2, 3, 4, 5]
|
||||
///
|
||||
/// [table]
|
||||
/// foo = "bar"
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Char The underlying character type of the output stream. Must be 1 byte in size.
|
||||
template <typename Char = char>
|
||||
class TOML_API default_formatter final : impl::formatter<Char>
|
||||
{
|
||||
private:
|
||||
/// \cond
|
||||
|
||||
using base = impl::formatter<Char>;
|
||||
std::vector<std::string> key_path;
|
||||
bool pending_table_separator_ = false;
|
||||
|
||||
void print_pending_table_separator()
|
||||
{
|
||||
if (pending_table_separator_)
|
||||
{
|
||||
base::print_newline(true);
|
||||
base::print_newline(true);
|
||||
pending_table_separator_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void print_key_segment(const std::string& str)
|
||||
{
|
||||
if (str.empty())
|
||||
impl::print_to_stream("''"sv, base::stream());
|
||||
else
|
||||
{
|
||||
bool requiresQuotes = false;
|
||||
{
|
||||
impl::utf8_decoder decoder;
|
||||
for (size_t i = 0; i < str.length() && !requiresQuotes; i++)
|
||||
{
|
||||
decoder(static_cast<uint8_t>(str[i]));
|
||||
if (decoder.error())
|
||||
requiresQuotes = true;
|
||||
else if (decoder.has_code_point())
|
||||
requiresQuotes = !impl::is_bare_key_character(decoder.codepoint);
|
||||
}
|
||||
}
|
||||
|
||||
if (requiresQuotes)
|
||||
{
|
||||
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());
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
|
||||
void print_key_path()
|
||||
{
|
||||
for (const auto& segment : key_path)
|
||||
{
|
||||
if (std::addressof(segment) > key_path.data())
|
||||
impl::print_to_stream('.', base::stream());
|
||||
impl::print_to_stream(segment, base::stream());
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
|
||||
void print_inline(const table& /*tbl*/);
|
||||
|
||||
void print(const array& arr)
|
||||
{
|
||||
if (arr.empty())
|
||||
impl::print_to_stream("[]"sv, base::stream());
|
||||
else
|
||||
{
|
||||
const auto original_indent = base::indent();
|
||||
const auto multiline = impl::default_formatter_forces_multiline(
|
||||
arr,
|
||||
base::indent_columns * static_cast<size_t>(original_indent < 0 ? 0 : original_indent));
|
||||
impl::print_to_stream("["sv, base::stream());
|
||||
if (multiline)
|
||||
{
|
||||
if (original_indent < 0)
|
||||
base::indent(0);
|
||||
base::increase_indent();
|
||||
}
|
||||
else
|
||||
impl::print_to_stream(' ', base::stream());
|
||||
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
if (i > 0_sz)
|
||||
{
|
||||
impl::print_to_stream(',', base::stream());
|
||||
if (!multiline)
|
||||
impl::print_to_stream(' ', base::stream());
|
||||
}
|
||||
|
||||
if (multiline)
|
||||
{
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
}
|
||||
|
||||
auto& v = arr[i];
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
if (multiline)
|
||||
{
|
||||
base::indent(original_indent);
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
}
|
||||
else
|
||||
impl::print_to_stream(' ', base::stream());
|
||||
impl::print_to_stream("]"sv, base::stream());
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
|
||||
void print(const table& tbl)
|
||||
{
|
||||
static constexpr auto is_non_inline_array_of_tables = [](auto&& nde) noexcept
|
||||
{
|
||||
auto arr = nde.as_array();
|
||||
return arr && arr->is_array_of_tables() && !arr->template get_as<table>(0_sz)->is_inline();
|
||||
};
|
||||
|
||||
// values, arrays, and inline tables/table arrays
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
const auto type = v.type();
|
||||
if ((type == node_type::table && !reinterpret_cast<const table*>(&v)->is_inline())
|
||||
|| (type == node_type::array && is_non_inline_array_of_tables(v)))
|
||||
continue;
|
||||
|
||||
pending_table_separator_ = true;
|
||||
base::print_newline();
|
||||
base::print_indent();
|
||||
print_key_segment(k);
|
||||
impl::print_to_stream(" = "sv, base::stream());
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
|
||||
// non-inline tables
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
const auto type = v.type();
|
||||
if (type != node_type::table || reinterpret_cast<const table*>(&v)->is_inline())
|
||||
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)
|
||||
size_t child_value_count{}; // includes inline tables and non-table arrays
|
||||
size_t child_table_count{};
|
||||
size_t child_table_array_count{};
|
||||
for (auto&& [child_k, child_v] : child_tbl)
|
||||
{
|
||||
(void)child_k;
|
||||
const auto child_type = child_v.type();
|
||||
TOML_ASSUME(child_type != node_type::none);
|
||||
switch (child_type)
|
||||
{
|
||||
case node_type::table:
|
||||
if (reinterpret_cast<const table*>(&child_v)->is_inline())
|
||||
child_value_count++;
|
||||
else
|
||||
child_table_count++;
|
||||
break;
|
||||
|
||||
case node_type::array:
|
||||
if (is_non_inline_array_of_tables(child_v))
|
||||
child_table_array_count++;
|
||||
else
|
||||
child_value_count++;
|
||||
break;
|
||||
|
||||
default: child_value_count++;
|
||||
}
|
||||
}
|
||||
bool skip_self = false;
|
||||
if (child_value_count == 0_sz && (child_table_count > 0_sz || child_table_array_count > 0_sz))
|
||||
skip_self = true;
|
||||
|
||||
key_path.push_back(impl::default_formatter_make_key_segment(k));
|
||||
|
||||
if (!skip_self)
|
||||
{
|
||||
print_pending_table_separator();
|
||||
base::increase_indent();
|
||||
base::print_indent();
|
||||
impl::print_to_stream("["sv, base::stream());
|
||||
print_key_path();
|
||||
impl::print_to_stream("]"sv, base::stream());
|
||||
pending_table_separator_ = true;
|
||||
}
|
||||
|
||||
print(child_tbl);
|
||||
|
||||
key_path.pop_back();
|
||||
if (!skip_self)
|
||||
base::decrease_indent();
|
||||
}
|
||||
|
||||
// table arrays
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
if (!is_non_inline_array_of_tables(v))
|
||||
continue;
|
||||
auto& arr = *reinterpret_cast<const array*>(&v);
|
||||
|
||||
base::increase_indent();
|
||||
key_path.push_back(impl::default_formatter_make_key_segment(k));
|
||||
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
print_pending_table_separator();
|
||||
base::print_indent();
|
||||
impl::print_to_stream("[["sv, base::stream());
|
||||
print_key_path();
|
||||
impl::print_to_stream("]]"sv, base::stream());
|
||||
pending_table_separator_ = true;
|
||||
print(*reinterpret_cast<const table*>(&arr[i]));
|
||||
}
|
||||
|
||||
key_path.pop_back();
|
||||
base::decrease_indent();
|
||||
}
|
||||
}
|
||||
|
||||
void print()
|
||||
{
|
||||
if (base::dump_failed_parse_result())
|
||||
return;
|
||||
|
||||
switch (auto source_type = base::source().type())
|
||||
{
|
||||
case node_type::table:
|
||||
{
|
||||
auto& tbl = *reinterpret_cast<const table*>(&base::source());
|
||||
if (tbl.is_inline())
|
||||
print_inline(tbl);
|
||||
else
|
||||
{
|
||||
base::decrease_indent(); // so root kvps and tables have the same indent
|
||||
print(tbl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&base::source())); break;
|
||||
|
||||
default: base::print_value(base::source(), source_type);
|
||||
}
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
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 = default_flags) noexcept
|
||||
: base{ source, flags }
|
||||
{}
|
||||
|
||||
#if defined(DOXYGEN) || (TOML_PARSER && !TOML_EXCEPTIONS)
|
||||
|
||||
/// \brief Constructs a default TOML formatter and binds it to a toml::parse_result.
|
||||
///
|
||||
/// \availability This constructor is only available when exceptions are disabled.
|
||||
///
|
||||
/// \attention Formatting a failed parse result will simply dump the error message out as-is.
|
||||
/// This will not be valid TOML, but at least gives you something to log or show up in diagnostics:
|
||||
/// \cpp
|
||||
/// std::cout << toml::default_formatter{ toml::parse("a = 'b'"sv) } // ok
|
||||
/// << "\n\n"
|
||||
/// << toml::default_formatter{ toml::parse("a = "sv) } // malformed
|
||||
/// << "\n";
|
||||
/// \ecpp
|
||||
/// \out
|
||||
/// a = 'b'
|
||||
///
|
||||
/// Error while parsing key-value pair: encountered end-of-file
|
||||
/// (error occurred at line 1, column 5)
|
||||
/// \eout
|
||||
/// Use the library with exceptions if you want to avoid this scenario.
|
||||
///
|
||||
/// \param result The parse result.
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit default_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
|
||||
: base{ result, flags }
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T, typename U>
|
||||
friend std::basic_ostream<T>& operator<<(std::basic_ostream<T>&, default_formatter<U>&);
|
||||
template <typename T, typename U>
|
||||
friend std::basic_ostream<T>& operator<<(std::basic_ostream<T>&, default_formatter<U>&&);
|
||||
};
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template class TOML_API default_formatter<char>;
|
||||
#endif
|
||||
|
||||
default_formatter(const table&)->default_formatter<char>;
|
||||
default_formatter(const array&)->default_formatter<char>;
|
||||
template <typename T>
|
||||
default_formatter(const value<T>&) -> default_formatter<char>;
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as formatted TOML.
|
||||
template <typename T, typename U>
|
||||
inline std::basic_ostream<T>& operator<<(std::basic_ostream<T>& lhs, default_formatter<U>& rhs)
|
||||
{
|
||||
rhs.attach(lhs);
|
||||
rhs.key_path.clear();
|
||||
rhs.print();
|
||||
rhs.detach();
|
||||
return lhs;
|
||||
}
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as formatted TOML (rvalue overload).
|
||||
template <typename T, typename U>
|
||||
inline std::basic_ostream<T>& operator<<(std::basic_ostream<T>& lhs, default_formatter<U>&& rhs)
|
||||
{
|
||||
return lhs << rhs; // as lvalue
|
||||
}
|
||||
|
||||
#ifndef DOXYGEN
|
||||
|
||||
#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
|
||||
|
||||
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
|
@ -5,16 +5,15 @@
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "toml_preprocessor.h"
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "toml_default_formatter.h"
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#include <cmath>
|
||||
TOML_ENABLE_WARNINGS;
|
||||
#include "default_formatter.h"
|
||||
|
||||
/// \cond
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
@ -77,7 +76,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
auto& n = *reinterpret_cast<const table*>(&node);
|
||||
if (n.empty())
|
||||
return 2_sz; // "{}"
|
||||
return 2_sz; // "{}"
|
||||
size_t weight = 3_sz; // "{ }"
|
||||
for (auto&& [k, v] : n)
|
||||
{
|
||||
@ -92,7 +91,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
auto& n = *reinterpret_cast<const array*>(&node);
|
||||
if (n.empty())
|
||||
return 2_sz; // "[]"
|
||||
return 2_sz; // "[]"
|
||||
size_t weight = 3_sz; // "[ ]"
|
||||
for (auto& elem : n)
|
||||
{
|
||||
@ -112,7 +111,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
case node_type::integer:
|
||||
{
|
||||
auto& n = *reinterpret_cast<const value<int64_t>*>(&node);
|
||||
auto v = n.get();
|
||||
auto v = n.get();
|
||||
if (!v)
|
||||
return 1_sz;
|
||||
size_t weight = {};
|
||||
@ -127,9 +126,9 @@ TOML_IMPL_NAMESPACE_START
|
||||
case node_type::floating_point:
|
||||
{
|
||||
auto& n = *reinterpret_cast<const value<double>*>(&node);
|
||||
auto v = n.get();
|
||||
auto v = n.get();
|
||||
if (v == 0.0)
|
||||
return 3_sz; // "0.0"
|
||||
return 3_sz; // "0.0"
|
||||
size_t weight = 2_sz; // ".0"
|
||||
if (v < 0.0)
|
||||
{
|
||||
@ -145,7 +144,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
case node_type::time: return 10_sz;
|
||||
case node_type::date_time: return 30_sz;
|
||||
case node_type::none: TOML_UNREACHABLE;
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
TOML_UNREACHABLE;
|
||||
@ -186,8 +185,7 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default:
|
||||
base::print_value(v, type);
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,36 +199,29 @@ TOML_NAMESPACE_END;
|
||||
// implementations of windows wide string nonsense
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
#ifndef _WINDOWS_
|
||||
#if TOML_INCLUDE_WINDOWS_H
|
||||
#include <Windows.h>
|
||||
#else
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllimport)
|
||||
int __stdcall WideCharToMultiByte(
|
||||
unsigned int CodePage,
|
||||
unsigned long dwFlags,
|
||||
const wchar_t* lpWideCharStr,
|
||||
int cchWideChar,
|
||||
char* lpMultiByteStr,
|
||||
int cbMultiByte,
|
||||
const char* lpDefaultChar,
|
||||
int* lpUsedDefaultChar
|
||||
);
|
||||
|
||||
__declspec(dllimport)
|
||||
int __stdcall MultiByteToWideChar(
|
||||
unsigned int CodePage,
|
||||
unsigned long dwFlags,
|
||||
const char* lpMultiByteStr,
|
||||
int cbMultiByte,
|
||||
wchar_t* lpWideCharStr,
|
||||
int cchWideChar
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#endif // _WINDOWS_
|
||||
#ifndef _WINDOWS_
|
||||
#if TOML_INCLUDE_WINDOWS_H
|
||||
#include <Windows.h>
|
||||
#else
|
||||
extern "C" {
|
||||
__declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int CodePage,
|
||||
unsigned long dwFlags,
|
||||
const wchar_t* lpWideCharStr,
|
||||
int cchWideChar,
|
||||
char* lpMultiByteStr,
|
||||
int cbMultiByte,
|
||||
const char* lpDefaultChar,
|
||||
int* lpUsedDefaultChar);
|
||||
|
||||
__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage,
|
||||
unsigned long dwFlags,
|
||||
const char* lpMultiByteStr,
|
||||
int cbMultiByte,
|
||||
wchar_t* lpWideCharStr,
|
||||
int cchWideChar);
|
||||
}
|
||||
#endif
|
||||
#endif // _WINDOWS_
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
@ -241,13 +232,19 @@ TOML_IMPL_NAMESPACE_START
|
||||
return {};
|
||||
|
||||
std::string s;
|
||||
const auto len = ::WideCharToMultiByte(
|
||||
65001, 0, str.data(), static_cast<int>(str.length()), nullptr, 0, nullptr, nullptr
|
||||
);
|
||||
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);
|
||||
::WideCharToMultiByte(65001,
|
||||
0,
|
||||
str.data(),
|
||||
static_cast<int>(str.length()),
|
||||
s.data(),
|
||||
len,
|
||||
nullptr,
|
||||
nullptr);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -285,4 +282,6 @@ TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_ARITHMETIC_WARNINGS
|
||||
TOML_POP_WARNINGS;
|
||||
|
||||
/// \endcond
|
295
include/toml++/impl/formatter.h
Normal file
295
include/toml++/impl/formatter.h
Normal file
@ -0,0 +1,295 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
/// \cond
|
||||
|
||||
#pragma once
|
||||
#include "print_to_stream.h"
|
||||
#if TOML_PARSER && !TOML_EXCEPTIONS
|
||||
#include "parse_result.h"
|
||||
#endif
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
template <typename Char = char>
|
||||
class TOML_API formatter
|
||||
{
|
||||
private:
|
||||
const toml::node* source_;
|
||||
std::basic_ostream<Char>* stream_ = {};
|
||||
format_flags flags_;
|
||||
int indent_;
|
||||
bool naked_newline_;
|
||||
#if TOML_PARSER && !TOML_EXCEPTIONS
|
||||
const parse_result* result_ = {};
|
||||
#endif
|
||||
|
||||
protected:
|
||||
TOML_NODISCARD
|
||||
const toml::node& source() const noexcept
|
||||
{
|
||||
return *source_;
|
||||
}
|
||||
TOML_NODISCARD
|
||||
std::basic_ostream<Char>& stream() const noexcept
|
||||
{
|
||||
return *stream_;
|
||||
}
|
||||
|
||||
static constexpr size_t indent_columns = 4;
|
||||
static constexpr std::string_view indent_string = " "sv;
|
||||
|
||||
TOML_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_NODISCARD
|
||||
bool quote_dates_and_times() const noexcept
|
||||
{
|
||||
return (flags_ & format_flags::quote_dates_and_times) != format_flags::none;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool literal_strings_allowed() const noexcept
|
||||
{
|
||||
return (flags_ & format_flags::allow_literal_strings) != format_flags::none;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool multi_line_strings_allowed() const noexcept
|
||||
{
|
||||
return (flags_ & format_flags::allow_multi_line_strings) != format_flags::none;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool value_format_flags_allowed() const noexcept
|
||||
{
|
||||
return (flags_ & format_flags::allow_value_format_flags) != format_flags::none;
|
||||
}
|
||||
|
||||
TOML_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
|
||||
{
|
||||
indent_ = {};
|
||||
naked_newline_ = true;
|
||||
stream_ = &stream;
|
||||
}
|
||||
|
||||
void detach() noexcept
|
||||
{
|
||||
stream_ = nullptr;
|
||||
}
|
||||
|
||||
void print_newline(bool force = false)
|
||||
{
|
||||
if (!naked_newline_ || force)
|
||||
{
|
||||
print_to_stream('\n', *stream_);
|
||||
naked_newline_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void print_indent()
|
||||
{
|
||||
for (int i = 0; i < indent_; i++)
|
||||
{
|
||||
print_to_stream(indent_string, *stream_);
|
||||
naked_newline_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void print_quoted_string(std::string_view str, bool allow_multi_line = true)
|
||||
{
|
||||
auto literals = literal_strings_allowed();
|
||||
if (str.empty())
|
||||
{
|
||||
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
|
||||
{
|
||||
const auto quot = multi_line ? R"(""")"sv : R"(")"sv;
|
||||
print_to_stream(quot, *stream_);
|
||||
print_to_stream_with_escapes(str, *stream_);
|
||||
print_to_stream(quot, *stream_);
|
||||
}
|
||||
clear_naked_newline();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void print(const value<T>& val)
|
||||
{
|
||||
if constexpr (std::is_same_v<T, std::string>)
|
||||
{
|
||||
print_quoted_string(val.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr (is_one_of<T, date, time, date_time>)
|
||||
{
|
||||
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_);
|
||||
}
|
||||
else if constexpr (is_one_of<T, int64_t /*, double*/>)
|
||||
{
|
||||
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;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void print_value(const node& val_node, node_type type)
|
||||
{
|
||||
TOML_ASSUME(type > node_type::array);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::string: print(*reinterpret_cast<const value<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;
|
||||
case node_type::date: print(*reinterpret_cast<const value<date>*>(&val_node)); break;
|
||||
case node_type::time: print(*reinterpret_cast<const value<time>*>(&val_node)); break;
|
||||
case node_type::date_time: print(*reinterpret_cast<const value<date_time>*>(&val_node)); break;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool dump_failed_parse_result()
|
||||
{
|
||||
#if TOML_PARSER && !TOML_EXCEPTIONS
|
||||
if (result_ && !(*result_))
|
||||
{
|
||||
stream() << result_->error();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
formatter(const toml::node& source, format_flags flags) noexcept //
|
||||
: source_{ &source },
|
||||
flags_{ flags }
|
||||
{}
|
||||
|
||||
#if TOML_PARSER && !TOML_EXCEPTIONS
|
||||
|
||||
formatter(const parse_result& result, format_flags flags) noexcept //
|
||||
: source_{ result ? &result.table() : nullptr },
|
||||
flags_{ flags },
|
||||
result_{ &result }
|
||||
{}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template class TOML_API formatter<char>;
|
||||
#endif
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_SWITCH_WARNINGS
|
||||
|
||||
/// \endcond
|
195
include/toml++/impl/json_formatter.h
Normal file
195
include/toml++/impl/json_formatter.h
Normal file
@ -0,0 +1,195 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "formatter.h"
|
||||
#include "table.h"
|
||||
#include "array.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A wrapper for printing TOML objects out to a stream as formatted JSON.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto some_toml = toml::parse(R"(
|
||||
/// [fruit]
|
||||
/// apple.color = "red"
|
||||
/// apple.taste.sweet = true
|
||||
///
|
||||
/// [fruit.apple.texture]
|
||||
/// smooth = true
|
||||
/// )"sv);
|
||||
/// std::cout << toml::json_formatter{ some_toml } << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// {
|
||||
/// "fruit" : {
|
||||
/// "apple" : {
|
||||
/// "color" : "red",
|
||||
/// "taste" : {
|
||||
/// "sweet" : true
|
||||
/// },
|
||||
/// "texture" : {
|
||||
/// "smooth" : true
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Char The underlying character type of the output stream. Must be 1 byte in size.
|
||||
template <typename Char = char>
|
||||
class TOML_API json_formatter final : impl::formatter<Char>
|
||||
{
|
||||
private:
|
||||
/// \cond
|
||||
|
||||
using base = impl::formatter<Char>;
|
||||
|
||||
void print(const toml::table& tbl);
|
||||
|
||||
void print(const array& arr)
|
||||
{
|
||||
if (arr.empty())
|
||||
impl::print_to_stream("[]"sv, base::stream());
|
||||
else
|
||||
{
|
||||
impl::print_to_stream('[', base::stream());
|
||||
base::increase_indent();
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
if (i > 0_sz)
|
||||
impl::print_to_stream(',', base::stream());
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
|
||||
auto& v = arr[i];
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
base::decrease_indent();
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
impl::print_to_stream(']', base::stream());
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
|
||||
void print()
|
||||
{
|
||||
if (base::dump_failed_parse_result())
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
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 = default_flags) noexcept
|
||||
: base{ source, flags }
|
||||
{}
|
||||
|
||||
#if defined(DOXYGEN) || (TOML_PARSER && !TOML_EXCEPTIONS)
|
||||
|
||||
/// \brief Constructs a JSON formatter and binds it to a toml::parse_result.
|
||||
///
|
||||
/// \availability This constructor is only available when exceptions are disabled.
|
||||
///
|
||||
/// \attention Formatting a failed parse result will simply dump the error message out as-is.
|
||||
/// This will not be valid JSON, but at least gives you something to log or show up in diagnostics:
|
||||
/// \cpp
|
||||
/// std::cout << toml::json_formatter{ toml::parse("a = 'b'"sv) } // ok
|
||||
/// << "\n\n"
|
||||
/// << toml::json_formatter{ toml::parse("a = "sv) } // malformed
|
||||
/// << "\n";
|
||||
/// \ecpp
|
||||
/// \out
|
||||
/// {
|
||||
/// "a" : "b"
|
||||
/// }
|
||||
///
|
||||
/// Error while parsing key-value pair: encountered end-of-file
|
||||
/// (error occurred at line 1, column 5)
|
||||
/// \eout
|
||||
/// Use the library with exceptions if you want to avoid this scenario.
|
||||
///
|
||||
/// \param result The parse result.
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit json_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
|
||||
: base{ result, flags }
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T, typename U>
|
||||
friend std::basic_ostream<T>& operator<<(std::basic_ostream<T>&, json_formatter<U>&);
|
||||
template <typename T, typename U>
|
||||
friend std::basic_ostream<T>& operator<<(std::basic_ostream<T>&, json_formatter<U>&&);
|
||||
};
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template class TOML_API json_formatter<char>;
|
||||
#endif
|
||||
|
||||
json_formatter(const table&)->json_formatter<char>;
|
||||
json_formatter(const array&)->json_formatter<char>;
|
||||
template <typename T>
|
||||
json_formatter(const value<T>&) -> json_formatter<char>;
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as JSON.
|
||||
template <typename T, typename U>
|
||||
inline std::basic_ostream<T>& operator<<(std::basic_ostream<T>& lhs, json_formatter<U>& rhs)
|
||||
{
|
||||
rhs.attach(lhs);
|
||||
rhs.print();
|
||||
rhs.detach();
|
||||
return lhs;
|
||||
}
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as JSON (rvalue overload).
|
||||
template <typename T, typename U>
|
||||
inline std::basic_ostream<T>& operator<<(std::basic_ostream<T>& lhs, json_formatter<U>&& rhs)
|
||||
{
|
||||
return lhs << rhs; // as lvalue
|
||||
}
|
||||
|
||||
#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
|
@ -5,13 +5,15 @@
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "toml_preprocessor.h"
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "toml_json_formatter.h"
|
||||
#include "json_formatter.h"
|
||||
|
||||
/// \cond
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
@ -45,10 +47,8 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default:
|
||||
base::print_value(v, type);
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
|
||||
}
|
||||
base::decrease_indent();
|
||||
base::print_newline(true);
|
||||
@ -60,4 +60,6 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_SWITCH_WARNINGS
|
||||
TOML_POP_WARNINGS;
|
||||
|
||||
/// \endcond
|
997
include/toml++/impl/node.h
Normal file
997
include/toml++/impl/node.h
Normal file
@ -0,0 +1,997 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A TOML node.
|
||||
///
|
||||
/// \detail A parsed TOML document forms a tree made up of tables, arrays and values.
|
||||
/// This type is the base of each of those, providing a lot of the polymorphic plumbing.
|
||||
class TOML_ABSTRACT_BASE TOML_API node
|
||||
{
|
||||
private:
|
||||
friend class TOML_PARSER_TYPENAME;
|
||||
source_region source_{};
|
||||
|
||||
/// \cond
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
decltype(auto) get_value_exact() const noexcept;
|
||||
|
||||
template <typename T, typename N>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
static decltype(auto) do_ref(N&& n) noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert((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_native<type>)
|
||||
return static_cast<N&&>(n).template ref_cast<type>().get();
|
||||
else
|
||||
return static_cast<N&&>(n).template ref_cast<type>();
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
protected:
|
||||
node() noexcept = default;
|
||||
node(const node&) noexcept;
|
||||
node(node&&) noexcept;
|
||||
node& operator=(const node&) noexcept;
|
||||
node& operator=(node&&) noexcept;
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
TOML_ATTR(pure)
|
||||
impl::wrap_node<T>& ref_cast() & noexcept
|
||||
{
|
||||
return *reinterpret_cast<impl::wrap_node<T>*>(this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
TOML_ATTR(pure)
|
||||
impl::wrap_node<T>&& ref_cast() && noexcept
|
||||
{
|
||||
return std::move(*reinterpret_cast<impl::wrap_node<T>*>(this));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
TOML_ATTR(pure)
|
||||
const impl::wrap_node<T>& ref_cast() const& noexcept
|
||||
{
|
||||
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>());
|
||||
|
||||
public:
|
||||
virtual ~node() noexcept = default;
|
||||
|
||||
/// \name Type checks
|
||||
/// @{
|
||||
|
||||
#if defined(DOXYGEN) || !TOML_ICC || TOML_ICC_CL
|
||||
|
||||
/// \brief Returns the node's type identifier.
|
||||
TOML_NODISCARD
|
||||
virtual node_type type() const noexcept = 0;
|
||||
|
||||
#else
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual node_type type() const noexcept
|
||||
{
|
||||
// Q: "what the fuck?"
|
||||
// A: https://github.com/marzer/tomlplusplus/issues/83
|
||||
// tl,dr: go home ICC, you're drunk.
|
||||
|
||||
return type();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// \brief Returns true if this node is a table.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_table() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is an array.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_array() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is a value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_value() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is a string value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_string() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is an integer value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_integer() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is an floating-point value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_floating_point() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is an integer or floating-point value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_number() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is a boolean value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_boolean() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is a local date value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_date() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is a local time value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_time() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is a date-time value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_date_time() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is an array containing only tables.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_array_of_tables() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Checks if a node is a specific type.
|
||||
///
|
||||
/// \tparam T A TOML node or value type.
|
||||
///
|
||||
/// \returns Returns true if this node is an instance of the specified type.
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
bool is() const noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert((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, 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();
|
||||
else if constexpr (std::is_same_v<type, date>)
|
||||
return is_date();
|
||||
else if constexpr (std::is_same_v<type, time>)
|
||||
return is_time();
|
||||
else if constexpr (std::is_same_v<type, date_time>)
|
||||
return is_date_time();
|
||||
}
|
||||
|
||||
/// \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();
|
||||
///
|
||||
/// 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
|
||||
/// array was not homogeneous!
|
||||
/// first non-match was a floating-point at line 1, column 18
|
||||
/// \eout
|
||||
///
|
||||
/// \param ntype A TOML node type. <br>
|
||||
/// \conditional_return{toml::node_type::none}
|
||||
/// "is every element the same type?"
|
||||
/// \conditional_return{Anything else}
|
||||
/// "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 node was homogeneous.
|
||||
///
|
||||
/// \remarks Always returns `false` for empty tables and arrays.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept = 0;
|
||||
|
||||
/// \brief Checks if a node contains values/elements of only one type (const overload).
|
||||
TOML_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.
|
||||
///
|
||||
/// \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>
|
||||
/// \conditional_return{toml::node_type::none}
|
||||
/// "is every element the same type?"
|
||||
/// \conditional_return{Anything else}
|
||||
/// "is every element one of these?"
|
||||
///
|
||||
/// \returns True if the node was homogeneous.
|
||||
///
|
||||
/// \remarks Always returns `false` for empty tables and arrays.
|
||||
TOML_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>
|
||||
/// \conditional_return{Left as `void`}
|
||||
/// "is every element the same type?" <br>
|
||||
/// \conditional_return{Explicitly specified}
|
||||
/// "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>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
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>);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Type casts
|
||||
/// @{
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::table, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual table* as_table() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::array, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual array* as_array() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::value<string>, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual toml::value<std::string>* as_string() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::value<int64_t>, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual toml::value<int64_t>* as_integer() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::value<double>, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual toml::value<double>* as_floating_point() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::value<bool>, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual toml::value<bool>* as_boolean() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::value<date>, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual toml::value<date>* as_date() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::value<time>, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual toml::value<time>* as_time() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::value<date_time>, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual toml::value<date_time>* as_date_time() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const table* as_table() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const array* as_array() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const toml::value<std::string>* as_string() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const toml::value<int64_t>* as_integer() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const toml::value<double>* as_floating_point() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const toml::value<bool>* as_boolean() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const toml::value<date>* as_date() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const toml::value<time>* as_time() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const toml::value<date_time>* as_date_time() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Gets a pointer to the node as a more specific node type.
|
||||
///
|
||||
/// \details \cpp
|
||||
///
|
||||
/// 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>\n";
|
||||
/// else if (tbl)
|
||||
/// 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>\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \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.
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
impl::wrap_node<T>* as() noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert((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, 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();
|
||||
else if constexpr (std::is_same_v<type, date>)
|
||||
return as_date();
|
||||
else if constexpr (std::is_same_v<type, time>)
|
||||
return as_time();
|
||||
else if constexpr (std::is_same_v<type, date_time>)
|
||||
return as_date_time();
|
||||
}
|
||||
|
||||
/// \brief Gets a pointer to the node as a more specific node type (const overload).
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
const impl::wrap_node<T>* as() const noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert((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, 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();
|
||||
else if constexpr (std::is_same_v<type, date>)
|
||||
return as_date();
|
||||
else if constexpr (std::is_same_v<type, time>)
|
||||
return as_time();
|
||||
else if constexpr (std::is_same_v<type, date_time>)
|
||||
return as_date_time();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Value retrieval
|
||||
/// @{
|
||||
|
||||
/// \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>
|
||||
TOML_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.
|
||||
///
|
||||
/// \note 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>
|
||||
TOML_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.
|
||||
///
|
||||
/// \note 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>
|
||||
TOML_NODISCARD
|
||||
auto value_or(T&& default_value) const noexcept;
|
||||
|
||||
// template <typename T>
|
||||
// TOML_NODISCARD
|
||||
// std::vector<T> select_exact() const noexcept;
|
||||
|
||||
// template <typename T>
|
||||
// TOML_NODISCARD
|
||||
// std::vector<T> select() const noexcept;
|
||||
|
||||
/// \brief Gets a raw reference to a value node's underlying data.
|
||||
///
|
||||
/// \warning This function is dangerous if used carelessly and **WILL** break your code if the
|
||||
/// chosen value type doesn't match the node's actual type. In debug builds an assertion
|
||||
/// will fire when invalid accesses are attempted: \cpp
|
||||
///
|
||||
/// auto tbl = toml::parse(R"(
|
||||
/// min = 32
|
||||
/// max = 45
|
||||
/// )"sv);
|
||||
///
|
||||
/// int64_t& min_ref = tbl.get("min")->ref<int64_t>(); // matching type
|
||||
/// double& max_ref = tbl.get("max")->ref<double>(); // mismatched type, hits assert()
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \tparam T One of the TOML value types.
|
||||
///
|
||||
/// \returns A reference to the underlying data.
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
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>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
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>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
const impl::unwrap_node<T>& ref() const& noexcept
|
||||
{
|
||||
return do_ref<T>(*this);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Metadata
|
||||
/// @{
|
||||
|
||||
/// \brief Returns the source region responsible for generating this node during parsing.
|
||||
TOML_NODISCARD
|
||||
const source_region& source() const noexcept
|
||||
{
|
||||
return source_;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
private:
|
||||
/// \cond
|
||||
|
||||
// clang-format off
|
||||
|
||||
template <typename Func, typename N, typename T>
|
||||
static constexpr bool can_visit = std::is_invocable_v<Func, ref_cast_type<N, T>>;
|
||||
|
||||
template <typename Func, typename N>
|
||||
static constexpr bool can_visit_any =
|
||||
can_visit<Func, N, table>
|
||||
|| can_visit<Func, N, array>
|
||||
|| can_visit<Func, N, std::string>
|
||||
|| can_visit<Func, N, int64_t>
|
||||
|| can_visit<Func, N, double>
|
||||
|| can_visit<Func, N, bool>
|
||||
|| can_visit<Func, N, date>
|
||||
|| can_visit<Func, N, time>
|
||||
|| can_visit<Func, N, date_time>;
|
||||
|
||||
template <typename Func, typename N>
|
||||
static constexpr bool can_visit_all =
|
||||
can_visit<Func, N, table>
|
||||
&& can_visit<Func, N, array>
|
||||
&& can_visit<Func, N, std::string>
|
||||
&& can_visit<Func, N, int64_t>
|
||||
&& can_visit<Func, N, double>
|
||||
&& can_visit<Func, N, bool>
|
||||
&& can_visit<Func, N, date>
|
||||
&& can_visit<Func, N, time>
|
||||
&& can_visit<Func, N, date_time>;
|
||||
|
||||
template <typename Func, typename N, typename T>
|
||||
static constexpr bool visit_is_nothrow_one =
|
||||
!can_visit<Func, N, T>
|
||||
|| std::is_nothrow_invocable_v<Func, ref_cast_type<N, T>>;
|
||||
|
||||
template <typename Func, typename N>
|
||||
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, std::string>
|
||||
&& visit_is_nothrow_one<Func, N, int64_t>
|
||||
&& visit_is_nothrow_one<Func, N, double>
|
||||
&& visit_is_nothrow_one<Func, N, bool>
|
||||
&& visit_is_nothrow_one<Func, N, date>
|
||||
&& visit_is_nothrow_one<Func, N, time>
|
||||
&& visit_is_nothrow_one<Func, N, date_time>;
|
||||
|
||||
// clang-format on
|
||||
|
||||
template <typename Func, typename N, typename T, bool = can_visit<Func, N, T>>
|
||||
struct visit_return_type_
|
||||
{
|
||||
using type = decltype(std::declval<Func>()(std::declval<ref_cast_type<N, T>>()));
|
||||
};
|
||||
template <typename Func, typename N, typename T>
|
||||
struct visit_return_type_<Func, N, T, false>
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
|
||||
template <typename Func, typename N, typename T>
|
||||
using visit_return_type = typename visit_return_type_<Func, N, T>::type;
|
||||
|
||||
template <typename A, typename B>
|
||||
using nonvoid = std::conditional_t<std::is_void_v<A>, B, A>;
|
||||
|
||||
//# these functions are static helpers to preserve const and ref categories
|
||||
//# (otherwise I'd have to implement them thrice)
|
||||
//# ((propagation in C++: a modern horror story))
|
||||
|
||||
template <typename N, typename Func>
|
||||
static decltype(auto) do_visit(N&& n, Func&& visitor) noexcept(visit_is_nothrow<Func&&, N&&>)
|
||||
{
|
||||
static_assert(can_visit_any<Func&&, N&&>,
|
||||
"TOML node visitors must be invocable for at least one of the toml::node "
|
||||
"specializations:" TOML_SA_NODE_TYPE_LIST);
|
||||
|
||||
switch (n.type())
|
||||
{
|
||||
case node_type::table:
|
||||
if constexpr (can_visit<Func&&, N&&, table>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<table>());
|
||||
break;
|
||||
|
||||
case node_type::array:
|
||||
if constexpr (can_visit<Func&&, N&&, array>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<array>());
|
||||
break;
|
||||
|
||||
case node_type::string:
|
||||
if constexpr (can_visit<Func&&, N&&, std::string>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<std::string>());
|
||||
break;
|
||||
|
||||
case node_type::integer:
|
||||
if constexpr (can_visit<Func&&, N&&, int64_t>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<int64_t>());
|
||||
break;
|
||||
|
||||
case node_type::floating_point:
|
||||
if constexpr (can_visit<Func&&, N&&, double>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<double>());
|
||||
break;
|
||||
|
||||
case node_type::boolean:
|
||||
if constexpr (can_visit<Func&&, N&&, bool>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<bool>());
|
||||
break;
|
||||
|
||||
case node_type::date:
|
||||
if constexpr (can_visit<Func&&, N&&, date>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<date>());
|
||||
break;
|
||||
|
||||
case node_type::time:
|
||||
if constexpr (can_visit<Func&&, N&&, time>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<time>());
|
||||
break;
|
||||
|
||||
case node_type::date_time:
|
||||
if constexpr (can_visit<Func&&, N&&, date_time>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<date_time>());
|
||||
break;
|
||||
|
||||
case node_type::none: TOML_UNREACHABLE;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
if constexpr (can_visit_all<Func&&, N&&>)
|
||||
TOML_UNREACHABLE;
|
||||
else
|
||||
{
|
||||
// clang-format off
|
||||
|
||||
using return_type =
|
||||
nonvoid<visit_return_type<Func&&, N&&, table>,
|
||||
nonvoid<visit_return_type<Func&&, N&&, array>,
|
||||
nonvoid<visit_return_type<Func&&, N&&, std::string>,
|
||||
nonvoid<visit_return_type<Func&&, N&&, int64_t>,
|
||||
nonvoid<visit_return_type<Func&&, N&&, double>,
|
||||
nonvoid<visit_return_type<Func&&, N&&, bool>,
|
||||
nonvoid<visit_return_type<Func&&, N&&, date>,
|
||||
nonvoid<visit_return_type<Func&&, N&&, time>,
|
||||
visit_return_type<Func&&, N&&, date_time>
|
||||
>>>>>>>>;
|
||||
|
||||
// clang-format on
|
||||
|
||||
if constexpr (!std::is_void_v<return_type>)
|
||||
{
|
||||
static_assert(std::is_default_constructible_v<return_type>,
|
||||
"Non-exhaustive visitors must return a default-constructible type, or void");
|
||||
return return_type{};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
public:
|
||||
/// \name Visitation
|
||||
/// @{
|
||||
|
||||
/// \brief Invokes a visitor on the node based on the node's concrete type.
|
||||
///
|
||||
/// \details Visitation is useful when you expect
|
||||
/// a node to be one of a set number of types and need
|
||||
/// to handle these types differently. Using `visit()` allows
|
||||
/// you to eliminate some of the casting/conversion boilerplate: \cpp
|
||||
///
|
||||
/// node.visit([](auto&& n)
|
||||
/// {
|
||||
/// if constexpr (toml::is_string<decltype(n)>)
|
||||
/// 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
|
||||
/// throw std::exception{ "Expected string or integer" };
|
||||
/// });
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \tparam Func A callable type invocable with one or more of the
|
||||
/// toml++ node types.
|
||||
///
|
||||
/// \param visitor The visitor object.
|
||||
///
|
||||
/// \returns The return value of the visitor.
|
||||
/// Can be void. Non-exhaustive visitors must return a default-constructible type.
|
||||
///
|
||||
/// \see https://en.wikipedia.org/wiki/Visitor_pattern
|
||||
template <typename Func>
|
||||
decltype(auto) visit(Func&& visitor) & noexcept(visit_is_nothrow<Func&&, node&>)
|
||||
{
|
||||
return do_visit(*this, static_cast<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&&>)
|
||||
{
|
||||
return do_visit(static_cast<node&&>(*this), static_cast<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&>)
|
||||
{
|
||||
return do_visit(*this, static_cast<Func&&>(visitor));
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Node views
|
||||
/// @{
|
||||
|
||||
/// \brief Creates a node_view pointing to this node.
|
||||
TOML_NODISCARD
|
||||
explicit operator node_view<node>() noexcept;
|
||||
|
||||
/// \brief Creates a node_view pointing to this node (const overload).
|
||||
TOML_NODISCARD
|
||||
explicit operator node_view<const node>() const noexcept;
|
||||
|
||||
/// @}
|
||||
};
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
62
include/toml++/impl/node_impl.h
Normal file
62
include/toml++/impl/node_impl.h
Normal file
@ -0,0 +1,62 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "node.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node::node(node && other) noexcept //
|
||||
: source_{ std::exchange(other.source_, {}) }
|
||||
{}
|
||||
|
||||
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::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
|
||||
{
|
||||
if (&rhs != this)
|
||||
source_ = std::exchange(rhs.source_, {});
|
||||
return *this;
|
||||
}
|
||||
|
||||
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;
|
815
include/toml++/impl/node_view.h
Normal file
815
include/toml++/impl/node_view.h
Normal file
@ -0,0 +1,815 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "table.h"
|
||||
#include "array.h"
|
||||
#include "value.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_ARITHMETIC_WARNINGS;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A view of a node.
|
||||
///
|
||||
/// \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"(
|
||||
///
|
||||
/// title = "my hardware store"
|
||||
///
|
||||
/// [[products]]
|
||||
/// name = "Hammer"
|
||||
/// sku = 738594937
|
||||
/// keywords = [ "hammer", "construction", "build" ]
|
||||
///
|
||||
/// [[products]]
|
||||
/// name = "Nail"
|
||||
/// sku = 284758393
|
||||
/// color = "gray"
|
||||
///
|
||||
/// )"sv);
|
||||
///
|
||||
/// 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"] << "\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"
|
||||
/// "Hammer"
|
||||
/// [ "hammer", "construction", "build" ]
|
||||
/// "build"
|
||||
/// [ "hammer", "construction", "build", "heavy" ]
|
||||
/// has product[2]: false
|
||||
/// product[2]:
|
||||
/// \eout
|
||||
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 = ViewedType;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
friend class TOML_NAMESPACE::node_view;
|
||||
|
||||
mutable viewed_type* node_ = nullptr;
|
||||
|
||||
template <typename Func>
|
||||
static constexpr bool visit_is_nothrow = noexcept(std::declval<viewed_type*>()->visit(std::declval<Func&&>()));
|
||||
|
||||
public:
|
||||
/// \brief Constructs an empty node view.
|
||||
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.
|
||||
TOML_NODISCARD
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return node_ != nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns the node that's being referenced by the view.
|
||||
TOML_NODISCARD
|
||||
viewed_type* node() const noexcept
|
||||
{
|
||||
return node_;
|
||||
}
|
||||
|
||||
/// \name Type checks
|
||||
/// @{
|
||||
|
||||
/// \brief Returns the type identifier for the viewed node.
|
||||
TOML_NODISCARD
|
||||
node_type type() const noexcept
|
||||
{
|
||||
return node_ ? node_->type() : node_type::none;
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::table.
|
||||
TOML_NODISCARD
|
||||
bool is_table() const noexcept
|
||||
{
|
||||
return node_ && node_->is_table();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::array.
|
||||
TOML_NODISCARD
|
||||
bool is_array() const noexcept
|
||||
{
|
||||
return node_ && node_->is_array();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<>.
|
||||
TOML_NODISCARD
|
||||
bool is_value() const noexcept
|
||||
{
|
||||
return node_ && node_->is_value();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<string>.
|
||||
TOML_NODISCARD
|
||||
bool is_string() const noexcept
|
||||
{
|
||||
return node_ && node_->is_string();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<int64_t>.
|
||||
TOML_NODISCARD
|
||||
bool is_integer() const noexcept
|
||||
{
|
||||
return node_ && node_->is_integer();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<double>.
|
||||
TOML_NODISCARD
|
||||
bool is_floating_point() const noexcept
|
||||
{
|
||||
return node_ && node_->is_floating_point();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<int64_t> or toml::value<double>.
|
||||
TOML_NODISCARD
|
||||
bool is_number() const noexcept
|
||||
{
|
||||
return node_ && node_->is_number();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<bool>.
|
||||
TOML_NODISCARD
|
||||
bool is_boolean() const noexcept
|
||||
{
|
||||
return node_ && node_->is_boolean();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<date>.
|
||||
TOML_NODISCARD
|
||||
bool is_date() const noexcept
|
||||
{
|
||||
return node_ && node_->is_date();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<time>.
|
||||
TOML_NODISCARD
|
||||
bool is_time() const noexcept
|
||||
{
|
||||
return node_ && node_->is_time();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<date_time>.
|
||||
TOML_NODISCARD
|
||||
bool is_date_time() const noexcept
|
||||
{
|
||||
return node_ && node_->is_date_time();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::array that contains only tables.
|
||||
TOML_NODISCARD
|
||||
bool is_array_of_tables() const noexcept
|
||||
{
|
||||
return node_ && node_->is_array_of_tables();
|
||||
}
|
||||
|
||||
/// \brief Checks if this view references a node of a specific 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 T>
|
||||
TOML_NODISCARD
|
||||
bool is() const noexcept
|
||||
{
|
||||
return node_ ? node_->template is<T>() : false;
|
||||
}
|
||||
|
||||
/// \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>
|
||||
/// \conditional_return{toml::node_type::none} "is every element the same type?"
|
||||
/// \conditional_return{Anything else} "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.
|
||||
TOML_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>
|
||||
/// \conditional_return{toml::node_type::none} "is every element the same type?"
|
||||
/// \conditional_return{Anything else} "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.
|
||||
TOML_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>
|
||||
/// \conditional_return{Left as `void`} "is every element the same type?" <br>
|
||||
/// \conditional_return{Explicitly specified} "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>
|
||||
TOML_NODISCARD
|
||||
bool is_homogeneous() const noexcept
|
||||
{
|
||||
return node_ ? node_->template is_homogeneous<impl::unwrap_node<ElemType>>() : false;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Type casts
|
||||
/// @{
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::table, if it is one.
|
||||
TOML_NODISCARD
|
||||
auto as_table() const noexcept
|
||||
{
|
||||
return as<table>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::array, if it is one.
|
||||
TOML_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.
|
||||
TOML_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.
|
||||
TOML_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.
|
||||
TOML_NODISCARD
|
||||
auto as_floating_point() const noexcept
|
||||
{
|
||||
return as<double>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<bool>, if it is one.
|
||||
TOML_NODISCARD
|
||||
auto as_boolean() const noexcept
|
||||
{
|
||||
return as<bool>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<date>, if it is one.
|
||||
TOML_NODISCARD
|
||||
auto as_date() const noexcept
|
||||
{
|
||||
return as<date>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<time>, if it is one.
|
||||
TOML_NODISCARD
|
||||
auto as_time() const noexcept
|
||||
{
|
||||
return as<time>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<date_time>, if it is one.
|
||||
TOML_NODISCARD
|
||||
auto as_date_time() const noexcept
|
||||
{
|
||||
return as<date_time>();
|
||||
}
|
||||
|
||||
/// \brief Gets a pointer to the viewed node as a more specific node type.
|
||||
///
|
||||
/// \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 T>
|
||||
TOML_NODISCARD
|
||||
auto as() const noexcept
|
||||
{
|
||||
return node_ ? node_->template as<T>() : nullptr;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Value retrieval
|
||||
/// @{
|
||||
|
||||
/// \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>
|
||||
TOML_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 value contained by the referenced 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. 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)
|
||||
/// and within the range of the output type, or an empty optional.
|
||||
///
|
||||
/// \note 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>
|
||||
TOML_NODISCARD
|
||||
optional<T> value() const noexcept
|
||||
{
|
||||
if (node_)
|
||||
return node_->template value<T>();
|
||||
return {};
|
||||
}
|
||||
|
||||
TOML_POP_WARNINGS;
|
||||
|
||||
/// \brief Gets the raw value contained by the referenced 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.
|
||||
///
|
||||
/// \note 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>
|
||||
TOML_NODISCARD
|
||||
auto value_or(T&& default_value) const noexcept
|
||||
{
|
||||
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(static_cast<T&&>(default_value));
|
||||
return std::wstring{ static_cast<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(static_cast<T&&>(default_value));
|
||||
if constexpr (std::is_pointer_v<value_type>)
|
||||
return value_type{ default_value };
|
||||
else
|
||||
return static_cast<T&&>(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Gets a raw reference to the viewed node's underlying data.
|
||||
///
|
||||
/// \warning This function is dangerous if used carelessly and **WILL** break your code if the
|
||||
/// node_view didn't reference a node, or the chosen value type doesn't match the node's
|
||||
/// actual type. In debug builds an assertion will fire when invalid accesses are attempted: \cpp
|
||||
///
|
||||
/// auto tbl = toml::parse(R"(
|
||||
/// min = 32
|
||||
/// max = 45
|
||||
/// )"sv);
|
||||
///
|
||||
/// int64_t& min_ref = tbl["min"].ref<int64_t>(); // matching type
|
||||
/// double& max_ref = tbl["max"].ref<double>(); // mismatched type, hits assert()
|
||||
/// int64_t& foo_ref = tbl["foo"].ref<int64_t>(); // nonexistent key, hits assert()
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \tparam T One of the TOML value types.
|
||||
///
|
||||
/// \returns A reference to the underlying data.
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
decltype(auto) ref() const noexcept
|
||||
{
|
||||
TOML_ASSERT(node_ && "toml::node_view::ref() called on a node_view that did not reference a node");
|
||||
return node_->template ref<impl::unwrap_node<T>>();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Visitation
|
||||
/// @{
|
||||
|
||||
/// \brief Invokes a visitor on the viewed node based on its concrete type.
|
||||
///
|
||||
/// \remarks Has no effect if the view does not reference a node.
|
||||
///
|
||||
/// \see node::visit()
|
||||
template <typename Func>
|
||||
decltype(auto) visit(Func&& visitor) const noexcept(visit_is_nothrow<Func&&>)
|
||||
{
|
||||
using return_type = decltype(node_->visit(static_cast<Func&&>(visitor)));
|
||||
if (node_)
|
||||
return node_->visit(static_cast<Func&&>(visitor));
|
||||
if constexpr (!std::is_void_v<return_type>)
|
||||
return return_type{};
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Equality
|
||||
/// @{
|
||||
|
||||
/// \brief Returns true if the viewed node is a table with the same contents as RHS.
|
||||
TOML_NODISCARD
|
||||
friend bool operator==(const node_view& lhs, const table& rhs) noexcept
|
||||
{
|
||||
if (lhs.node_ == &rhs)
|
||||
return true;
|
||||
const auto tbl = lhs.as<table>();
|
||||
return tbl && *tbl == rhs;
|
||||
}
|
||||
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.
|
||||
TOML_NODISCARD
|
||||
friend bool operator==(const node_view& lhs, const array& rhs) noexcept
|
||||
{
|
||||
if (lhs.node_ == &rhs)
|
||||
return true;
|
||||
const auto arr = lhs.as<array>();
|
||||
return arr && *arr == rhs;
|
||||
}
|
||||
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 T>
|
||||
TOML_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<T>();
|
||||
return val && *val == rhs;
|
||||
}
|
||||
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.
|
||||
TOML_CONSTRAINED_TEMPLATE((impl::is_native<T> || impl::is_losslessly_convertible_to_native<T>), typename T)
|
||||
TOML_NODISCARD
|
||||
friend bool operator==(const node_view& lhs, const T& rhs) noexcept
|
||||
{
|
||||
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 T&,
|
||||
TOML_CONSTRAINED_TEMPLATE((impl::is_native<T> || impl::is_losslessly_convertible_to_native<T>),
|
||||
typename T));
|
||||
|
||||
/// \brief Returns true if the viewed node is an array with the same contents as the RHS initializer list.
|
||||
template <typename T>
|
||||
TOML_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<T>&, template <typename T>);
|
||||
|
||||
/// \brief Returns true if the viewed node is an array with the same contents as the RHS vector.
|
||||
template <typename T>
|
||||
TOML_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<T>&, template <typename T>);
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Subviews
|
||||
/// @{
|
||||
|
||||
/// \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.
|
||||
TOML_NODISCARD
|
||||
node_view operator[](std::string_view key) const noexcept
|
||||
{
|
||||
if (auto tbl = this->as_table())
|
||||
return node_view{ tbl->get(key) };
|
||||
return node_view{ nullptr };
|
||||
}
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Returns a view of the selected subnode.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \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.
|
||||
TOML_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.
|
||||
TOML_NODISCARD
|
||||
node_view operator[](size_t index) const noexcept
|
||||
{
|
||||
if (auto arr = this->as_array())
|
||||
return node_view{ arr->get(index) };
|
||||
return node_view{ nullptr };
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
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>
|
||||
inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& os, const node_view<T>& nv)
|
||||
{
|
||||
if (nv.node_)
|
||||
{
|
||||
nv.node_->visit([&os](const auto& n) { os << n; });
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
#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);
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
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
|
||||
|
||||
#endif // !TOML_HEADER_ONLY
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_ARITHMETIC_WARNINGS
|
150
include/toml++/impl/parse_error.h
Normal file
150
include/toml++/impl/parse_error.h
Normal file
@ -0,0 +1,150 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_PARSER
|
||||
#error This header cannot not be included when TOML_PARSER is disabled.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_INIT_WARNINGS;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex);
|
||||
|
||||
#if defined(DOXYGEN) || !TOML_EXCEPTIONS
|
||||
|
||||
/// \brief An error generated when parsing fails.
|
||||
///
|
||||
/// \remarks This class inherits from std::runtime_error when exceptions are enabled.
|
||||
/// The public interface is the same regardless of exception mode.
|
||||
class parse_error final
|
||||
{
|
||||
private:
|
||||
std::string description_;
|
||||
source_region source_;
|
||||
|
||||
public:
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(std::string&& desc, source_region&& src) noexcept
|
||||
: description_{ std::move(desc) },
|
||||
source_{ std::move(src) }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(std::string&& desc, const source_region& src) noexcept
|
||||
: parse_error{ std::move(desc), source_region{ src } }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(std::string&& desc, const source_position& position, const source_path_ptr& path = {}) noexcept
|
||||
: parse_error{ std::move(desc), source_region{ position, position, path } }
|
||||
{}
|
||||
|
||||
/// \brief Returns a textual description of the error.
|
||||
/// \remark The backing string is guaranteed to be null-terminated.
|
||||
TOML_NODISCARD
|
||||
std::string_view description() const noexcept
|
||||
{
|
||||
return description_;
|
||||
}
|
||||
|
||||
/// \brief Returns the region of the source document responsible for the error.
|
||||
TOML_NODISCARD
|
||||
const source_region& source() const noexcept
|
||||
{
|
||||
return source_;
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class parse_error final : public std::runtime_error
|
||||
{
|
||||
private:
|
||||
source_region source_;
|
||||
|
||||
public:
|
||||
TOML_NODISCARD_CTOR
|
||||
TOML_ATTR(nonnull)
|
||||
parse_error(const char* desc, source_region&& src) noexcept
|
||||
: std::runtime_error{ desc },
|
||||
source_{ std::move(src) }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
TOML_ATTR(nonnull)
|
||||
parse_error(const char* desc, const source_region& src) noexcept : parse_error{ desc, source_region{ src } }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
TOML_ATTR(nonnull)
|
||||
parse_error(const char* desc, const source_position& position, const source_path_ptr& path = {}) noexcept
|
||||
: parse_error{ desc, source_region{ position, position, path } }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD
|
||||
std::string_view description() const noexcept
|
||||
{
|
||||
return std::string_view{ what() };
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
const source_region& source() const noexcept
|
||||
{
|
||||
return source_;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
|
||||
/// \brief Prints a parse_error to a stream.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// try
|
||||
/// {
|
||||
/// auto tbl = toml::parse("enabled = trUe"sv);
|
||||
/// }
|
||||
/// catch (const toml::parse_error & err)
|
||||
/// {
|
||||
/// std::cerr << "Parsing failed:\n"sv << err << "\n";
|
||||
/// }
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// Parsing failed:
|
||||
/// Encountered unexpected character while parsing boolean; expected 'true', saw 'trU'
|
||||
/// (error occurred at line 1, column 13)
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Char The output stream's underlying character type. Must be 1 byte in size.
|
||||
/// \param lhs The stream.
|
||||
/// \param rhs The parse_error.
|
||||
///
|
||||
/// \returns The input stream.
|
||||
template <typename Char>
|
||||
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;
|
||||
lhs << rhs.source();
|
||||
lhs << ")"sv;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
#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_DISABLE_INIT_WARNINGS
|
389
include/toml++/impl/parse_result.h
Normal file
389
include/toml++/impl/parse_result.h
Normal file
@ -0,0 +1,389 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_PARSER
|
||||
#error This header cannot not be included when TOML_PARSER is disabled.
|
||||
#endif
|
||||
//# }}
|
||||
#include "table.h"
|
||||
#include "parse_error.h"
|
||||
|
||||
#if defined(DOXYGEN) || !TOML_EXCEPTIONS
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_ABI_NAMESPACE_START(noex);
|
||||
|
||||
/// \brief The result of a parsing operation.
|
||||
///
|
||||
/// \detail A parse_result is effectively a discriminated union containing either a toml::table
|
||||
/// or a toml::parse_error. Most member functions assume a particular one of these two states,
|
||||
/// and calling them when in the wrong state will cause errors (e.g. attempting to access the
|
||||
/// error object when parsing was successful). \cpp
|
||||
/// parse_result result = toml::parse_file("config.toml");
|
||||
/// if (result)
|
||||
/// do_stuff_with_a_table(result); //implicitly converts to table&
|
||||
/// else
|
||||
/// std::cerr << "Parse failed:\n"sv << result.error() << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// example output:
|
||||
///
|
||||
/// Parse failed:
|
||||
/// Encountered unexpected character while parsing boolean; expected 'true', saw 'trU'
|
||||
/// (error occurred at line 1, column 13 of 'config.toml')
|
||||
/// \eout
|
||||
///
|
||||
/// Getting node_views (`operator[]`) and using the iterator accessor functions (`begin(), end()` etc.) are
|
||||
/// unconditionally safe; when parsing fails these just return 'empty' values. A ranged-for loop on a failed
|
||||
/// parse_result is also safe since `begin()` and `end()` return the same iterator and will not lead to any
|
||||
/// dereferences and iterations.
|
||||
///
|
||||
/// \availability <strong>This type only exists when exceptions are disabled.</strong>
|
||||
/// Otherwise parse_result is just an alias for toml::table: \cpp
|
||||
/// #if TOML_EXCEPTIONS
|
||||
/// using parse_result = table;
|
||||
/// #else
|
||||
/// class parse_result final { // ...
|
||||
/// #endif
|
||||
/// \ecpp
|
||||
class parse_result
|
||||
{
|
||||
private:
|
||||
struct storage_t
|
||||
{
|
||||
static constexpr size_t size_ =
|
||||
(sizeof(toml::table) < sizeof(parse_error) ? sizeof(parse_error) : sizeof(toml::table));
|
||||
static constexpr size_t align_ =
|
||||
(alignof(toml::table) < alignof(parse_error) ? alignof(parse_error) : alignof(toml::table));
|
||||
|
||||
alignas(align_) unsigned char bytes[size_];
|
||||
};
|
||||
|
||||
mutable storage_t storage_;
|
||||
bool err_;
|
||||
|
||||
template <typename Type>
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
static Type* get_as(storage_t& s) noexcept
|
||||
{
|
||||
return TOML_LAUNDER(reinterpret_cast<Type*>(s.bytes));
|
||||
}
|
||||
|
||||
void destroy() noexcept
|
||||
{
|
||||
if (err_)
|
||||
get_as<parse_error>(storage_)->~parse_error();
|
||||
else
|
||||
get_as<toml::table>(storage_)->~table();
|
||||
}
|
||||
|
||||
public:
|
||||
/// \brief A BidirectionalIterator for iterating over key-value pairs in a wrapped toml::table.
|
||||
using iterator = table_iterator;
|
||||
|
||||
/// \brief A BidirectionalIterator for iterating over const key-value pairs in a wrapped toml::table.
|
||||
using const_iterator = const_table_iterator;
|
||||
|
||||
/// \brief Returns true if parsing succeeeded.
|
||||
TOML_NODISCARD
|
||||
bool succeeded() const noexcept
|
||||
{
|
||||
return !err_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if parsing failed.
|
||||
TOML_NODISCARD
|
||||
bool failed() const noexcept
|
||||
{
|
||||
return err_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if parsing succeeded.
|
||||
TOML_NODISCARD
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return !err_;
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table.
|
||||
TOML_NODISCARD
|
||||
toml::table& table() & noexcept
|
||||
{
|
||||
TOML_ASSERT(!err_);
|
||||
return *get_as<toml::table>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
toml::table&& table() && noexcept
|
||||
{
|
||||
TOML_ASSERT(!err_);
|
||||
return static_cast<toml::table&&>(*get_as<toml::table>(storage_));
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table (const lvalue overload).
|
||||
TOML_NODISCARD
|
||||
const toml::table& table() const& noexcept
|
||||
{
|
||||
TOML_ASSERT(!err_);
|
||||
return *get_as<const toml::table>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error.
|
||||
TOML_NODISCARD
|
||||
parse_error& error() & noexcept
|
||||
{
|
||||
TOML_ASSERT(err_);
|
||||
return *get_as<parse_error>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
parse_error&& error() && noexcept
|
||||
{
|
||||
TOML_ASSERT(err_);
|
||||
return static_cast<parse_error&&>(*get_as<parse_error>(storage_));
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error (const lvalue overload).
|
||||
TOML_NODISCARD
|
||||
const parse_error& error() const& noexcept
|
||||
{
|
||||
TOML_ASSERT(err_);
|
||||
return *get_as<const parse_error>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table.
|
||||
TOML_NODISCARD
|
||||
operator toml::table&() noexcept
|
||||
{
|
||||
return table();
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
operator toml::table&&() noexcept
|
||||
{
|
||||
return std::move(table());
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table (const lvalue overload).
|
||||
TOML_NODISCARD
|
||||
operator const toml::table&() const noexcept
|
||||
{
|
||||
return table();
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error.
|
||||
TOML_NODISCARD
|
||||
explicit operator parse_error&() noexcept
|
||||
{
|
||||
return error();
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
explicit operator parse_error&&() noexcept
|
||||
{
|
||||
return std::move(error());
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error (const lvalue overload).
|
||||
TOML_NODISCARD
|
||||
explicit operator const parse_error&() const noexcept
|
||||
{
|
||||
return error();
|
||||
}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_result() noexcept //
|
||||
: err_{ true }
|
||||
{
|
||||
::new (static_cast<void*>(storage_.bytes)) parse_error{ std::string{}, source_region{} };
|
||||
}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit parse_result(toml::table&& tbl) noexcept //
|
||||
: err_{ false }
|
||||
{
|
||||
::new (static_cast<void*>(storage_.bytes)) toml::table{ std::move(tbl) };
|
||||
}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit parse_result(parse_error&& err) noexcept //
|
||||
: err_{ true }
|
||||
{
|
||||
::new (static_cast<void*>(storage_.bytes)) parse_error{ std::move(err) };
|
||||
}
|
||||
|
||||
/// \brief Move constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_result(parse_result&& res) noexcept //
|
||||
: err_{ res.err_ }
|
||||
{
|
||||
if (err_)
|
||||
::new (static_cast<void*>(storage_.bytes)) parse_error{ std::move(res).error() };
|
||||
else
|
||||
::new (static_cast<void*>(storage_.bytes)) toml::table{ std::move(res).table() };
|
||||
}
|
||||
|
||||
/// \brief Move-assignment operator.
|
||||
parse_result& operator=(parse_result&& rhs) noexcept
|
||||
{
|
||||
if (err_ != rhs.err_)
|
||||
{
|
||||
destroy();
|
||||
err_ = rhs.err_;
|
||||
if (err_)
|
||||
::new (static_cast<void*>(storage_.bytes)) parse_error{ std::move(rhs).error() };
|
||||
else
|
||||
::new (static_cast<void*>(storage_.bytes)) toml::table{ std::move(rhs).table() };
|
||||
}
|
||||
else
|
||||
{
|
||||
if (err_)
|
||||
error() = std::move(rhs).error();
|
||||
else
|
||||
table() = std::move(rhs).table();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Destructor.
|
||||
~parse_result() noexcept
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
/// \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
|
||||
TOML_NODISCARD
|
||||
node_view<node> operator[](string_view key) noexcept
|
||||
{
|
||||
return 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
|
||||
TOML_NODISCARD
|
||||
node_view<const node> operator[](string_view key) const noexcept
|
||||
{
|
||||
return 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.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \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
|
||||
TOML_NODISCARD
|
||||
node_view<node> operator[](std::wstring_view key) noexcept
|
||||
{
|
||||
return err_ ? node_view<node>{} : table()[key];
|
||||
}
|
||||
|
||||
/// \brief Gets a node_view for the selected key-value pair in the wrapped table (const overload).
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \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
|
||||
TOML_NODISCARD
|
||||
node_view<const node> operator[](std::wstring_view key) const noexcept
|
||||
{
|
||||
return 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.
|
||||
TOML_NODISCARD
|
||||
table_iterator begin() noexcept
|
||||
{
|
||||
return 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.
|
||||
TOML_NODISCARD
|
||||
const_table_iterator begin() const noexcept
|
||||
{
|
||||
return 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.
|
||||
TOML_NODISCARD
|
||||
const_table_iterator cbegin() const noexcept
|
||||
{
|
||||
return 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.
|
||||
TOML_NODISCARD
|
||||
table_iterator end() noexcept
|
||||
{
|
||||
return 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.
|
||||
TOML_NODISCARD
|
||||
const_table_iterator end() const noexcept
|
||||
{
|
||||
return 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.
|
||||
TOML_NODISCARD
|
||||
const_table_iterator cend() const noexcept
|
||||
{
|
||||
return err_ ? const_table_iterator{} : table().cend();
|
||||
}
|
||||
|
||||
/// \brief Prints the held error or table object out to a text stream.
|
||||
template <typename Char>
|
||||
friend std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& os, const parse_result& result)
|
||||
{
|
||||
return result.err_ ? (os << result.error()) : (os << result.table());
|
||||
}
|
||||
};
|
||||
|
||||
TOML_ABI_NAMESPACE_END;
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
#endif // !TOML_EXCEPTIONS
|
@ -5,30 +5,28 @@
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "toml_preprocessor.h"
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_PARSER
|
||||
#error This header cannot not be included when TOML_PARSER is disabled.
|
||||
#endif
|
||||
//# }}
|
||||
#include "toml_table.h"
|
||||
#include "toml_parse_error.h"
|
||||
#include "toml_parse_result.h"
|
||||
#include "toml_utf8_streams.h"
|
||||
#include "table.h"
|
||||
#include "parse_error.h"
|
||||
#include "parse_result.h"
|
||||
#include "utf8_streams.h"
|
||||
|
||||
/// \cond
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex);
|
||||
|
||||
[[nodiscard]]
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result do_parse(utf8_reader_interface&&) TOML_MAY_THROW;
|
||||
|
||||
parse_result do_parse(utf8_reader_interface &&) TOML_MAY_THROW;
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
|
||||
/// \endcond
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
@ -40,13 +38,13 @@ TOML_NAMESPACE_START
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("a = 3"sv);
|
||||
/// 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)
|
||||
@ -56,22 +54,22 @@ TOML_NAMESPACE_START
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
[[nodiscard]]
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::string_view doc, std::string_view source_path = {}) TOML_MAY_THROW;
|
||||
|
||||
/// \brief Parses a TOML document from a string view.
|
||||
///
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("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)
|
||||
@ -81,26 +79,26 @@ TOML_NAMESPACE_START
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
[[nodiscard]]
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::string_view doc, std::string&& source_path) TOML_MAY_THROW;
|
||||
parse_result parse(std::string_view doc, std::string && source_path) TOML_MAY_THROW;
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Parses a TOML document from a string view.
|
||||
///
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("a = 3"sv, L"foo.toml");
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
///
|
||||
/// \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)
|
||||
@ -110,26 +108,26 @@ TOML_NAMESPACE_START
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
[[nodiscard]]
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::string_view doc, std::wstring_view source_path) TOML_MAY_THROW;
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
#if TOML_HAS_CHAR8
|
||||
|
||||
/// \brief Parses a TOML document from a char8_t string view.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse(u8"a = 3"sv);
|
||||
/// 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)
|
||||
@ -139,22 +137,22 @@ TOML_NAMESPACE_START
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
[[nodiscard]]
|
||||
TOML_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)
|
||||
@ -164,25 +162,25 @@ TOML_NAMESPACE_START
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
[[nodiscard]]
|
||||
TOML_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::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
|
||||
///
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
///
|
||||
/// \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)
|
||||
@ -192,29 +190,29 @@ TOML_NAMESPACE_START
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
[[nodiscard]]
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::u8string_view doc, std::wstring_view source_path) TOML_MAY_THROW;
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
#endif // TOML_HAS_CHAR8
|
||||
#endif // TOML_HAS_CHAR8
|
||||
|
||||
/// \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`.
|
||||
@ -226,13 +224,10 @@ TOML_NAMESPACE_START
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
template <typename Char>
|
||||
[[nodiscard]]
|
||||
inline parse_result parse(std::basic_istream<Char>& doc, std::string_view source_path = {}) TOML_MAY_THROW
|
||||
TOML_NODISCARD
|
||||
inline parse_result parse(std::basic_istream<Char> & doc, std::string_view source_path = {}) TOML_MAY_THROW
|
||||
{
|
||||
static_assert(
|
||||
sizeof(Char) == 1,
|
||||
"The stream's underlying character type must be 1 byte in size."
|
||||
);
|
||||
static_assert(sizeof(Char) == 1, "The stream's underlying character type must be 1 byte in size.");
|
||||
|
||||
return impl::do_parse(impl::utf8_reader{ doc, source_path });
|
||||
}
|
||||
@ -242,16 +237,16 @@ TOML_NAMESPACE_START
|
||||
/// \detail \cpp
|
||||
/// std::stringstream ss;
|
||||
/// ss << "a = 3"sv;
|
||||
///
|
||||
///
|
||||
/// auto tbl = toml::parse(ss, "foo.toml");
|
||||
/// 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`.
|
||||
@ -263,36 +258,33 @@ TOML_NAMESPACE_START
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
template <typename Char>
|
||||
[[nodiscard]]
|
||||
inline parse_result parse(std::basic_istream<Char>& doc, std::string&& source_path) TOML_MAY_THROW
|
||||
TOML_NODISCARD
|
||||
inline parse_result parse(std::basic_istream<Char> & doc, std::string && source_path) TOML_MAY_THROW
|
||||
{
|
||||
static_assert(
|
||||
sizeof(Char) == 1,
|
||||
"The stream's underlying character type must be 1 byte in size."
|
||||
);
|
||||
static_assert(sizeof(Char) == 1, "The stream's underlying character type must be 1 byte in size.");
|
||||
|
||||
return impl::do_parse(impl::utf8_reader{ doc, std::move(source_path) });
|
||||
}
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
#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
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
///
|
||||
/// \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`.
|
||||
@ -304,18 +296,20 @@ TOML_NAMESPACE_START
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
template <typename Char>
|
||||
[[nodiscard]]
|
||||
inline parse_result parse(std::basic_istream<Char>& doc, std::wstring_view source_path) TOML_MAY_THROW
|
||||
TOML_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
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
#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;
|
||||
#endif
|
||||
#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;
|
||||
#endif
|
||||
|
||||
/// \brief Parses a TOML document from a file.
|
||||
///
|
||||
@ -325,18 +319,18 @@ TOML_NAMESPACE_START
|
||||
/// return toml::parse_file("foo.toml");
|
||||
/// }
|
||||
/// \ecpp
|
||||
///
|
||||
///
|
||||
/// \param file_path The TOML document to parse. Must be valid UTF-8.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
[[nodiscard]]
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse_file(std::string_view file_path) TOML_MAY_THROW;
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
#if TOML_HAS_CHAR8
|
||||
|
||||
/// \brief Parses a TOML document from a file.
|
||||
///
|
||||
@ -346,20 +340,20 @@ TOML_NAMESPACE_START
|
||||
/// return toml::parse_file(u8"foo.toml");
|
||||
/// }
|
||||
/// \ecpp
|
||||
///
|
||||
///
|
||||
/// \param file_path The TOML document to parse. Must be valid UTF-8.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
[[nodiscard]]
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse_file(std::u8string_view file_path) TOML_MAY_THROW;
|
||||
|
||||
#endif // TOML_HAS_CHAR8
|
||||
#endif // TOML_HAS_CHAR8
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Parses a TOML document from a file.
|
||||
///
|
||||
@ -378,11 +372,11 @@ TOML_NAMESPACE_START
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
[[nodiscard]]
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse_file(std::wstring_view file_path) TOML_MAY_THROW;
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
|
||||
@ -391,19 +385,19 @@ TOML_NAMESPACE_START
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, lit_ex, lit_noex);
|
||||
|
||||
/// \brief Parses TOML data from a string literal.
|
||||
///
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// using namespace toml::literals;
|
||||
///
|
||||
///
|
||||
/// auto tbl = "a = 3"_toml;
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
///
|
||||
/// \param str The string data. Must be valid UTF-8.
|
||||
/// \param len The string length.
|
||||
///
|
||||
@ -411,26 +405,26 @@ TOML_NAMESPACE_START
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
[[nodiscard]]
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result operator"" _toml(const char* str, size_t len) TOML_MAY_THROW;
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
#if TOML_HAS_CHAR8
|
||||
|
||||
/// \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"] << "\n";
|
||||
///
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
///
|
||||
/// \param str The string data. Must be valid UTF-8.
|
||||
/// \param len The string length.
|
||||
///
|
||||
@ -438,11 +432,11 @@ TOML_NAMESPACE_START
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
[[nodiscard]]
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result operator"" _toml(const char8_t* str, size_t len) TOML_MAY_THROW;
|
||||
|
||||
#endif // TOML_HAS_CHAR8
|
||||
#endif // TOML_HAS_CHAR8
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
}
|
3191
include/toml++/impl/parser_impl.h
Normal file
3191
include/toml++/impl/parser_impl.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -79,6 +79,7 @@
|
||||
|
||||
#define TOML_DISABLE_SHADOW_WARNINGS \
|
||||
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
|
||||
_Pragma("clang diagnostic ignored \"-Wshadow-field\"") \
|
||||
static_assert(true)
|
||||
|
||||
#define TOML_DISABLE_SPAM_WARNINGS \
|
||||
@ -371,7 +372,11 @@
|
||||
#endif
|
||||
|
||||
#ifndef TOML_UNRELEASED_FEATURES
|
||||
#define TOML_UNRELEASED_FEATURES 0
|
||||
#if TOML_INTELLISENSE
|
||||
#define TOML_UNRELEASED_FEATURES 1
|
||||
#else
|
||||
#define TOML_UNRELEASED_FEATURES 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TOML_LARGE_FILES
|
||||
@ -392,23 +397,17 @@
|
||||
// 256 is crazy high! if you're hitting this limit with real input, TOML is probably the wrong tool for the job...
|
||||
#endif
|
||||
|
||||
#ifndef DOXYGEN
|
||||
#ifdef _WIN32
|
||||
#ifndef TOML_WINDOWS_COMPAT
|
||||
#define TOML_WINDOWS_COMPAT 1
|
||||
#endif
|
||||
#if TOML_WINDOWS_COMPAT && !defined(TOML_INCLUDE_WINDOWS_H)
|
||||
#define TOML_INCLUDE_WINDOWS_H 0
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(_WIN32) || !defined(TOML_WINDOWS_COMPAT)
|
||||
#undef TOML_WINDOWS_COMPAT
|
||||
#define TOML_WINDOWS_COMPAT 0
|
||||
#endif
|
||||
#if !TOML_WINDOWS_COMPAT
|
||||
#undef TOML_INCLUDE_WINDOWS_H
|
||||
#define TOML_INCLUDE_WINDOWS_H 0
|
||||
#endif
|
||||
#ifndef TOML_WINDOWS_COMPAT
|
||||
#define TOML_WINDOWS_COMPAT 1
|
||||
#endif
|
||||
/// \cond
|
||||
#ifndef _WIN32
|
||||
#undef TOML_WINDOWS_COMPAT
|
||||
#define TOML_WINDOWS_COMPAT 0
|
||||
#endif
|
||||
/// \endcond
|
||||
#ifndef TOML_INCLUDE_WINDOWS_H
|
||||
#define TOML_INCLUDE_WINDOWS_H 0
|
||||
#endif
|
||||
|
||||
#ifdef TOML_OPTIONAL_TYPE
|
||||
@ -419,9 +418,7 @@
|
||||
|
||||
#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.
|
||||
#error TOML_CHAR_8_STRINGS was removed in toml++ 2.0.0; all value setters and getters now work with char8_t strings implicitly.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -554,8 +551,6 @@ is no longer necessary.
|
||||
#define TOML_UNREACHABLE TOML_ASSERT(false)
|
||||
#endif
|
||||
|
||||
#define TOML_NO_DEFAULT_CASE default: TOML_UNREACHABLE
|
||||
|
||||
#if defined(__cpp_consteval) && __cpp_consteval >= 201811 && !defined(_MSC_VER)
|
||||
// https://developercommunity.visualstudio.com/t/Erroneous-C7595-error-with-consteval-in/1404234
|
||||
#define TOML_CONSTEVAL consteval
|
||||
@ -569,25 +564,29 @@ is no longer necessary.
|
||||
#define TOML_HAS_ATTR(...) 0
|
||||
#endif
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_INTELLISENSE
|
||||
#if !defined(TOML_LIKELY) && TOML_HAS_ATTR(likely) >= 201803
|
||||
#define TOML_LIKELY(...) (__VA_ARGS__) [[likely]]
|
||||
#endif
|
||||
#if !defined(TOML_UNLIKELY) && TOML_HAS_ATTR(unlikely) >= 201803
|
||||
#define TOML_UNLIKELY(...) (__VA_ARGS__) [[unlikely]]
|
||||
#endif
|
||||
#if TOML_HAS_ATTR(nodiscard) >= 201907
|
||||
#define TOML_NODISCARD_CTOR [[nodiscard]]
|
||||
#endif
|
||||
#if !defined(TOML_LIKELY) && TOML_HAS_ATTR(likely) >= 201803
|
||||
#define TOML_LIKELY(...) (__VA_ARGS__) [[likely]]
|
||||
#endif
|
||||
|
||||
#ifndef TOML_LIKELY
|
||||
#define TOML_LIKELY(...) (__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if !defined(TOML_UNLIKELY) && TOML_HAS_ATTR(unlikely) >= 201803
|
||||
#define TOML_UNLIKELY(...) (__VA_ARGS__) [[unlikely]]
|
||||
#endif
|
||||
#ifndef TOML_UNLIKELY
|
||||
#define TOML_UNLIKELY(...) (__VA_ARGS__)
|
||||
#endif
|
||||
#ifndef TOML_NODISCARD_CTOR
|
||||
|
||||
#if TOML_HAS_ATTR(nodiscard)
|
||||
#define TOML_NODISCARD [[nodiscard]]
|
||||
#else
|
||||
#define TOML_NODISCARD
|
||||
#endif
|
||||
|
||||
#if TOML_HAS_ATTR(nodiscard) >= 201907
|
||||
#define TOML_NODISCARD_CTOR [[nodiscard]]
|
||||
#else
|
||||
#define TOML_NODISCARD_CTOR
|
||||
#endif
|
||||
|
||||
@ -595,10 +594,10 @@ is no longer necessary.
|
||||
#define TOML_TRIVIAL_ABI
|
||||
#endif
|
||||
|
||||
#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__ TOML_NODISCARD friend bool operator == (RHS rhs, LHS lhs) noexcept { return lhs == rhs; } \
|
||||
__VA_ARGS__ TOML_NODISCARD friend bool operator != (LHS lhs, RHS rhs) noexcept { return !(lhs == rhs); } \
|
||||
__VA_ARGS__ TOML_NODISCARD friend bool operator != (RHS rhs, LHS lhs) noexcept { return !(lhs == rhs); } \
|
||||
static_assert(true)
|
||||
|
||||
#ifndef TOML_SIMPLE_STATIC_ASSERT_MESSAGES
|
||||
@ -619,7 +618,7 @@ is no longer necessary.
|
||||
#endif
|
||||
|
||||
#define TOML_MAKE_FLAGS_(name, op) \
|
||||
[[nodiscard]] \
|
||||
TOML_NODISCARD \
|
||||
TOML_ALWAYS_INLINE \
|
||||
TOML_ATTR(const) \
|
||||
constexpr name operator op(name lhs, name rhs) noexcept \
|
||||
@ -637,7 +636,7 @@ is no longer necessary.
|
||||
TOML_MAKE_FLAGS_(name, &); \
|
||||
TOML_MAKE_FLAGS_(name, |); \
|
||||
TOML_MAKE_FLAGS_(name, ^); \
|
||||
[[nodiscard]] \
|
||||
TOML_NODISCARD \
|
||||
TOML_ALWAYS_INLINE \
|
||||
TOML_ATTR(const) \
|
||||
constexpr name operator~(name val) noexcept \
|
||||
@ -645,7 +644,7 @@ is no longer necessary.
|
||||
using under = std::underlying_type_t<name>; \
|
||||
return static_cast<name>(~static_cast<under>(val)); \
|
||||
} \
|
||||
[[nodiscard]] \
|
||||
TOML_NODISCARD \
|
||||
TOML_ALWAYS_INLINE \
|
||||
TOML_ATTR(const) \
|
||||
constexpr bool operator!(name val) noexcept \
|
||||
@ -660,6 +659,27 @@ is no longer necessary.
|
||||
#define TOML_LIFETIME_HOOKS 0
|
||||
#endif
|
||||
|
||||
#if !defined(__POXY__) && !defined(POXY_IMPLEMENTATION_DETAIL)
|
||||
#define POXY_IMPLEMENTATION_DETAIL(...) __VA_ARGS__
|
||||
#endif
|
||||
|
||||
//======================================================================================================================
|
||||
// SFINAE
|
||||
//======================================================================================================================
|
||||
|
||||
/// \cond
|
||||
#if defined(__cpp_concepts) && __cpp_concepts >= 201907
|
||||
#define TOML_REQUIRES(...) requires(__VA_ARGS__)
|
||||
#else
|
||||
#define TOML_REQUIRES(...)
|
||||
#endif
|
||||
#define TOML_ENABLE_IF(...) , typename std::enable_if<(__VA_ARGS__), int>::type = 0
|
||||
#define TOML_CONSTRAINED_TEMPLATE(condition, ...) template <__VA_ARGS__ TOML_ENABLE_IF(condition)> TOML_REQUIRES(condition)
|
||||
/// \endcond
|
||||
#ifndef TOML_CONSTRAINED_TEMPLATE
|
||||
#define TOML_CONSTRAINED_TEMPLATE(condition, ...) template <__VA_ARGS__>
|
||||
#endif
|
||||
|
||||
//#====================================================================================================================
|
||||
//# EXTENDED INT AND FLOAT TYPES
|
||||
//#====================================================================================================================
|
||||
@ -697,7 +717,7 @@ is no longer necessary.
|
||||
//# VERSIONS AND NAMESPACES
|
||||
//#====================================================================================================================
|
||||
|
||||
#include "toml_version.h"
|
||||
#include "version.h"
|
||||
|
||||
#define TOML_LIB_SINGLE_HEADER 0
|
||||
|
||||
@ -778,6 +798,63 @@ TOML_DISABLE_WARNINGS;
|
||||
#endif
|
||||
TOML_ENABLE_WARNINGS;
|
||||
|
||||
//#====================================================================================================================
|
||||
//# STATIC ASSERT MESSAGE FORMATTING
|
||||
//#====================================================================================================================
|
||||
|
||||
/// \cond
|
||||
|
||||
#if TOML_SIMPLE_STATIC_ASSERT_MESSAGES
|
||||
|
||||
#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
|
||||
|
||||
/// \endcond
|
||||
|
||||
//#====================================================================================================================
|
||||
//# DOXYGEN SPAM
|
||||
//#====================================================================================================================
|
@ -4,22 +4,11 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "toml_date_time.h"
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#include <cmath>
|
||||
#if TOML_INT_CHARCONV || TOML_FLOAT_CHARCONV
|
||||
#include <charconv>
|
||||
#endif
|
||||
#if !TOML_INT_CHARCONV || !TOML_FLOAT_CHARCONV
|
||||
#include <sstream>
|
||||
#endif
|
||||
#if !TOML_INT_CHARCONV
|
||||
#include <iomanip>
|
||||
#endif
|
||||
TOML_ENABLE_WARNINGS;
|
||||
#include "date_time.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
TOML_DISABLE_ARITHMETIC_WARNINGS;
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
@ -36,7 +25,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
// - Strings in C++. Honestly.
|
||||
|
||||
template <typename Char1, typename Char2>
|
||||
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);
|
||||
@ -66,7 +55,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
stream.write(reinterpret_cast<const Char*>(str), static_cast<std::streamsize>(len));
|
||||
}
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
#if TOML_HAS_CHAR8
|
||||
|
||||
template <typename Char>
|
||||
inline void print_to_stream(char8_t character, std::basic_ostream<Char>& stream)
|
||||
@ -83,27 +72,35 @@ TOML_IMPL_NAMESPACE_START
|
||||
stream.write(reinterpret_cast<const Char*>(str), static_cast<std::streamsize>(len));
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template <typename T> inline constexpr size_t charconv_buffer_length = 0;
|
||||
template <> inline constexpr size_t charconv_buffer_length<double> = 60;
|
||||
template <> inline constexpr size_t charconv_buffer_length<float> = 40;
|
||||
template <> inline constexpr size_t charconv_buffer_length<uint64_t> = 20; // strlen("18446744073709551615")
|
||||
template <> inline constexpr size_t charconv_buffer_length<int64_t> = 20; // strlen("-9223372036854775808")
|
||||
template <> inline constexpr size_t charconv_buffer_length<int32_t> = 11; // strlen("-2147483648")
|
||||
template <> inline constexpr size_t charconv_buffer_length<int16_t> = 6; // strlen("-32768")
|
||||
template <> inline constexpr size_t charconv_buffer_length<int8_t> = 4; // strlen("-128")
|
||||
template <> inline constexpr size_t charconv_buffer_length<uint32_t> = 10; // strlen("4294967295")
|
||||
template <> inline constexpr size_t charconv_buffer_length<uint16_t> = 5; // strlen("65535")
|
||||
template <> inline constexpr size_t charconv_buffer_length<uint8_t> = 3; // strlen("255")
|
||||
template <typename T>
|
||||
inline constexpr size_t charconv_buffer_length = 0;
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<double> = 60;
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<float> = 40;
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<uint64_t> = 20; // strlen("18446744073709551615")
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<int64_t> = 20; // strlen("-9223372036854775808")
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<int32_t> = 11; // strlen("-2147483648")
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<int16_t> = 6; // strlen("-32768")
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<int8_t> = 4; // strlen("-128")
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<uint32_t> = 10; // strlen("4294967295")
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<uint16_t> = 5; // strlen("65535")
|
||||
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, value_flags format = {})
|
||||
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."
|
||||
);
|
||||
static_assert(sizeof(Char) == 1, "The stream's underlying character type must be 1 byte in size.");
|
||||
|
||||
if (!val)
|
||||
{
|
||||
@ -123,94 +120,86 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
}
|
||||
|
||||
#if TOML_INT_CHARCONV
|
||||
{
|
||||
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>;
|
||||
#if TOML_INT_CHARCONV
|
||||
|
||||
if TOML_UNLIKELY(format == value_flags::format_as_binary)
|
||||
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>;
|
||||
|
||||
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++)
|
||||
{
|
||||
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))
|
||||
{
|
||||
if ((v & mask))
|
||||
{
|
||||
print_to_stream('1', stream);
|
||||
found_one = true;
|
||||
}
|
||||
else if (found_one)
|
||||
print_to_stream('0', stream);
|
||||
mask >>= 1;
|
||||
print_to_stream('1', stream);
|
||||
found_one = true;
|
||||
}
|
||||
}
|
||||
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);
|
||||
else if (found_one)
|
||||
print_to_stream('0', stream);
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
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> \
|
||||
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); \
|
||||
}
|
||||
#define TOML_P2S_OVERLOAD(T) \
|
||||
template <typename Char> \
|
||||
inline void print_to_stream(T val, std::basic_ostream<Char>& stream, value_flags format) \
|
||||
{ \
|
||||
static_assert(sizeof(Char) == 1); \
|
||||
print_integer_to_stream(val, stream, format); \
|
||||
} \
|
||||
static_assert(true)
|
||||
|
||||
TOML_P2S_OVERLOAD(int8_t)
|
||||
TOML_P2S_OVERLOAD(int16_t)
|
||||
TOML_P2S_OVERLOAD(int32_t)
|
||||
TOML_P2S_OVERLOAD(int64_t)
|
||||
TOML_P2S_OVERLOAD(uint8_t)
|
||||
TOML_P2S_OVERLOAD(uint16_t)
|
||||
TOML_P2S_OVERLOAD(uint32_t)
|
||||
TOML_P2S_OVERLOAD(uint64_t)
|
||||
TOML_P2S_OVERLOAD(int8_t);
|
||||
TOML_P2S_OVERLOAD(int16_t);
|
||||
TOML_P2S_OVERLOAD(int32_t);
|
||||
TOML_P2S_OVERLOAD(int64_t);
|
||||
TOML_P2S_OVERLOAD(uint8_t);
|
||||
TOML_P2S_OVERLOAD(uint16_t);
|
||||
TOML_P2S_OVERLOAD(uint32_t);
|
||||
TOML_P2S_OVERLOAD(uint64_t);
|
||||
|
||||
#undef TOML_P2S_OVERLOAD
|
||||
#undef TOML_P2S_OVERLOAD
|
||||
|
||||
template <typename T, typename Char>
|
||||
inline 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."
|
||||
);
|
||||
static_assert(sizeof(Char) == 1, "The stream's underlying character type must be 1 byte in size.");
|
||||
|
||||
switch (impl::fpclassify(val))
|
||||
{
|
||||
case fp_class::neg_inf:
|
||||
print_to_stream("-inf"sv, stream);
|
||||
break;
|
||||
case fp_class::neg_inf: print_to_stream("-inf"sv, stream); break;
|
||||
|
||||
case fp_class::pos_inf:
|
||||
print_to_stream("inf"sv, stream);
|
||||
break;
|
||||
case fp_class::pos_inf: print_to_stream("inf"sv, stream); break;
|
||||
|
||||
case fp_class::nan:
|
||||
print_to_stream("nan"sv, stream);
|
||||
break;
|
||||
case fp_class::nan: print_to_stream("nan"sv, stream); break;
|
||||
|
||||
case fp_class::ok:
|
||||
{
|
||||
@ -222,54 +211,54 @@ TOML_IMPL_NAMESPACE_START
|
||||
return true;
|
||||
};
|
||||
|
||||
#if TOML_FLOAT_CHARCONV
|
||||
{
|
||||
char buf[charconv_buffer_length<T>];
|
||||
const auto res = hexfloat
|
||||
? std::to_chars(buf, buf + sizeof(buf), val, std::chars_format::hex)
|
||||
: std::to_chars(buf, buf + sizeof(buf), val);
|
||||
const auto str = std::string_view{ buf, static_cast<size_t>(res.ptr - buf) };
|
||||
print_to_stream(str, stream);
|
||||
if (!hexfloat && needs_decimal_point(str))
|
||||
print_to_stream(".0"sv, stream);
|
||||
}
|
||||
#else
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
ss.precision(std::numeric_limits<T>::digits10 + 1);
|
||||
if (hexfloat)
|
||||
ss << std::hexfloat;
|
||||
ss << val;
|
||||
const auto str = std::move(ss).str();
|
||||
print_to_stream(str, stream);
|
||||
if (!hexfloat && needs_decimal_point(str))
|
||||
print_to_stream(".0"sv, stream);
|
||||
}
|
||||
#endif
|
||||
#if TOML_FLOAT_CHARCONV
|
||||
|
||||
break;
|
||||
char buf[charconv_buffer_length<T>];
|
||||
const auto res = hexfloat ? std::to_chars(buf, buf + sizeof(buf), val, std::chars_format::hex)
|
||||
: std::to_chars(buf, buf + sizeof(buf), val);
|
||||
const auto str = std::string_view{ buf, static_cast<size_t>(res.ptr - buf) };
|
||||
print_to_stream(str, stream);
|
||||
if (!hexfloat && needs_decimal_point(str))
|
||||
print_to_stream(".0"sv, stream);
|
||||
|
||||
#else
|
||||
|
||||
std::ostringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
ss.precision(std::numeric_limits<T>::digits10 + 1);
|
||||
if (hexfloat)
|
||||
ss << std::hexfloat;
|
||||
ss << val;
|
||||
const auto str = std::move(ss).str();
|
||||
print_to_stream(str, stream);
|
||||
if (!hexfloat && needs_decimal_point(str))
|
||||
print_to_stream(".0"sv, stream);
|
||||
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API void print_floating_point_to_stream(double, std::ostream&, bool);
|
||||
#endif
|
||||
#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> \
|
||||
inline void print_to_stream(Type val, std::basic_ostream<Char>& stream) \
|
||||
{ \
|
||||
static_assert(sizeof(Char) == 1); \
|
||||
print_floating_point_to_stream(val, stream); \
|
||||
}
|
||||
#define TOML_P2S_OVERLOAD(Type) \
|
||||
template <typename Char> \
|
||||
inline void print_to_stream(Type val, std::basic_ostream<Char>& stream) \
|
||||
{ \
|
||||
static_assert(sizeof(Char) == 1); \
|
||||
print_floating_point_to_stream(val, stream); \
|
||||
} \
|
||||
static_assert(true)
|
||||
|
||||
TOML_P2S_OVERLOAD(double)
|
||||
TOML_P2S_OVERLOAD(double);
|
||||
|
||||
#undef TOML_P2S_OVERLOAD
|
||||
#undef TOML_P2S_OVERLOAD
|
||||
|
||||
template <typename Char>
|
||||
inline void print_to_stream(bool val, std::basic_ostream<Char>& stream)
|
||||
@ -279,28 +268,28 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
|
||||
template <typename T, typename Char>
|
||||
inline void print_to_stream(T val, std::basic_ostream<Char>& stream, size_t zero_pad_to_digits)
|
||||
inline void print_to_stream(T val, std::basic_ostream<Char> & stream, size_t zero_pad_to_digits)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1);
|
||||
#if TOML_INT_CHARCONV
|
||||
#if TOML_INT_CHARCONV
|
||||
|
||||
char buf[charconv_buffer_length<T>];
|
||||
const auto res = std::to_chars(buf, buf + sizeof(buf), val);
|
||||
const auto len = static_cast<size_t>(res.ptr - buf);
|
||||
for (size_t i = len; i < zero_pad_to_digits; i++)
|
||||
print_to_stream('0', stream);
|
||||
print_to_stream(buf, static_cast<size_t>(res.ptr - buf), stream);
|
||||
char buf[charconv_buffer_length<T>];
|
||||
const auto res = std::to_chars(buf, buf + sizeof(buf), val);
|
||||
const auto len = static_cast<size_t>(res.ptr - buf);
|
||||
for (size_t i = len; i < zero_pad_to_digits; i++)
|
||||
print_to_stream('0', stream);
|
||||
print_to_stream(buf, static_cast<size_t>(res.ptr - buf), stream);
|
||||
|
||||
#else
|
||||
#else
|
||||
|
||||
std::ostringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
using cast_type = std::conditional_t<std::is_signed_v<T>, int64_t, uint64_t>;
|
||||
ss << std::setfill('0') << std::setw(static_cast<int>(zero_pad_to_digits)) << static_cast<cast_type>(val);
|
||||
const auto str = std::move(ss).str();
|
||||
print_to_stream(str, stream);
|
||||
std::ostringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
using cast_type = std::conditional_t<std::is_signed_v<T>, int64_t, uint64_t>;
|
||||
ss << std::setfill('0') << std::setw(static_cast<int>(zero_pad_to_digits)) << static_cast<cast_type>(val);
|
||||
const auto str = std::move(ss).str();
|
||||
print_to_stream(str, stream);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
@ -326,7 +315,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
if (val.nanosecond && val.nanosecond <= 999999999u)
|
||||
{
|
||||
print_to_stream('.', stream);
|
||||
auto ns = val.nanosecond;
|
||||
auto ns = val.nanosecond;
|
||||
size_t digits = 9_sz;
|
||||
while (ns % 10u == 0u)
|
||||
{
|
||||
@ -338,7 +327,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline void print_to_stream(toml::time_offset val, std::basic_ostream<Char>& stream)
|
||||
inline void print_to_stream(toml::time_offset val, std::basic_ostream<Char> & stream)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1);
|
||||
if (!val.minutes)
|
||||
@ -377,11 +366,8 @@ TOML_IMPL_NAMESPACE_START
|
||||
print_to_stream(*val.offset, stream);
|
||||
}
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_ARITHMETIC_WARNINGS;
|
||||
|
||||
template <typename T, typename Char>
|
||||
void print_to_stream_with_escapes(T && str, std::basic_ostream<Char>& stream)
|
||||
void print_to_stream_with_escapes(T && str, std::basic_ostream<Char> & stream)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1);
|
||||
for (auto c : str)
|
||||
@ -398,8 +384,6 @@ TOML_IMPL_NAMESPACE_START
|
||||
print_to_stream(c, stream);
|
||||
}
|
||||
}
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_ARITHMETIC_WARNINGS
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
@ -409,29 +393,26 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("bar = 42"sv);
|
||||
///
|
||||
///
|
||||
/// std::cout << "The value for 'bar' was found on "sv
|
||||
/// << tbl.get("bar")->source().begin()
|
||||
/// << "\n";
|
||||
///
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
///
|
||||
/// \out
|
||||
/// The value for 'bar' was found on line 1, column 7
|
||||
/// \eout
|
||||
///
|
||||
///
|
||||
/// \tparam Char The output stream's underlying character type. Must be 1 byte in size.
|
||||
/// \param lhs The stream.
|
||||
/// \param rhs The source_position.
|
||||
///
|
||||
/// \returns The input stream.
|
||||
template <typename Char>
|
||||
inline 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,
|
||||
"The stream's underlying character type must be 1 byte in size."
|
||||
);
|
||||
static_assert(sizeof(Char) == 1, "The stream's underlying character type must be 1 byte in size.");
|
||||
impl::print_to_stream("line "sv, lhs);
|
||||
impl::print_to_stream(rhs.line, lhs);
|
||||
impl::print_to_stream(", column "sv, lhs);
|
||||
@ -443,29 +424,26 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("bar = 42", "config.toml");
|
||||
///
|
||||
///
|
||||
/// std::cout << "The value for 'bar' was found on "sv
|
||||
/// << tbl.get("bar")->source()
|
||||
/// << "\n";
|
||||
///
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
///
|
||||
/// \out
|
||||
/// The value for 'bar' was found on line 1, column 7 of 'config.toml'
|
||||
/// \eout
|
||||
///
|
||||
///
|
||||
/// \tparam Char The output stream's underlying character type. Must be 1 byte in size.
|
||||
/// \param lhs The stream.
|
||||
/// \param rhs The source_position.
|
||||
///
|
||||
/// \returns The input stream.
|
||||
template <typename Char>
|
||||
inline 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,
|
||||
"The stream's underlying character type must be 1 byte in size."
|
||||
);
|
||||
static_assert(sizeof(Char) == 1, "The stream's underlying character type must be 1 byte in size.");
|
||||
lhs << rhs.begin;
|
||||
if (rhs.path)
|
||||
{
|
||||
@ -476,11 +454,13 @@ TOML_NAMESPACE_START
|
||||
return lhs;
|
||||
}
|
||||
|
||||
#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
|
||||
#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
|
||||
TOML_POP_WARNINGS;
|
1333
include/toml++/impl/table.h
Normal file
1333
include/toml++/impl/table.h
Normal file
File diff suppressed because it is too large
Load Diff
210
include/toml++/impl/table_impl.h
Normal file
210
include/toml++/impl/table_impl.h
Normal file
@ -0,0 +1,210 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "table.h"
|
||||
#include "node_view.h"
|
||||
|
||||
/// \cond
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table() noexcept
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_TABLE_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(const table& other) noexcept //
|
||||
: node(other),
|
||||
inline_{ other.inline_ }
|
||||
{
|
||||
for (auto&& [k, v] : other)
|
||||
map.emplace_hint(map.end(), k, impl::make_node(v));
|
||||
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_TABLE_CREATED;
|
||||
#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
|
||||
TOML_TABLE_CREATED;
|
||||
#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(impl::table_init_pair * pairs, size_t count) noexcept
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
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
|
||||
bool table::is_homogeneous(node_type ntype) const noexcept
|
||||
{
|
||||
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[](std::string_view key) const noexcept
|
||||
{
|
||||
return node_view<const node>{ this->get(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) };
|
||||
}
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool operator==(const table& lhs, const table& rhs) noexcept
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.map.size() != rhs.map.size())
|
||||
return false;
|
||||
|
||||
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;
|
||||
|
||||
const auto lhs_type = l->second->type();
|
||||
const node& rhs_ = *r->second;
|
||||
const auto rhs_type = rhs_.type();
|
||||
if (lhs_type != rhs_type)
|
||||
return false;
|
||||
|
||||
const bool equal = l->second->visit(
|
||||
[&](const auto& lhs_) noexcept
|
||||
{ return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_); });
|
||||
if (!equal)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool operator!=(const table& lhs, const table& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
/// \endcond
|
@ -5,7 +5,7 @@
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "toml_preprocessor.h"
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
@ -19,11 +19,11 @@ TOML_DISABLE_WARNINGS;
|
||||
#include <istream>
|
||||
TOML_ENABLE_WARNINGS;
|
||||
|
||||
#include "toml_node_view.h"
|
||||
#include "toml_default_formatter.h"
|
||||
#include "toml_json_formatter.h"
|
||||
#include "node_view.h"
|
||||
#include "default_formatter.h"
|
||||
#include "json_formatter.h"
|
||||
#if TOML_PARSER
|
||||
#include "toml_parser.h"
|
||||
#include "parser.h"
|
||||
#endif
|
||||
|
||||
// internal implementation namespace
|
||||
@ -58,34 +58,35 @@ TOML_NAMESPACE_START
|
||||
template class json_formatter<char>;
|
||||
|
||||
// various ostream operators
|
||||
template std::ostream& operator << (std::ostream&, const source_position&);
|
||||
template std::ostream& operator << (std::ostream&, const source_region&);
|
||||
template std::ostream& operator << (std::ostream&, const date&);
|
||||
template std::ostream& operator << (std::ostream&, const time&);
|
||||
template std::ostream& operator << (std::ostream&, const time_offset&);
|
||||
template std::ostream& operator << (std::ostream&, const date_time&);
|
||||
template std::ostream& operator << (std::ostream&, const value<std::string>&);
|
||||
template std::ostream& operator << (std::ostream&, const value<int64_t>&);
|
||||
template std::ostream& operator << (std::ostream&, const value<double>&);
|
||||
template std::ostream& operator << (std::ostream&, const value<bool>&);
|
||||
template std::ostream& operator << (std::ostream&, const value<toml::date>&);
|
||||
template std::ostream& operator << (std::ostream&, const value<toml::time>&);
|
||||
template std::ostream& operator << (std::ostream&, const value<toml::date_time>&);
|
||||
template std::ostream& operator << (std::ostream&, default_formatter<char>&);
|
||||
template std::ostream& operator << (std::ostream&, default_formatter<char>&&);
|
||||
template std::ostream& operator << (std::ostream&, json_formatter<char>&);
|
||||
template std::ostream& operator << (std::ostream&, json_formatter<char>&&);
|
||||
template std::ostream& operator << (std::ostream&, const table&);
|
||||
template std::ostream& operator << (std::ostream&, const array&);
|
||||
template std::ostream& operator << (std::ostream&, const node_view<node>&);
|
||||
template std::ostream& operator << (std::ostream&, const node_view<const node>&);
|
||||
template std::ostream& operator << (std::ostream&, node_type);
|
||||
template std::ostream& operator<<(std::ostream&, const source_position&);
|
||||
template std::ostream& operator<<(std::ostream&, const source_region&);
|
||||
template std::ostream& operator<<(std::ostream&, const date&);
|
||||
template std::ostream& operator<<(std::ostream&, const time&);
|
||||
template std::ostream& operator<<(std::ostream&, const time_offset&);
|
||||
template std::ostream& operator<<(std::ostream&, const date_time&);
|
||||
template std::ostream& operator<<(std::ostream&, const value<std::string>&);
|
||||
template std::ostream& operator<<(std::ostream&, const value<int64_t>&);
|
||||
template std::ostream& operator<<(std::ostream&, const value<double>&);
|
||||
template std::ostream& operator<<(std::ostream&, const value<bool>&);
|
||||
template std::ostream& operator<<(std::ostream&, const value<toml::date>&);
|
||||
template std::ostream& operator<<(std::ostream&, const value<toml::time>&);
|
||||
template std::ostream& operator<<(std::ostream&, const value<toml::date_time>&);
|
||||
template std::ostream& operator<<(std::ostream&, default_formatter<char>&);
|
||||
template std::ostream& operator<<(std::ostream&, default_formatter<char>&&);
|
||||
template std::ostream& operator<<(std::ostream&, json_formatter<char>&);
|
||||
template std::ostream& operator<<(std::ostream&, json_formatter<char>&&);
|
||||
template std::ostream& operator<<(std::ostream&, const table&);
|
||||
template std::ostream& operator<<(std::ostream&, const array&);
|
||||
template std::ostream& operator<<(std::ostream&, const node_view<node>&);
|
||||
template std::ostream& operator<<(std::ostream&, const node_view<const node>&);
|
||||
template std::ostream& operator<<(std::ostream&, node_type);
|
||||
|
||||
// node::value, node_view:::value etc
|
||||
#define TOML_INSTANTIATE(name, T) \
|
||||
template optional<T> node::name<T>() const noexcept; \
|
||||
template optional<T> node_view<node>::name<T>() const noexcept; \
|
||||
template optional<T> node_view<const node>::name<T>() const noexcept
|
||||
#define TOML_INSTANTIATE(name, T) \
|
||||
template optional<T> node::name<T>() const noexcept; \
|
||||
template optional<T> node_view<node>::name<T>() const noexcept; \
|
||||
template 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*);
|
||||
@ -114,34 +115,34 @@ TOML_NAMESPACE_START
|
||||
TOML_INSTANTIATE(value, time);
|
||||
TOML_INSTANTIATE(value, date_time);
|
||||
TOML_INSTANTIATE(value, bool);
|
||||
#if TOML_HAS_CHAR8
|
||||
#if TOML_HAS_CHAR8
|
||||
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
|
||||
#endif
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
TOML_INSTANTIATE(value_exact, std::wstring);
|
||||
TOML_INSTANTIATE(value, std::wstring);
|
||||
#endif
|
||||
#undef TOML_INSTANTIATE
|
||||
#endif
|
||||
#undef TOML_INSTANTIATE
|
||||
|
||||
// parser instantiations
|
||||
#if TOML_PARSER
|
||||
// parser instantiations
|
||||
#if TOML_PARSER
|
||||
|
||||
// parse error ostream
|
||||
template std::ostream& operator << (std::ostream&, const parse_error&);
|
||||
// parse error ostream
|
||||
template std::ostream& operator<<(std::ostream&, const parse_error&);
|
||||
|
||||
// parse() and parse_file()
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex);
|
||||
// parse() and parse_file()
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex);
|
||||
|
||||
template parse_result parse(std::istream&, std::string_view) TOML_MAY_THROW;
|
||||
template parse_result parse(std::istream&, std::string&&) TOML_MAY_THROW;
|
||||
template parse_result parse(std::istream&, std::string_view) TOML_MAY_THROW;
|
||||
template parse_result parse(std::istream&, std::string &&) TOML_MAY_THROW;
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
|
||||
#endif // TOML_PARSER
|
||||
#endif // TOML_PARSER
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
957
include/toml++/impl/utf8.h
Normal file
957
include/toml++/impl/utf8.h
Normal file
@ -0,0 +1,957 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "preprocessor.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
|
||||
/// \cond
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_ascii_whitespace(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint == U'\t' || codepoint == U' ';
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
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")
|
||||
|
||||
return codepoint == U'\u00A0' // no-break space
|
||||
|| codepoint == U'\u1680' // ogham space mark
|
||||
|| (codepoint >= U'\u2000' && codepoint <= U'\u200A') // em quad -> hair space
|
||||
|| codepoint == U'\u202F' // narrow no-break space
|
||||
|| codepoint == U'\u205F' // medium mathematical space
|
||||
|| codepoint == U'\u3000' // ideographic space
|
||||
;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_whitespace(char32_t codepoint) noexcept
|
||||
{
|
||||
return is_ascii_whitespace(codepoint) || is_non_ascii_whitespace(codepoint);
|
||||
}
|
||||
|
||||
template <bool IncludeCarriageReturn = true>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_ascii_line_break(char32_t codepoint) noexcept
|
||||
{
|
||||
constexpr auto low_range_end = IncludeCarriageReturn ? U'\r' : U'\f';
|
||||
return (codepoint >= U'\n' && codepoint <= low_range_end);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
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")
|
||||
|
||||
return codepoint == U'\u0085' // next line
|
||||
|| codepoint == U'\u2028' // line separator
|
||||
|| codepoint == U'\u2029' // paragraph separator
|
||||
;
|
||||
}
|
||||
|
||||
template <bool IncludeCarriageReturn = true>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_line_break(char32_t codepoint) noexcept
|
||||
{
|
||||
return is_ascii_line_break<IncludeCarriageReturn>(codepoint) || is_non_ascii_line_break(codepoint);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_string_delimiter(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint == U'"' || codepoint == U'\'';
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_ascii_letter(char32_t codepoint) noexcept
|
||||
{
|
||||
return (codepoint >= U'a' && codepoint <= U'z') || (codepoint >= U'A' && codepoint <= U'Z');
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_binary_digit(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint == U'0' || codepoint == U'1';
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_octal_digit(char32_t codepoint) noexcept
|
||||
{
|
||||
return (codepoint >= U'0' && codepoint <= U'7');
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_decimal_digit(char32_t codepoint) noexcept
|
||||
{
|
||||
return (codepoint >= U'0' && codepoint <= U'9');
|
||||
}
|
||||
|
||||
TOML_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>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr uint_least32_t hex_to_dec(const T codepoint) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<remove_cvref_t<T>, uint_least32_t>)
|
||||
return codepoint >= 0x41u // >= 'A'
|
||||
? 10u + (codepoint | 0x20u) - 0x61u // - 'a'
|
||||
: codepoint - 0x30u // - '0'
|
||||
;
|
||||
else
|
||||
return hex_to_dec(static_cast<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
|
||||
TOML_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) & 0x8A7FFC004001DFA0ull)
|
||||
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, 0xFFC0001FBFFFFFC1u,
|
||||
0x00000000FFFFFFFFu, 0xFFFFFFFFFC000000u, 0x00FFC0400008FFFFu, 0x7FFFFE67F87FFF80u,
|
||||
0x00EC00100008F17Fu, 0x7FFFFE61F80400C0u, 0x001780000000DB7Fu, 0x7FFFFEEFF8000700u,
|
||||
0x00C000400008FB7Fu, 0x7FFFFE67F8008000u, 0x00EC00000008FB7Fu, 0xC6358F71FA000080u,
|
||||
0x000000400000FFF1u, 0x7FFFFF77F8000000u, 0x00C9C0000008FFFFu, 0x7FFFFF77F8400000u,
|
||||
0x00D800000008FBFFu, 0x0000000000000180u,
|
||||
};
|
||||
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0xAAull) / 0x40ull]
|
||||
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0xAAull) % 0x40ull));
|
||||
// 1957 code units from 126 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,
|
||||
0xF0003FFFF8003FFFu, 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));
|
||||
// 2241 code units from 82 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, 0x1FE0000FFFFFFFFFu,
|
||||
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));
|
||||
// 1185 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[] = {
|
||||
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 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));
|
||||
// 773 code units from 28 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 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, 0xFE000001F583FFFFu, 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));
|
||||
// 2567 code units from 54 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, 0xF7FF000FFFFFFFFFu, 0x1BFBFFFBFFB7F7FFu, 0x0000000000000000u,
|
||||
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
|
||||
0x007FFFFFFFFFFFFFu, 0x000000FF003FFFFFu, 0x07FDFFFFFFFFFFBFu, 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));
|
||||
// 1747 code units from 59 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, 0x0000003FFFF00000u, 0x000001FFFFF00000u, 0xFFFFFF8007FFFFF0u,
|
||||
0x000000000FFFFFFFu, 0xFFFFFF8002600000u, 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,
|
||||
0x000007F000000000u, 0x0000000000000000u, 0x0000000000000000u, 0xFFFFFFF000000000u,
|
||||
0x000000000000FFFFu, 0x0000000000000000u, 0xFFFFFFFFFFFFFFF0u, 0xF6FF27F80000000Fu,
|
||||
0x00000028000FFFFFu, 0x0000000000000000u, 0x001FFFFFFFFFCFF0u, 0xFFFF8010000000A0u,
|
||||
0x00100000407FFFFFu, 0x00003FFFFFFFFFFFu, 0xFFFFFFFFFFF00002u, 0x000000001FFFFFFFu,
|
||||
};
|
||||
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x10F1Cull) / 0x40ull]
|
||||
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0x10F1Cull) % 0x40ull));
|
||||
// 1174 code units from 71 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'\U00012F90' <= c && c <= U'\U00012FF0') || 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, 0xFFFF00007FFFFFFFu, 0x7FFFFFFFFFFFFFFFu, 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));
|
||||
// 1329 code units from 15 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'\U0001AFF0' > c || c > U'\U0001B2FB')
|
||||
return false;
|
||||
|
||||
constexpr uint_least64_t bitmask_table_1[] = {
|
||||
0xFFFFFFFFFFFF6FEFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
|
||||
0x0007FFFFFFFFFFFFu, 0x00F0000700000000u, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
|
||||
0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu,
|
||||
0x0000000000000FFFu,
|
||||
};
|
||||
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x1AFF0ull) / 0x40ull]
|
||||
& (0x1ull << ((static_cast<uint_least64_t>(c) - 0x1AFF0ull) % 0x40ull));
|
||||
// 707 code units from 7 ranges (spanning a search area of 780)
|
||||
}
|
||||
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'\U0001DF1E')
|
||||
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,
|
||||
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,
|
||||
0x000000007FFFFFFFu,
|
||||
};
|
||||
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x1D400ull) / 0x40ull]
|
||||
& (0x1ull << (static_cast<uint_least64_t>(c) % 0x40ull));
|
||||
// 967 code units from 31 ranges (spanning a search area of 2847)
|
||||
}
|
||||
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, 0x00003FFFFFFF0000u, 0x00000FFFFFFFFFFFu,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x7FFF6F7F00000000u,
|
||||
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));
|
||||
// 421 code units from 12 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;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
// 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'\U0002A6DF' || U'\U0002A700' <= c;
|
||||
case 0x38: return c <= U'\U0002B738' || (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;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
// 131704 code units from 646 ranges (spanning a search area of 201377)
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
//# Returns true if a codepoint belongs to any of these categories:
|
||||
//# Nd, Nl
|
||||
TOML_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'\U00016AC0' <= c && c <= U'\U00016AC9')
|
||||
|| (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;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
// 886 code units from 73 ranges (spanning a search area of 128410)
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
//# Returns true if a codepoint belongs to any of these categories:
|
||||
//# Mn, Mc
|
||||
TOML_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, 0x00000000FF000000u, 0xFFFFFFFBFFFFFC00u,
|
||||
0xDC0000000000000Fu, 0x0000000C00FEFFFFu, 0xD00000000000000Eu, 0x4000000C0080399Fu,
|
||||
0xD00000000000000Eu, 0x0023000000023987u, 0xD00000000000000Eu, 0xFC00000C00003BBFu,
|
||||
0xD00000000000000Eu, 0x0000000C00E0399Fu, 0xC000000000000004u, 0x0000000000803DC7u,
|
||||
0xD00000000000001Fu, 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,
|
||||
0x001C0000003C0000u, 0x000C0000000C0000u, 0xFFF0000000000000u, 0x00000000200FFFFFu,
|
||||
0x000000000000B800u, 0x0000000000000000u, 0x0000020000000060u, 0x0000000000000000u,
|
||||
0x0FFF0FFF00000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x000000000F800000u, 0x9FFFFFFF7FE00000u, 0xBFFF000000000000u, 0x0000000000007FFFu,
|
||||
0xFFF000000000001Fu, 0x000FF8000000001Fu, 0x00003FFE00000007u, 0x000FFFC000000000u,
|
||||
0x00FFFFF000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x039021FFFFF70000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0xFFFFFFFFFFFFFFFFu,
|
||||
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));
|
||||
// 1141 code units from 158 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, 0x000000F000000000u, 0x0000000000000000u, 0x0000001C00000000u,
|
||||
0x000001FFFC000000u, 0x0000001E00640000u, 0x000000101FFC0000u, 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));
|
||||
// 410 code units from 67 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'\U0001CF00' > c || c > U'\U0001E94A')
|
||||
return false;
|
||||
|
||||
constexpr uint_least64_t bitmask_table_1[] = {
|
||||
0xFFFF3FFFFFFFFFFFu, 0x000000000000007Fu, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0xF807E3E000000000u, 0x00003C0000000FE7u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x000000000000001Cu, 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,
|
||||
0xF87FFFFFFFFFFFFFu, 0x00201FFFFFFFFFFFu, 0x0000FFFEF8000010u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x000007DBF9FFFF7Fu, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x007F000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000400000000000u, 0x0000F00000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u,
|
||||
0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x00000000007F0000u,
|
||||
0x0000000000000000u, 0x00000000000007F0u,
|
||||
};
|
||||
return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0x1CF00ull) / 0x40ull]
|
||||
& (0x1ull << (static_cast<uint_least64_t>(c) % 0x40ull));
|
||||
// 293 code units from 24 ranges (spanning a search area of 6731)
|
||||
}
|
||||
case 0x3F: return U'\U000E0100' <= c;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
// 2395 code units from 302 ranges (spanning a search area of 917232)
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
#endif // TOML_LANG_UNRELEASED
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_bare_key_character(char32_t codepoint) noexcept
|
||||
{
|
||||
return is_ascii_letter(codepoint) || is_decimal_digit(codepoint) || codepoint == U'-' || codepoint == U'_'
|
||||
#if TOML_LANG_UNRELEASED // toml/issues/644 ('+' in bare keys) & toml/issues/687 (unicode bare keys)
|
||||
|| codepoint == U'+' || is_non_ascii_letter(codepoint) || is_non_ascii_number(codepoint)
|
||||
|| is_combining_mark(codepoint)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_value_terminator(char32_t codepoint) noexcept
|
||||
{
|
||||
return is_ascii_line_break(codepoint) || is_ascii_whitespace(codepoint) || codepoint == U']'
|
||||
|| codepoint == U'}' || codepoint == U',' || codepoint == U'#' || is_non_ascii_line_break(codepoint)
|
||||
|| is_non_ascii_whitespace(codepoint);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_control_character(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint <= U'\u001F' || codepoint == U'\u007F';
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_nontab_control_character(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint <= U'\u0008' || (codepoint >= U'\u000A' && codepoint <= U'\u001F') || codepoint == U'\u007F';
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_unicode_surrogate(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint >= 0xD800u && codepoint <= 0xDFFF;
|
||||
}
|
||||
|
||||
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{};
|
||||
|
||||
static constexpr uint8_t state_table[]{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 11, 6, 6,
|
||||
6, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
|
||||
0, 12, 24, 36, 60, 96, 84, 12, 12, 12, 48, 72, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 12,
|
||||
12, 12, 12, 12, 0, 12, 0, 12, 12, 12, 24, 12, 12, 12, 12, 12, 24, 12, 24, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
12, 24, 12, 12, 12, 12, 12, 24, 12, 12, 12, 12, 12, 12, 12, 24, 12, 12, 12, 12, 12, 12, 12, 12, 12, 36, 12,
|
||||
36, 12, 12, 12, 36, 12, 12, 12, 12, 12, 36, 12, 36, 12, 12, 12, 36, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12
|
||||
};
|
||||
|
||||
TOML_NODISCARD
|
||||
constexpr bool error() const noexcept
|
||||
{
|
||||
return state == uint_least32_t{ 12u };
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
constexpr bool has_code_point() const noexcept
|
||||
{
|
||||
return state == uint_least32_t{};
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
constexpr bool needs_more_input() const noexcept
|
||||
{
|
||||
return state > uint_least32_t{} && state != uint_least32_t{ 12u };
|
||||
}
|
||||
|
||||
constexpr void operator()(uint8_t byte) noexcept
|
||||
{
|
||||
TOML_ASSERT(!error());
|
||||
|
||||
const auto type = state_table[byte];
|
||||
|
||||
codepoint = static_cast<char32_t>(has_code_point() ? (uint_least32_t{ 255u } >> type) & byte
|
||||
: (byte & uint_least32_t{ 63u })
|
||||
| (static_cast<uint_least32_t>(codepoint) << 6));
|
||||
|
||||
state = state_table[state + uint_least32_t{ 256u } + type];
|
||||
}
|
||||
};
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
/// \endcond
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_SWITCH_WARNINGS
|
399
include/toml++/impl/utf8_streams.h
Normal file
399
include/toml++/impl/utf8_streams.h
Normal file
@ -0,0 +1,399 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_PARSER
|
||||
#error This header cannot not be included when TOML_PARSER is disabled.
|
||||
#endif
|
||||
//# }}
|
||||
#include "utf8.h"
|
||||
#include "parse_error.h"
|
||||
|
||||
/// \cond
|
||||
|
||||
#if TOML_EXCEPTIONS
|
||||
#define TOML_ERROR_CHECK (void)0
|
||||
#define TOML_ERROR throw parse_error
|
||||
#else
|
||||
#define TOML_ERROR_CHECK \
|
||||
if (err) \
|
||||
return nullptr
|
||||
#define TOML_ERROR err.emplace
|
||||
#endif
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
template <typename T>
|
||||
class utf8_byte_stream;
|
||||
|
||||
inline constexpr auto utf8_byte_order_mark = "\xEF\xBB\xBF"sv;
|
||||
|
||||
template <typename Char>
|
||||
class TOML_API utf8_byte_stream<std::basic_string_view<Char>> final
|
||||
{
|
||||
static_assert(sizeof(Char) == 1_sz);
|
||||
|
||||
private:
|
||||
std::basic_string_view<Char> source;
|
||||
size_t position = {};
|
||||
|
||||
public:
|
||||
explicit constexpr utf8_byte_stream(std::basic_string_view<Char> sv) noexcept : source{ sv }
|
||||
{
|
||||
// trim trailing nulls
|
||||
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'
|
||||
{
|
||||
actual_len = i + 1_sz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (initial_len != actual_len)
|
||||
source = source.substr(0_sz, actual_len);
|
||||
|
||||
// skip bom
|
||||
if (actual_len >= 3_sz && memcmp(utf8_byte_order_mark.data(), source.data(), 3_sz) == 0)
|
||||
position += 3_sz;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
constexpr bool eof() const noexcept
|
||||
{
|
||||
return position >= source.length();
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
constexpr bool peek_eof() const noexcept
|
||||
{
|
||||
return eof();
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
constexpr bool error() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
constexpr unsigned int operator()() noexcept
|
||||
{
|
||||
if (position >= source.length())
|
||||
return 0xFFFFFFFFu;
|
||||
return static_cast<unsigned int>(static_cast<uint8_t>(source[position++]));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
class TOML_API utf8_byte_stream<std::basic_istream<Char>> final
|
||||
{
|
||||
static_assert(sizeof(Char) == 1_sz);
|
||||
|
||||
private:
|
||||
std::basic_istream<Char>* source;
|
||||
|
||||
public:
|
||||
explicit utf8_byte_stream(std::basic_istream<Char>& stream) : source{ &stream }
|
||||
{
|
||||
if (!source->good()) // eof, fail, bad
|
||||
return;
|
||||
|
||||
const auto initial_pos = source->tellg();
|
||||
Char bom[3];
|
||||
source->read(bom, 3);
|
||||
if (source->bad() || (source->gcount() == 3 && memcmp(utf8_byte_order_mark.data(), bom, 3_sz) == 0))
|
||||
return;
|
||||
|
||||
source->clear();
|
||||
source->seekg(initial_pos, std::basic_istream<Char>::beg);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
bool eof() const noexcept
|
||||
{
|
||||
return source->eof();
|
||||
}
|
||||
|
||||
TOML_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();
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
bool error() const noexcept
|
||||
{
|
||||
return !(*source);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
unsigned int operator()()
|
||||
{
|
||||
auto val = source->get();
|
||||
if (val == std::basic_istream<Char>::traits_type::eof())
|
||||
return 0xFFFFFFFFu;
|
||||
return static_cast<unsigned int>(val);
|
||||
}
|
||||
};
|
||||
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_LARGE_FILES, lf, sf);
|
||||
|
||||
struct utf8_codepoint final
|
||||
{
|
||||
char32_t value;
|
||||
char bytes[4];
|
||||
source_position position;
|
||||
|
||||
TOML_NODISCARD
|
||||
std::string_view as_view() const noexcept
|
||||
{
|
||||
return bytes[3] ? std::string_view{ bytes, 4_sz } : std::string_view{ bytes };
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
constexpr operator char32_t&() noexcept
|
||||
{
|
||||
return value;
|
||||
}
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
constexpr operator const char32_t&() const noexcept
|
||||
{
|
||||
return value;
|
||||
}
|
||||
TOML_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);
|
||||
|
||||
struct TOML_ABSTRACT_BASE utf8_reader_interface
|
||||
{
|
||||
TOML_NODISCARD
|
||||
virtual const source_path_ptr& source_path() const noexcept = 0;
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const utf8_codepoint* read_next() = 0;
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual bool peek_eof() const = 0;
|
||||
|
||||
#if !TOML_EXCEPTIONS
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual optional<parse_error>&& error() noexcept = 0;
|
||||
|
||||
#endif
|
||||
|
||||
virtual ~utf8_reader_interface() noexcept = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TOML_EMPTY_BASES TOML_API utf8_reader final : public utf8_reader_interface
|
||||
{
|
||||
private:
|
||||
utf8_byte_stream<T> stream;
|
||||
utf8_decoder decoder;
|
||||
utf8_codepoint codepoints[2];
|
||||
size_t cp_idx = 1;
|
||||
uint8_t current_byte_count{};
|
||||
source_path_ptr source_path_;
|
||||
#if !TOML_EXCEPTIONS
|
||||
optional<parse_error> err;
|
||||
#endif
|
||||
|
||||
public:
|
||||
template <typename U, typename String = std::string_view>
|
||||
explicit utf8_reader(U&& source, String&& source_path = {}) noexcept(
|
||||
std::is_nothrow_constructible_v<utf8_byte_stream<T>, U&&>)
|
||||
: stream{ static_cast<U&&>(source) }
|
||||
{
|
||||
std::memset(codepoints, 0, sizeof(codepoints));
|
||||
codepoints[0].position = { 1, 1 };
|
||||
codepoints[1].position = { 1, 1 };
|
||||
|
||||
if (!source_path.empty())
|
||||
source_path_ = std::make_shared<const std::string>(static_cast<String&&>(source_path));
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
const source_path_ptr& source_path() const noexcept override
|
||||
{
|
||||
return source_path_;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
const utf8_codepoint* read_next() override
|
||||
{
|
||||
TOML_ERROR_CHECK;
|
||||
|
||||
auto& prev = codepoints[(cp_idx - 1_sz) % 2_sz];
|
||||
|
||||
if (stream.eof())
|
||||
return nullptr;
|
||||
else if (stream.error())
|
||||
TOML_ERROR("An error occurred while reading from the underlying stream", prev.position, source_path_);
|
||||
else if (decoder.error())
|
||||
TOML_ERROR("Encountered invalid utf-8 sequence", prev.position, source_path_);
|
||||
|
||||
TOML_ERROR_CHECK;
|
||||
|
||||
while (true)
|
||||
{
|
||||
uint8_t next_byte;
|
||||
{
|
||||
unsigned int next_byte_raw{ 0xFFFFFFFFu };
|
||||
if constexpr (noexcept(stream()) || !TOML_EXCEPTIONS)
|
||||
{
|
||||
next_byte_raw = stream();
|
||||
}
|
||||
#if TOML_EXCEPTIONS
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
next_byte_raw = stream();
|
||||
}
|
||||
catch (const std::exception& exc)
|
||||
{
|
||||
throw parse_error{ exc.what(), prev.position, source_path_ };
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
throw parse_error{ "An unspecified error occurred", prev.position, source_path_ };
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (next_byte_raw >= 256u)
|
||||
{
|
||||
if (stream.eof())
|
||||
{
|
||||
if (decoder.needs_more_input())
|
||||
TOML_ERROR("Encountered EOF during incomplete utf-8 code point sequence",
|
||||
prev.position,
|
||||
source_path_);
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
TOML_ERROR("An error occurred while reading from the underlying stream",
|
||||
prev.position,
|
||||
source_path_);
|
||||
}
|
||||
|
||||
TOML_ERROR_CHECK;
|
||||
next_byte = static_cast<uint8_t>(next_byte_raw);
|
||||
}
|
||||
|
||||
decoder(next_byte);
|
||||
if (decoder.error())
|
||||
TOML_ERROR("Encountered invalid utf-8 sequence", prev.position, source_path_);
|
||||
|
||||
TOML_ERROR_CHECK;
|
||||
|
||||
auto& current = codepoints[cp_idx % 2_sz];
|
||||
current.bytes[current_byte_count++] = static_cast<char>(next_byte);
|
||||
if (decoder.has_code_point())
|
||||
{
|
||||
// store codepoint
|
||||
current.value = decoder.codepoint;
|
||||
|
||||
// reset prev (will be the next 'current')
|
||||
std::memset(prev.bytes, 0, sizeof(prev.bytes));
|
||||
current_byte_count = {};
|
||||
if (is_line_break<false>(current.value))
|
||||
prev.position = { static_cast<source_index>(current.position.line + 1), 1 };
|
||||
else
|
||||
prev.position = { current.position.line,
|
||||
static_cast<source_index>(current.position.column + 1) };
|
||||
cp_idx++;
|
||||
return ¤t;
|
||||
}
|
||||
}
|
||||
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool peek_eof() const override
|
||||
{
|
||||
return stream.peek_eof();
|
||||
}
|
||||
|
||||
#if !TOML_EXCEPTIONS
|
||||
|
||||
TOML_NODISCARD
|
||||
optional<parse_error>&& error() noexcept override
|
||||
{
|
||||
return std::move(err);
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
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_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>>;
|
||||
|
||||
class TOML_EMPTY_BASES TOML_API utf8_buffered_reader final : public utf8_reader_interface
|
||||
{
|
||||
public:
|
||||
static constexpr size_t max_history_length = 72;
|
||||
|
||||
private:
|
||||
static constexpr size_t history_buffer_size = max_history_length - 1; //'head' is stored in the reader
|
||||
utf8_reader_interface& reader;
|
||||
struct
|
||||
{
|
||||
utf8_codepoint buffer[history_buffer_size];
|
||||
size_t count, first;
|
||||
} history = {};
|
||||
const utf8_codepoint* head = {};
|
||||
size_t negative_offset = {};
|
||||
|
||||
public:
|
||||
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
|
||||
optional<parse_error>&& error() noexcept override;
|
||||
#endif
|
||||
};
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
#undef TOML_ERROR_CHECK
|
||||
#undef TOML_ERROR
|
||||
|
||||
/// \endcond
|
@ -5,7 +5,7 @@
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "toml_preprocessor.h"
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
@ -14,11 +14,17 @@
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "toml_utf8_streams.h"
|
||||
#include "utf8_streams.h"
|
||||
|
||||
/// \cond
|
||||
|
||||
#if !TOML_EXCEPTIONS
|
||||
#undef TOML_ERROR_CHECK
|
||||
#define TOML_ERROR_CHECK if (reader.error()) return nullptr
|
||||
#define TOML_ERROR_CHECK \
|
||||
if (reader.error()) \
|
||||
return nullptr
|
||||
#else
|
||||
#define TOML_ERROR_CHECK (void)0
|
||||
#endif
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
@ -26,8 +32,7 @@ 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_ }
|
||||
utf8_buffered_reader::utf8_buffered_reader(utf8_reader_interface & reader_) noexcept : reader{ reader_ }
|
||||
{}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
@ -84,8 +89,8 @@ TOML_IMPL_NAMESPACE_START
|
||||
negative_offset += count;
|
||||
|
||||
return negative_offset
|
||||
? history.buffer + ((history.first + history.count - negative_offset) % history_buffer_size)
|
||||
: head;
|
||||
? history.buffer + ((history.first + history.count - negative_offset) % history_buffer_size)
|
||||
: head;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
@ -94,17 +99,18 @@ TOML_IMPL_NAMESPACE_START
|
||||
return reader.peek_eof();
|
||||
}
|
||||
|
||||
#if !TOML_EXCEPTIONS
|
||||
#if !TOML_EXCEPTIONS
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
optional<parse_error>&& utf8_buffered_reader::error() noexcept
|
||||
{
|
||||
return reader.error();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
#undef TOML_ERROR_CHECK
|
||||
#undef TOML_ERROR
|
||||
|
||||
/// \endcond
|
1164
include/toml++/impl/value.h
Normal file
1164
include/toml++/impl/value.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,10 +5,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define TOML_LIB_MAJOR 2
|
||||
#define TOML_LIB_MINOR 5
|
||||
#define TOML_LIB_PATCH 0
|
||||
#define TOML_LIB_MAJOR 2
|
||||
#define TOML_LIB_MINOR 6
|
||||
#define TOML_LIB_PATCH 0
|
||||
|
||||
#define TOML_LANG_MAJOR 1
|
||||
#define TOML_LANG_MINOR 0
|
||||
#define TOML_LANG_PATCH 0
|
||||
#define TOML_LANG_MAJOR 1
|
||||
#define TOML_LANG_MINOR 0
|
||||
#define TOML_LANG_PATCH 0
|
@ -10,53 +10,53 @@
|
||||
//# they're listed explicitly here because this file
|
||||
//# is used as the source for generate_single_header.py.
|
||||
|
||||
#include "toml_preprocessor.h"
|
||||
#include "impl/preprocessor.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SPAM_WARNINGS;
|
||||
|
||||
#include "toml_common.h"
|
||||
#include "toml_date_time.h"
|
||||
#include "toml_print_to_stream.h"
|
||||
#include "toml_node.h"
|
||||
#include "toml_value.h"
|
||||
#include "toml_array.h"
|
||||
#include "toml_table.h"
|
||||
#include "toml_node_view.h"
|
||||
#include "toml_utf8.h"
|
||||
#include "impl/common.h"
|
||||
#include "impl/date_time.h"
|
||||
#include "impl/print_to_stream.h"
|
||||
#include "impl/node.h"
|
||||
#include "impl/value.h"
|
||||
#include "impl/array.h"
|
||||
#include "impl/table.h"
|
||||
#include "impl/node_view.h"
|
||||
#include "impl/utf8.h"
|
||||
#if TOML_PARSER
|
||||
#include "toml_parse_error.h"
|
||||
#include "toml_parse_result.h"
|
||||
#include "toml_utf8_streams.h"
|
||||
#include "toml_parser.h"
|
||||
#include "impl/parse_error.h"
|
||||
#include "impl/parse_result.h"
|
||||
#include "impl/utf8_streams.h"
|
||||
#include "impl/parser.h"
|
||||
#endif // TOML_PARSER
|
||||
#include "toml_formatter.h"
|
||||
#include "toml_default_formatter.h"
|
||||
#include "toml_json_formatter.h"
|
||||
#include "impl/formatter.h"
|
||||
#include "impl/default_formatter.h"
|
||||
#include "impl/json_formatter.h"
|
||||
|
||||
#if TOML_IMPLEMENTATION
|
||||
#include "toml_node.hpp"
|
||||
#include "toml_array.hpp"
|
||||
#include "toml_table.hpp"
|
||||
#include "impl/node_impl.h"
|
||||
#include "impl/array_impl.h"
|
||||
#include "impl/table_impl.h"
|
||||
#if TOML_PARSER
|
||||
#include "toml_utf8_streams.hpp"
|
||||
#include "toml_parser.hpp"
|
||||
#include "impl/utf8_streams_impl.h"
|
||||
#include "impl/parser_impl.h"
|
||||
#endif // TOML_PARSER
|
||||
#include "toml_default_formatter.hpp"
|
||||
#include "toml_json_formatter.hpp"
|
||||
#include "impl/default_formatter_impl.h"
|
||||
#include "impl/json_formatter_impl.h"
|
||||
#if !TOML_HEADER_ONLY
|
||||
#include "toml_instantiations.hpp"
|
||||
#include "impl/template_instantiations.h"
|
||||
#endif // !TOML_HEADER_ONLY
|
||||
#endif // TOML_IMPLEMENTATION
|
||||
#endif // TOML_IMPLEMENTATION
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_SPAM_WARNINGS
|
||||
|
||||
// macro hygiene
|
||||
#if TOML_UNDEF_MACROS
|
||||
#undef TOML_ABI_NAMESPACES
|
||||
#undef TOML_ABI_NAMESPACE_BOOL
|
||||
#undef TOML_ABI_NAMESPACE_END
|
||||
#undef TOML_ABI_NAMESPACE_START
|
||||
#undef TOML_ABI_NAMESPACES
|
||||
#undef TOML_ABSTRACT_BASE
|
||||
#undef TOML_ALWAYS_INLINE
|
||||
#undef TOML_ANON_NAMESPACE
|
||||
@ -72,39 +72,41 @@ TOML_POP_WARNINGS; // TOML_DISABLE_SPAM_WARNINGS
|
||||
#undef TOML_CONCAT
|
||||
#undef TOML_CONCAT_1
|
||||
#undef TOML_CONSTEVAL
|
||||
#undef TOML_CONSTRAINED_TEMPLATE
|
||||
#undef TOML_CPP
|
||||
#undef TOML_DISABLE_ARITHMETIC_WARNINGS
|
||||
#undef TOML_DISABLE_CODE_ANALYSIS_WARNINGS
|
||||
#undef TOML_DISABLE_INIT_WARNINGS
|
||||
#undef TOML_DISABLE_SPAM_WARNINGS
|
||||
#undef TOML_DISABLE_SHADOW_WARNINGS
|
||||
#undef TOML_DISABLE_SPAM_WARNINGS
|
||||
#undef TOML_DISABLE_SUGGEST_WARNINGS
|
||||
#undef TOML_DISABLE_SWITCH_WARNINGS
|
||||
#undef TOML_DISABLE_WARNINGS
|
||||
#undef TOML_ENABLE_WARNINGS
|
||||
#undef TOML_EMPTY_BASES
|
||||
#undef TOML_ENABLE_IF
|
||||
#undef TOML_ENABLE_WARNINGS
|
||||
#undef TOML_EVAL_BOOL_0
|
||||
#undef TOML_EVAL_BOOL_1
|
||||
#undef TOML_EXTERNAL_LINKAGE
|
||||
#undef TOML_FLOAT_CHARCONV
|
||||
#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_CHAR8
|
||||
#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_IMPLEMENTATION
|
||||
#undef TOML_INCLUDE_WINDOWS_H
|
||||
#undef TOML_INT_CHARCONV
|
||||
#undef TOML_INT128
|
||||
#undef TOML_INTELLISENSE
|
||||
#undef TOML_INTERNAL_LINKAGE
|
||||
#undef TOML_INT_CHARCONV
|
||||
#undef TOML_LANG_AT_LEAST
|
||||
#undef TOML_LANG_EFFECTIVE_VERSION
|
||||
#undef TOML_LANG_HIGHER_THAN
|
||||
@ -112,8 +114,8 @@ TOML_POP_WARNINGS; // TOML_DISABLE_SPAM_WARNINGS
|
||||
#undef TOML_LAUNDER
|
||||
#undef TOML_LIFETIME_HOOKS
|
||||
#undef TOML_LIKELY
|
||||
#undef TOML_MAKE_FLAGS_
|
||||
#undef TOML_MAKE_FLAGS
|
||||
#undef TOML_MAKE_FLAGS_
|
||||
#undef TOML_MAKE_VERSION
|
||||
#undef TOML_MAY_THROW
|
||||
#undef TOML_MSVC
|
||||
@ -121,11 +123,12 @@ TOML_POP_WARNINGS; // TOML_DISABLE_SPAM_WARNINGS
|
||||
#undef TOML_NAMESPACE_END
|
||||
#undef TOML_NAMESPACE_START
|
||||
#undef TOML_NEVER_INLINE
|
||||
#undef TOML_NODISCARD
|
||||
#undef TOML_NODISCARD_CTOR
|
||||
#undef TOML_NO_DEFAULT_CASE
|
||||
#undef TOML_PARSER_TYPENAME
|
||||
#undef TOML_POP_WARNINGS
|
||||
#undef TOML_PUSH_WARNINGS
|
||||
#undef TOML_REQUIRES
|
||||
#undef TOML_SA_LIST_BEG
|
||||
#undef TOML_SA_LIST_END
|
||||
#undef TOML_SA_LIST_NEW
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,356 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "toml_preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "toml_array.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::lh_ctor() noexcept
|
||||
{
|
||||
TOML_ARRAY_CREATED;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
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) ),
|
||||
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
|
||||
{
|
||||
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; }
|
||||
TOML_MEMBER_ATTR(const) bool array::is_table() const noexcept { return false; }
|
||||
TOML_MEMBER_ATTR(const) bool array::is_array() const noexcept { return true; }
|
||||
TOML_MEMBER_ATTR(const) bool array::is_value() const noexcept { return false; }
|
||||
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 *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 *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 { 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 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) { 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 < elements.size())
|
||||
elements.resize(new_size);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::iterator array::erase(const_iterator pos) noexcept
|
||||
{
|
||||
return { elements.erase(pos.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::iterator array::erase(const_iterator first, const_iterator last) noexcept
|
||||
{
|
||||
return { elements.erase(first.raw_, last.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::pop_back() noexcept
|
||||
{
|
||||
elements.pop_back();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
TOML_ATTR(pure)
|
||||
node* array::get(size_t index) noexcept
|
||||
{
|
||||
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 < elements.size() ? elements[index].get() : nullptr;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool operator == (const array& lhs, const array& rhs) noexcept
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.elements.size() != rhs.elements.size())
|
||||
return false;
|
||||
for (size_t i = 0, e = lhs.elements.size(); i < e; 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.elements[i]->visit([&](const auto& lhs_) noexcept
|
||||
{
|
||||
return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_);
|
||||
});
|
||||
if (!equal)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool operator != (const array& lhs, const array& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
size_t array::total_leaf_count() const noexcept
|
||||
{
|
||||
size_t leaves{};
|
||||
for (size_t i = 0, e = elements.size(); i < e; i++)
|
||||
{
|
||||
auto arr = elements[i]->as_array();
|
||||
leaves += arr ? arr->total_leaf_count() : 1_sz;
|
||||
}
|
||||
return leaves;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::flatten_child(array&& child, size_t& dest_index) noexcept
|
||||
{
|
||||
for (size_t i = 0, e = child.size(); i < e; i++)
|
||||
{
|
||||
auto type = child.elements[i]->type();
|
||||
if (type == node_type::array)
|
||||
{
|
||||
array& arr = *reinterpret_cast<array*>(child.elements[i].get());
|
||||
if (!arr.empty())
|
||||
flatten_child(std::move(arr), dest_index);
|
||||
}
|
||||
else
|
||||
elements[dest_index++] = std::move(child.elements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::flatten() &
|
||||
{
|
||||
if (elements.empty())
|
||||
return *this;
|
||||
|
||||
bool requires_flattening = false;
|
||||
size_t size_after_flattening = elements.size();
|
||||
for (size_t i = elements.size(); i --> 0_sz;)
|
||||
{
|
||||
auto arr = elements[i]->as_array();
|
||||
if (!arr)
|
||||
continue;
|
||||
size_after_flattening--; //discount the array itself
|
||||
const auto leaf_count = arr->total_leaf_count();
|
||||
if (leaf_count > 0_sz)
|
||||
{
|
||||
requires_flattening = true;
|
||||
size_after_flattening += leaf_count;
|
||||
}
|
||||
else
|
||||
elements.erase(elements.cbegin() + static_cast<ptrdiff_t>(i));
|
||||
}
|
||||
|
||||
if (!requires_flattening)
|
||||
return *this;
|
||||
|
||||
elements.reserve(size_after_flattening);
|
||||
|
||||
size_t i = 0;
|
||||
while (i < elements.size())
|
||||
{
|
||||
auto arr = elements[i]->as_array();
|
||||
if (!arr)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
flatten_child(std::move(*arr), i); //increments i
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool array::is_array_of_tables() const noexcept
|
||||
{
|
||||
return is_homogeneous(node_type::table);
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
@ -1,452 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "toml_formatter.h"
|
||||
#include "toml_table.h"
|
||||
#include "toml_array.h"
|
||||
#include "toml_utf8.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
|
||||
/// \cond
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
[[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;
|
||||
/// \endcond
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \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
|
||||
/// operators of the TOML node types already print themselves out using this formatter.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::table{{
|
||||
/// { "description", "This is some TOML, yo." },
|
||||
/// { "fruit", toml::array{ "apple", "orange", "pear" } },
|
||||
/// { "numbers", toml::array{ 1, 2, 3, 4, 5 } },
|
||||
/// { "table", toml::table{{ { "foo", "bar" } }} }
|
||||
/// }};
|
||||
///
|
||||
/// // these two lines are equivalent:
|
||||
/// std::cout << toml::default_formatter{ tbl } << "\n";
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// description = "This is some TOML, yo."
|
||||
/// fruit = ["apple", "orange", "pear"]
|
||||
/// numbers = [1, 2, 3, 4, 5]
|
||||
///
|
||||
/// [table]
|
||||
/// foo = "bar"
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Char The underlying character type of the output stream. Must be 1 byte in size.
|
||||
template <typename Char = char>
|
||||
class TOML_API default_formatter final : impl::formatter<Char>
|
||||
{
|
||||
private:
|
||||
/// \cond
|
||||
|
||||
using base = impl::formatter<Char>;
|
||||
std::vector<std::string> key_path;
|
||||
bool pending_table_separator_ = false;
|
||||
|
||||
void print_pending_table_separator()
|
||||
{
|
||||
if (pending_table_separator_)
|
||||
{
|
||||
base::print_newline(true);
|
||||
base::print_newline(true);
|
||||
pending_table_separator_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void print_key_segment(const std::string& str)
|
||||
{
|
||||
if (str.empty())
|
||||
impl::print_to_stream("''"sv, base::stream());
|
||||
else
|
||||
{
|
||||
bool requiresQuotes = false;
|
||||
{
|
||||
impl::utf8_decoder decoder;
|
||||
for (size_t i = 0; i < str.length() && !requiresQuotes; i++)
|
||||
{
|
||||
decoder(static_cast<uint8_t>(str[i]));
|
||||
if (decoder.error())
|
||||
requiresQuotes = true;
|
||||
else if (decoder.has_code_point())
|
||||
requiresQuotes = !impl::is_bare_key_character(decoder.codepoint);
|
||||
}
|
||||
}
|
||||
|
||||
if (requiresQuotes)
|
||||
{
|
||||
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());
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
|
||||
void print_key_path()
|
||||
{
|
||||
for (const auto& segment : key_path)
|
||||
{
|
||||
if (std::addressof(segment) > key_path.data())
|
||||
impl::print_to_stream('.', base::stream());
|
||||
impl::print_to_stream(segment, base::stream());
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
|
||||
void print_inline(const table& /*tbl*/);
|
||||
|
||||
void print(const array& arr)
|
||||
{
|
||||
if (arr.empty())
|
||||
impl::print_to_stream("[]"sv, base::stream());
|
||||
else
|
||||
{
|
||||
const auto original_indent = base::indent();
|
||||
const auto multiline = impl::default_formatter_forces_multiline(
|
||||
arr,
|
||||
base::indent_columns * static_cast<size_t>(original_indent < 0 ? 0 : original_indent)
|
||||
);
|
||||
impl::print_to_stream("["sv, base::stream());
|
||||
if (multiline)
|
||||
{
|
||||
if (original_indent < 0)
|
||||
base::indent(0);
|
||||
base::increase_indent();
|
||||
}
|
||||
else
|
||||
impl::print_to_stream(' ', base::stream());
|
||||
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
if (i > 0_sz)
|
||||
{
|
||||
impl::print_to_stream(',', base::stream());
|
||||
if (!multiline)
|
||||
impl::print_to_stream(' ', base::stream());
|
||||
}
|
||||
|
||||
if (multiline)
|
||||
{
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
}
|
||||
|
||||
auto& v = arr[i];
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default:
|
||||
base::print_value(v, type);
|
||||
}
|
||||
|
||||
}
|
||||
if (multiline)
|
||||
{
|
||||
base::indent(original_indent);
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
}
|
||||
else
|
||||
impl::print_to_stream(' ', base::stream());
|
||||
impl::print_to_stream("]"sv, base::stream());
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
|
||||
void print(const table& tbl)
|
||||
{
|
||||
static constexpr auto is_non_inline_array_of_tables = [](auto&& nde) noexcept
|
||||
{
|
||||
auto arr = nde.as_array();
|
||||
return arr
|
||||
&& arr->is_array_of_tables()
|
||||
&& !arr->template get_as<table>(0_sz)->is_inline();
|
||||
};
|
||||
|
||||
// values, arrays, and inline tables/table arrays
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
const auto type = v.type();
|
||||
if ((type == node_type::table && !reinterpret_cast<const table*>(&v)->is_inline())
|
||||
|| (type == node_type::array && is_non_inline_array_of_tables(v)))
|
||||
continue;
|
||||
|
||||
pending_table_separator_ = true;
|
||||
base::print_newline();
|
||||
base::print_indent();
|
||||
print_key_segment(k);
|
||||
impl::print_to_stream(" = "sv, base::stream());
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default:
|
||||
base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
|
||||
// non-inline tables
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
const auto type = v.type();
|
||||
if (type != node_type::table || reinterpret_cast<const table*>(&v)->is_inline())
|
||||
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)
|
||||
size_t child_value_count{}; //includes inline tables and non-table arrays
|
||||
size_t child_table_count{};
|
||||
size_t child_table_array_count{};
|
||||
for (auto&& [child_k, child_v] : child_tbl)
|
||||
{
|
||||
(void)child_k;
|
||||
const auto child_type = child_v.type();
|
||||
TOML_ASSUME(child_type != node_type::none);
|
||||
switch (child_type)
|
||||
{
|
||||
case node_type::table:
|
||||
if (reinterpret_cast<const table*>(&child_v)->is_inline())
|
||||
child_value_count++;
|
||||
else
|
||||
child_table_count++;
|
||||
break;
|
||||
|
||||
case node_type::array:
|
||||
if (is_non_inline_array_of_tables(child_v))
|
||||
child_table_array_count++;
|
||||
else
|
||||
child_value_count++;
|
||||
break;
|
||||
|
||||
default:
|
||||
child_value_count++;
|
||||
}
|
||||
}
|
||||
bool skip_self = false;
|
||||
if (child_value_count == 0_sz && (child_table_count > 0_sz || child_table_array_count > 0_sz))
|
||||
skip_self = true;
|
||||
|
||||
key_path.push_back(impl::default_formatter_make_key_segment(k));
|
||||
|
||||
if (!skip_self)
|
||||
{
|
||||
print_pending_table_separator();
|
||||
base::increase_indent();
|
||||
base::print_indent();
|
||||
impl::print_to_stream("["sv, base::stream());
|
||||
print_key_path();
|
||||
impl::print_to_stream("]"sv, base::stream());
|
||||
pending_table_separator_ = true;
|
||||
}
|
||||
|
||||
print(child_tbl);
|
||||
|
||||
key_path.pop_back();
|
||||
if (!skip_self)
|
||||
base::decrease_indent();
|
||||
}
|
||||
|
||||
// table arrays
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
if (!is_non_inline_array_of_tables(v))
|
||||
continue;
|
||||
auto& arr = *reinterpret_cast<const array*>(&v);
|
||||
|
||||
base::increase_indent();
|
||||
key_path.push_back(impl::default_formatter_make_key_segment(k));
|
||||
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
print_pending_table_separator();
|
||||
base::print_indent();
|
||||
impl::print_to_stream("[["sv, base::stream());
|
||||
print_key_path();
|
||||
impl::print_to_stream("]]"sv, base::stream());
|
||||
pending_table_separator_ = true;
|
||||
print(*reinterpret_cast<const table*>(&arr[i]));
|
||||
}
|
||||
|
||||
key_path.pop_back();
|
||||
base::decrease_indent();
|
||||
}
|
||||
}
|
||||
|
||||
void print()
|
||||
{
|
||||
if (base::dump_failed_parse_result())
|
||||
return;
|
||||
|
||||
switch (auto source_type = base::source().type())
|
||||
{
|
||||
case node_type::table:
|
||||
{
|
||||
auto& tbl = *reinterpret_cast<const table*>(&base::source());
|
||||
if (tbl.is_inline())
|
||||
print_inline(tbl);
|
||||
else
|
||||
{
|
||||
base::decrease_indent(); // so root kvps and tables have the same indent
|
||||
print(tbl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case node_type::array:
|
||||
print(*reinterpret_cast<const array*>(&base::source()));
|
||||
break;
|
||||
|
||||
default:
|
||||
base::print_value(base::source(), source_type);
|
||||
}
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
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 = default_flags) noexcept
|
||||
: base{ source, flags }
|
||||
{}
|
||||
|
||||
#if defined(DOXYGEN) || (TOML_PARSER && !TOML_EXCEPTIONS)
|
||||
|
||||
/// \brief Constructs a default TOML formatter and binds it to a toml::parse_result.
|
||||
///
|
||||
/// \availability This constructor is only available when exceptions are disabled.
|
||||
///
|
||||
/// \attention Formatting a failed parse result will simply dump the error message out as-is.
|
||||
/// This will not be valid TOML, but at least gives you something to log or show up in diagnostics:
|
||||
/// \cpp
|
||||
/// std::cout << toml::default_formatter{ toml::parse("a = 'b'"sv) } // ok
|
||||
/// << "\n\n"
|
||||
/// << toml::default_formatter{ toml::parse("a = "sv) } // malformed
|
||||
/// << "\n";
|
||||
/// \ecpp
|
||||
/// \out
|
||||
/// a = 'b'
|
||||
///
|
||||
/// Error while parsing key-value pair: encountered end-of-file
|
||||
/// (error occurred at line 1, column 5)
|
||||
/// \eout
|
||||
/// Use the library with exceptions if you want to avoid this scenario.
|
||||
///
|
||||
/// \param result The parse result.
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit default_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
|
||||
: base{ result, flags }
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T, typename U>
|
||||
friend std::basic_ostream<T>& operator << (std::basic_ostream<T>&, default_formatter<U>&);
|
||||
template <typename T, typename U>
|
||||
friend std::basic_ostream<T>& operator << (std::basic_ostream<T>&, default_formatter<U>&&);
|
||||
};
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template class TOML_API default_formatter<char>;
|
||||
#endif
|
||||
|
||||
default_formatter(const table&) -> default_formatter<char>;
|
||||
default_formatter(const array&) -> default_formatter<char>;
|
||||
template <typename T> default_formatter(const value<T>&) -> default_formatter<char>;
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as formatted TOML.
|
||||
template <typename T, typename U>
|
||||
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, default_formatter<U>& rhs)
|
||||
{
|
||||
rhs.attach(lhs);
|
||||
rhs.key_path.clear();
|
||||
rhs.print();
|
||||
rhs.detach();
|
||||
return lhs;
|
||||
}
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as formatted TOML (rvalue overload).
|
||||
template <typename T, typename U>
|
||||
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, default_formatter<U>&& rhs)
|
||||
{
|
||||
return lhs << rhs; //as lvalue
|
||||
}
|
||||
|
||||
#ifndef DOXYGEN
|
||||
|
||||
#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
|
||||
|
||||
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
|
||||
|
@ -1,272 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
/// \cond
|
||||
|
||||
#pragma once
|
||||
#include "toml_print_to_stream.h"
|
||||
#if TOML_PARSER && !TOML_EXCEPTIONS
|
||||
#include "toml_parse_result.h"
|
||||
#endif
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
template <typename Char = char>
|
||||
class TOML_API formatter
|
||||
{
|
||||
private:
|
||||
const toml::node* source_;
|
||||
std::basic_ostream<Char>* stream_ = {};
|
||||
format_flags flags_;
|
||||
int indent_;
|
||||
bool naked_newline_;
|
||||
#if TOML_PARSER && !TOML_EXCEPTIONS
|
||||
const parse_result* result_ = {};
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
[[nodiscard]] const toml::node& source() const noexcept { return *source_; }
|
||||
[[nodiscard]] std::basic_ostream<Char>& stream() const noexcept { return *stream_; }
|
||||
|
||||
static constexpr size_t indent_columns = 4;
|
||||
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_--; }
|
||||
|
||||
[[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
|
||||
{
|
||||
indent_ = {};
|
||||
naked_newline_ = true;
|
||||
stream_ = &stream;
|
||||
}
|
||||
|
||||
void detach() noexcept
|
||||
{
|
||||
stream_ = nullptr;
|
||||
}
|
||||
|
||||
void print_newline(bool force = false)
|
||||
{
|
||||
if (!naked_newline_ || force)
|
||||
{
|
||||
print_to_stream('\n', *stream_);
|
||||
naked_newline_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void print_indent()
|
||||
{
|
||||
for (int i = 0; i < indent_; i++)
|
||||
{
|
||||
print_to_stream(indent_string, *stream_);
|
||||
naked_newline_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void print_quoted_string(std::string_view str, bool allow_multi_line = true)
|
||||
{
|
||||
auto literals = literal_strings_allowed();
|
||||
if (str.empty())
|
||||
{
|
||||
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
|
||||
{
|
||||
const auto quot = multi_line ? R"(""")"sv : R"(")"sv;
|
||||
print_to_stream(quot, *stream_);
|
||||
print_to_stream_with_escapes(str, *stream_);
|
||||
print_to_stream(quot, *stream_);
|
||||
}
|
||||
clear_naked_newline();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void print(const value<T>& val)
|
||||
{
|
||||
if constexpr (std::is_same_v<T, std::string>)
|
||||
{
|
||||
print_quoted_string(val.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr (is_one_of<T, date, time, date_time>)
|
||||
{
|
||||
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_);
|
||||
}
|
||||
else if constexpr (is_one_of<T, int64_t/*, double*/>)
|
||||
{
|
||||
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;
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void print_value(const node& val_node, node_type type)
|
||||
{
|
||||
TOML_ASSUME(type > node_type::array);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::string: print(*reinterpret_cast<const value<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;
|
||||
case node_type::date: print(*reinterpret_cast<const value<date>*>(&val_node)); break;
|
||||
case node_type::time: print(*reinterpret_cast<const value<time>*>(&val_node)); break;
|
||||
case node_type::date_time: print(*reinterpret_cast<const value<date_time>*>(&val_node)); break;
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
bool dump_failed_parse_result()
|
||||
{
|
||||
#if TOML_PARSER && !TOML_EXCEPTIONS
|
||||
if (result_ && !(*result_))
|
||||
{
|
||||
stream() << result_->error();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
formatter(const toml::node& source, format_flags flags) noexcept
|
||||
: source_{ &source },
|
||||
flags_{ flags }
|
||||
{}
|
||||
|
||||
#if TOML_PARSER && !TOML_EXCEPTIONS
|
||||
|
||||
formatter(const parse_result& result, format_flags flags) noexcept
|
||||
: source_{ result ? &result.table() : nullptr },
|
||||
flags_{ flags },
|
||||
result_{ &result }
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template class TOML_API formatter<char>;
|
||||
#endif
|
||||
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_SWITCH_WARNINGS
|
||||
|
||||
/// \endcond
|
@ -1,200 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "toml_formatter.h"
|
||||
#include "toml_table.h"
|
||||
#include "toml_array.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A wrapper for printing TOML objects out to a stream as formatted JSON.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto some_toml = toml::parse(R"(
|
||||
/// [fruit]
|
||||
/// apple.color = "red"
|
||||
/// apple.taste.sweet = true
|
||||
///
|
||||
/// [fruit.apple.texture]
|
||||
/// smooth = true
|
||||
/// )"sv);
|
||||
/// std::cout << toml::json_formatter{ some_toml } << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// {
|
||||
/// "fruit" : {
|
||||
/// "apple" : {
|
||||
/// "color" : "red",
|
||||
/// "taste" : {
|
||||
/// "sweet" : true
|
||||
/// },
|
||||
/// "texture" : {
|
||||
/// "smooth" : true
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Char The underlying character type of the output stream. Must be 1 byte in size.
|
||||
template <typename Char = char>
|
||||
class TOML_API json_formatter final : impl::formatter<Char>
|
||||
{
|
||||
private:
|
||||
/// \cond
|
||||
|
||||
using base = impl::formatter<Char>;
|
||||
|
||||
void print(const toml::table& tbl);
|
||||
|
||||
void print(const array& arr)
|
||||
{
|
||||
if (arr.empty())
|
||||
impl::print_to_stream("[]"sv, base::stream());
|
||||
else
|
||||
{
|
||||
impl::print_to_stream('[', base::stream());
|
||||
base::increase_indent();
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
if (i > 0_sz)
|
||||
impl::print_to_stream(',', base::stream());
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
|
||||
auto& v = arr[i];
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default:
|
||||
base::print_value(v, type);
|
||||
}
|
||||
|
||||
}
|
||||
base::decrease_indent();
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
impl::print_to_stream(']', base::stream());
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
|
||||
void print()
|
||||
{
|
||||
if (base::dump_failed_parse_result())
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
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 = default_flags) noexcept
|
||||
: base{ source, flags }
|
||||
{}
|
||||
|
||||
#if defined(DOXYGEN) || (TOML_PARSER && !TOML_EXCEPTIONS)
|
||||
|
||||
/// \brief Constructs a JSON formatter and binds it to a toml::parse_result.
|
||||
///
|
||||
/// \availability This constructor is only available when exceptions are disabled.
|
||||
///
|
||||
/// \attention Formatting a failed parse result will simply dump the error message out as-is.
|
||||
/// This will not be valid JSON, but at least gives you something to log or show up in diagnostics:
|
||||
/// \cpp
|
||||
/// std::cout << toml::json_formatter{ toml::parse("a = 'b'"sv) } // ok
|
||||
/// << "\n\n"
|
||||
/// << toml::json_formatter{ toml::parse("a = "sv) } // malformed
|
||||
/// << "\n";
|
||||
/// \ecpp
|
||||
/// \out
|
||||
/// {
|
||||
/// "a" : "b"
|
||||
/// }
|
||||
///
|
||||
/// Error while parsing key-value pair: encountered end-of-file
|
||||
/// (error occurred at line 1, column 5)
|
||||
/// \eout
|
||||
/// Use the library with exceptions if you want to avoid this scenario.
|
||||
///
|
||||
/// \param result The parse result.
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit json_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
|
||||
: base{ result, flags }
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T, typename U>
|
||||
friend std::basic_ostream<T>& operator << (std::basic_ostream<T>&, json_formatter<U>&);
|
||||
template <typename T, typename U>
|
||||
friend std::basic_ostream<T>& operator << (std::basic_ostream<T>&, json_formatter<U>&&);
|
||||
};
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template class TOML_API json_formatter<char>;
|
||||
#endif
|
||||
|
||||
json_formatter(const table&) -> json_formatter<char>;
|
||||
json_formatter(const array&) -> json_formatter<char>;
|
||||
template <typename T> json_formatter(const value<T>&) -> json_formatter<char>;
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as JSON.
|
||||
template <typename T, typename U>
|
||||
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, json_formatter<U>& rhs)
|
||||
{
|
||||
rhs.attach(lhs);
|
||||
rhs.print();
|
||||
rhs.detach();
|
||||
return lhs;
|
||||
}
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as JSON (rvalue overload).
|
||||
template <typename T, typename U>
|
||||
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, json_formatter<U>&& rhs)
|
||||
{
|
||||
return lhs << rhs; //as lvalue
|
||||
}
|
||||
|
||||
#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
|
@ -1,886 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "toml_common.h"
|
||||
|
||||
#if defined(DOXYGEN) || TOML_SIMPLE_STATIC_ASSERT_MESSAGES
|
||||
|
||||
#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.
|
||||
///
|
||||
/// \detail A parsed TOML document forms a tree made up of tables, arrays and values.
|
||||
/// This type is the base of each of those, providing a lot of the polymorphic plumbing.
|
||||
class TOML_ABSTRACT_BASE TOML_API node
|
||||
{
|
||||
private:
|
||||
friend class TOML_PARSER_TYPENAME;
|
||||
source_region source_{};
|
||||
|
||||
/// \cond
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
decltype(auto) get_value_exact() const noexcept;
|
||||
|
||||
template <typename T, typename N>
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(pure)
|
||||
static decltype(auto) do_ref(N&& n) noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert(
|
||||
(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_native<type>)
|
||||
return static_cast<N&&>(n).template ref_cast<type>().get();
|
||||
else
|
||||
return static_cast<N&&>(n).template ref_cast<type>();
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
protected:
|
||||
|
||||
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
|
||||
TOML_ATTR(pure)
|
||||
impl::wrap_node<T>& ref_cast() & noexcept
|
||||
{
|
||||
return *reinterpret_cast<impl::wrap_node<T>*>(this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
TOML_ALWAYS_INLINE
|
||||
TOML_ATTR(pure)
|
||||
impl::wrap_node<T>&& ref_cast() && noexcept
|
||||
{
|
||||
return std::move(*reinterpret_cast<impl::wrap_node<T>*>(this));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
TOML_ALWAYS_INLINE
|
||||
TOML_ATTR(pure)
|
||||
const impl::wrap_node<T>& ref_cast() const & noexcept
|
||||
{
|
||||
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>());
|
||||
|
||||
public:
|
||||
|
||||
virtual ~node() noexcept = default;
|
||||
|
||||
/// \name Type checks
|
||||
/// @{
|
||||
|
||||
#if defined(DOXYGEN) || !TOML_ICC || TOML_ICC_CL
|
||||
|
||||
/// \brief Returns the node's type identifier.
|
||||
[[nodiscard]] virtual node_type type() const noexcept = 0;
|
||||
|
||||
#else
|
||||
|
||||
[[nodiscard]] virtual node_type type() const noexcept
|
||||
{
|
||||
// Q: "what the fuck?"
|
||||
// A: https://github.com/marzer/tomlplusplus/issues/83
|
||||
// tl,dr: go home ICC, you're drunk.
|
||||
|
||||
return type();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// \brief Returns true if this node is a table.
|
||||
[[nodiscard]] virtual bool is_table() const noexcept = 0;
|
||||
/// \brief Returns true if this node is an array.
|
||||
[[nodiscard]] virtual bool is_array() const noexcept = 0;
|
||||
/// \brief Returns true if this node is a value.
|
||||
[[nodiscard]] virtual bool is_value() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is a string value.
|
||||
[[nodiscard]] virtual bool is_string() const noexcept;
|
||||
/// \brief Returns true if this node is an integer value.
|
||||
[[nodiscard]] virtual bool is_integer() const noexcept;
|
||||
/// \brief Returns true if this node is an floating-point value.
|
||||
[[nodiscard]] virtual bool is_floating_point() const noexcept;
|
||||
/// \brief Returns true if this node is an integer or floating-point value.
|
||||
[[nodiscard]] virtual bool is_number() const noexcept;
|
||||
/// \brief Returns true if this node is a boolean value.
|
||||
[[nodiscard]] virtual bool is_boolean() const noexcept;
|
||||
/// \brief Returns true if this node is a local date value.
|
||||
[[nodiscard]] virtual bool is_date() const noexcept;
|
||||
/// \brief Returns true if this node is a local time value.
|
||||
[[nodiscard]] virtual bool is_time() const noexcept;
|
||||
/// \brief Returns true if this node is a date-time value.
|
||||
[[nodiscard]] virtual bool is_date_time() const noexcept;
|
||||
/// \brief Returns true if this node is an array containing only tables.
|
||||
[[nodiscard]] virtual bool is_array_of_tables() const noexcept;
|
||||
|
||||
/// \brief Checks if a node is a specific type.
|
||||
///
|
||||
/// \tparam T A TOML node or value type.
|
||||
///
|
||||
/// \returns Returns true if this node is an instance of the specified type.
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(pure)
|
||||
bool is() const noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert(
|
||||
(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, 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();
|
||||
else if constexpr (std::is_same_v<type, date>) return is_date();
|
||||
else if constexpr (std::is_same_v<type, time>) return is_time();
|
||||
else if constexpr (std::is_same_v<type, date_time>) return is_date_time();
|
||||
}
|
||||
|
||||
/// \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();
|
||||
///
|
||||
/// 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
|
||||
/// array was not homogeneous!
|
||||
/// first non-match was a floating-point at line 1, column 18
|
||||
/// \eout
|
||||
///
|
||||
/// \param ntype A TOML node type. <br>
|
||||
/// \conditional_return{toml::node_type::none}
|
||||
/// "is every element the same type?"
|
||||
/// \conditional_return{Anything else}
|
||||
/// "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 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 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.
|
||||
///
|
||||
/// \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>
|
||||
/// \conditional_return{toml::node_type::none}
|
||||
/// "is every element the same type?"
|
||||
/// \conditional_return{Anything else}
|
||||
/// "is every element one of these?"
|
||||
///
|
||||
/// \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>
|
||||
/// \conditional_return{Left as `void`}
|
||||
/// "is every element the same type?" <br>
|
||||
/// \conditional_return{Explicitly specified}
|
||||
/// "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]]
|
||||
TOML_ATTR(pure)
|
||||
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>);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Type casts
|
||||
/// @{
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::table, if it is one.
|
||||
[[nodiscard]] virtual table* as_table() noexcept;
|
||||
/// \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<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.
|
||||
[[nodiscard]] virtual toml::value<double>* as_floating_point() noexcept;
|
||||
/// \brief Returns a pointer to the node as a toml::value<bool>, if it is one.
|
||||
[[nodiscard]] virtual toml::value<bool>* as_boolean() noexcept;
|
||||
/// \brief Returns a pointer to the node as a toml::value<date>, if it is one.
|
||||
[[nodiscard]] virtual toml::value<date>* as_date() noexcept;
|
||||
/// \brief Returns a pointer to the node as a toml::value<time>, if it is one.
|
||||
[[nodiscard]] virtual toml::value<time>* as_time() noexcept;
|
||||
/// \brief Returns a pointer to the node as a toml::value<date_time>, if it is one.
|
||||
[[nodiscard]] virtual toml::value<date_time>* as_date_time() noexcept;
|
||||
|
||||
[[nodiscard]] virtual const table* as_table() const noexcept;
|
||||
[[nodiscard]] virtual const array* as_array() 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;
|
||||
[[nodiscard]] virtual const toml::value<date>* as_date() const noexcept;
|
||||
[[nodiscard]] virtual const toml::value<time>* as_time() const noexcept;
|
||||
[[nodiscard]] virtual const toml::value<date_time>* as_date_time() const noexcept;
|
||||
|
||||
/// \brief Gets a pointer to the node as a more specific node type.
|
||||
///
|
||||
/// \details \cpp
|
||||
///
|
||||
/// 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>\n";
|
||||
/// else if (tbl)
|
||||
/// 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>\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \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.
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(pure)
|
||||
impl::wrap_node<T>* as() noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert(
|
||||
(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, 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();
|
||||
else if constexpr (std::is_same_v<type, date>) return as_date();
|
||||
else if constexpr (std::is_same_v<type, time>) return as_time();
|
||||
else if constexpr (std::is_same_v<type, date_time>) return as_date_time();
|
||||
}
|
||||
|
||||
/// \brief Gets a pointer to the node as a more specific node type (const overload).
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(pure)
|
||||
const impl::wrap_node<T>* as() const noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert(
|
||||
(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, 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();
|
||||
else if constexpr (std::is_same_v<type, date>) return as_date();
|
||||
else if constexpr (std::is_same_v<type, time>) return as_time();
|
||||
else if constexpr (std::is_same_v<type, date_time>) return as_date_time();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Value retrieval
|
||||
/// @{
|
||||
|
||||
/// \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]]
|
||||
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.
|
||||
///
|
||||
/// \note 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.
|
||||
///
|
||||
/// \note 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 raw reference to a value node's underlying data.
|
||||
///
|
||||
/// \warning This function is dangerous if used carelessly and **WILL** break your code if the
|
||||
/// chosen value type doesn't match the node's actual type. In debug builds an assertion
|
||||
/// will fire when invalid accesses are attempted: \cpp
|
||||
///
|
||||
/// auto tbl = toml::parse(R"(
|
||||
/// min = 32
|
||||
/// max = 45
|
||||
/// )"sv);
|
||||
///
|
||||
/// int64_t& min_ref = tbl.get("min")->ref<int64_t>(); // matching type
|
||||
/// double& max_ref = tbl.get("max")->ref<double>(); // mismatched type, hits assert()
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \tparam T One of the TOML value types.
|
||||
///
|
||||
/// \returns A reference to the underlying data.
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(pure)
|
||||
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]]
|
||||
TOML_ATTR(pure)
|
||||
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]]
|
||||
TOML_ATTR(pure)
|
||||
const impl::unwrap_node<T>& ref() const& noexcept
|
||||
{
|
||||
return do_ref<T>(*this);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Metadata
|
||||
/// @{
|
||||
|
||||
/// \brief Returns the source region responsible for generating this node during parsing.
|
||||
[[nodiscard]] const source_region& source() const noexcept;
|
||||
|
||||
/// @}
|
||||
|
||||
private:
|
||||
|
||||
/// \cond
|
||||
|
||||
template <typename Func, typename N, typename T>
|
||||
static constexpr bool can_visit = std::is_invocable_v<Func, ref_cast_type<N, T>>;
|
||||
|
||||
template <typename Func, typename N>
|
||||
static constexpr bool can_visit_any =
|
||||
can_visit<Func, N, table>
|
||||
|| can_visit<Func, N, array>
|
||||
|| can_visit<Func, N, std::string>
|
||||
|| can_visit<Func, N, int64_t>
|
||||
|| can_visit<Func, N, double>
|
||||
|| can_visit<Func, N, bool>
|
||||
|| can_visit<Func, N, date>
|
||||
|| can_visit<Func, N, time>
|
||||
|| can_visit<Func, N, date_time>;
|
||||
|
||||
template <typename Func, typename N>
|
||||
static constexpr bool can_visit_all =
|
||||
can_visit<Func, N, table>
|
||||
&& can_visit<Func, N, array>
|
||||
&& can_visit<Func, N, std::string>
|
||||
&& can_visit<Func, N, int64_t>
|
||||
&& can_visit<Func, N, double>
|
||||
&& can_visit<Func, N, bool>
|
||||
&& can_visit<Func, N, date>
|
||||
&& can_visit<Func, N, time>
|
||||
&& can_visit<Func, N, date_time>;
|
||||
|
||||
template <typename Func, typename N, typename T>
|
||||
static constexpr bool visit_is_nothrow_one =
|
||||
!can_visit<Func, N, T>
|
||||
|| std::is_nothrow_invocable_v<Func, ref_cast_type<N, T>>;
|
||||
|
||||
template <typename Func, typename N>
|
||||
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, std::string>
|
||||
&& visit_is_nothrow_one<Func, N, int64_t>
|
||||
&& visit_is_nothrow_one<Func, N, double>
|
||||
&& visit_is_nothrow_one<Func, N, bool>
|
||||
&& visit_is_nothrow_one<Func, N, date>
|
||||
&& visit_is_nothrow_one<Func, N, time>
|
||||
&& visit_is_nothrow_one<Func, N, date_time>;
|
||||
|
||||
template <typename Func, typename N, typename T, bool = can_visit<Func, N, T>>
|
||||
struct visit_return_type final
|
||||
{
|
||||
using type = decltype(std::declval<Func>()(std::declval<ref_cast_type<N, T>>()));
|
||||
};
|
||||
template <typename Func, typename N, typename T>
|
||||
struct visit_return_type<Func, N, T, false> final
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
|
||||
template <typename A, typename B>
|
||||
using nonvoid = std::conditional_t<std::is_void_v<A>, B, A>;
|
||||
|
||||
//# these functions are static helpers to preserve const and ref categories
|
||||
//# (otherwise I'd have to implement them thrice)
|
||||
//# ((propagation in C++: a modern horror story))
|
||||
|
||||
template <typename N, typename Func>
|
||||
static decltype(auto) do_visit(N&& n, Func&& visitor)
|
||||
noexcept(visit_is_nothrow<Func&&, N&&>)
|
||||
{
|
||||
static_assert(
|
||||
can_visit_any<Func&&, N&&>,
|
||||
"TOML node visitors must be invocable for at least one of the toml::node specializations:"
|
||||
TOML_SA_NODE_TYPE_LIST
|
||||
);
|
||||
|
||||
switch (n.type())
|
||||
{
|
||||
case node_type::table:
|
||||
if constexpr (can_visit<Func&&, N&&, table>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<table>());
|
||||
break;
|
||||
|
||||
case node_type::array:
|
||||
if constexpr (can_visit<Func&&, N&&, array>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<array>());
|
||||
break;
|
||||
|
||||
case node_type::string:
|
||||
if constexpr (can_visit<Func&&, N&&, std::string>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<std::string>());
|
||||
break;
|
||||
|
||||
case node_type::integer:
|
||||
if constexpr (can_visit<Func&&, N&&, int64_t>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<int64_t>());
|
||||
break;
|
||||
|
||||
case node_type::floating_point:
|
||||
if constexpr (can_visit<Func&&, N&&, double>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<double>());
|
||||
break;
|
||||
|
||||
case node_type::boolean:
|
||||
if constexpr (can_visit<Func&&, N&&, bool>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<bool>());
|
||||
break;
|
||||
|
||||
case node_type::date:
|
||||
if constexpr (can_visit<Func&&, N&&, date>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<date>());
|
||||
break;
|
||||
|
||||
case node_type::time:
|
||||
if constexpr (can_visit<Func&&, N&&, time>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<time>());
|
||||
break;
|
||||
|
||||
case node_type::date_time:
|
||||
if constexpr (can_visit<Func&&, N&&, date_time>)
|
||||
return static_cast<Func&&>(visitor)(static_cast<N&&>(n).template ref_cast<date_time>());
|
||||
break;
|
||||
|
||||
case node_type::none: TOML_UNREACHABLE;
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
|
||||
if constexpr (can_visit_all<Func&&, N&&>)
|
||||
TOML_UNREACHABLE;
|
||||
else
|
||||
{
|
||||
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&&, 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,
|
||||
nonvoid<typename visit_return_type<Func&&, N&&, date>::type,
|
||||
nonvoid<typename visit_return_type<Func&&, N&&, time>::type,
|
||||
typename visit_return_type<Func&&, N&&, date_time>::type
|
||||
>>>>>>>>;
|
||||
|
||||
if constexpr (!std::is_void_v<return_type>)
|
||||
{
|
||||
static_assert(
|
||||
std::is_default_constructible_v<return_type>,
|
||||
"Non-exhaustive visitors must return a default-constructible type, or void"
|
||||
);
|
||||
return return_type{};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
public:
|
||||
|
||||
/// \name Visitation
|
||||
/// @{
|
||||
|
||||
/// \brief Invokes a visitor on the node based on the node's concrete type.
|
||||
///
|
||||
/// \details Visitation is useful when you expect
|
||||
/// a node to be one of a set number of types and need
|
||||
/// to handle these types differently. Using `visit()` allows
|
||||
/// you to eliminate some of the casting/conversion boilerplate: \cpp
|
||||
///
|
||||
/// node.visit([](auto&& n)
|
||||
/// {
|
||||
/// if constexpr (toml::is_string<decltype(n)>)
|
||||
/// 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
|
||||
/// throw std::exception{ "Expected string or integer" };
|
||||
/// });
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \tparam Func A callable type invocable with one or more of the
|
||||
/// toml++ node types.
|
||||
///
|
||||
/// \param visitor The visitor object.
|
||||
///
|
||||
/// \returns The return value of the visitor.
|
||||
/// Can be void. Non-exhaustive visitors must return a default-constructible type.
|
||||
///
|
||||
/// \see https://en.wikipedia.org/wiki/Visitor_pattern
|
||||
template <typename Func>
|
||||
decltype(auto) visit(Func&& visitor) &
|
||||
noexcept(visit_is_nothrow<Func&&, node&>)
|
||||
{
|
||||
return do_visit(*this, static_cast<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&&>)
|
||||
{
|
||||
return do_visit(static_cast<node&&>(*this), static_cast<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&>)
|
||||
{
|
||||
return do_visit(*this, static_cast<Func&&>(visitor));
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Node views
|
||||
/// @{
|
||||
|
||||
/// \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_NAMESPACE_END;
|
@ -1,102 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "toml_preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "toml_node.h"
|
||||
|
||||
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_) }
|
||||
{
|
||||
other.source_.begin = {};
|
||||
other.source_.end = {};
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
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 = {};
|
||||
rhs.source_.end = {};
|
||||
return *this;
|
||||
}
|
||||
|
||||
#define TOML_MEMBER_ATTR(attr) TOML_EXTERNAL_LINKAGE TOML_ATTR(attr)
|
||||
|
||||
TOML_MEMBER_ATTR(const) bool node::is_string() const noexcept { return false; }
|
||||
TOML_MEMBER_ATTR(const) bool node::is_integer() const noexcept { return false; }
|
||||
TOML_MEMBER_ATTR(const) bool node::is_floating_point() const noexcept { return false; }
|
||||
TOML_MEMBER_ATTR(const) bool node::is_number() const noexcept { return false; }
|
||||
TOML_MEMBER_ATTR(const) bool node::is_boolean() const noexcept { return false; }
|
||||
TOML_MEMBER_ATTR(const) bool node::is_date() const noexcept { return false; }
|
||||
TOML_MEMBER_ATTR(const) bool node::is_time() const noexcept { return false; }
|
||||
TOML_MEMBER_ATTR(const) bool node::is_date_time() const noexcept { return false; }
|
||||
TOML_MEMBER_ATTR(const) bool node::is_array_of_tables() const noexcept { return false; }
|
||||
|
||||
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<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; }
|
||||
TOML_MEMBER_ATTR(const) value<date>* node::as_date() noexcept { return nullptr; }
|
||||
TOML_MEMBER_ATTR(const) value<time>* node::as_time() noexcept { return nullptr; }
|
||||
TOML_MEMBER_ATTR(const) value<date_time>* node::as_date_time() noexcept { return nullptr; }
|
||||
|
||||
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<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; }
|
||||
TOML_MEMBER_ATTR(const) const value<date>* node::as_date() const noexcept { return nullptr; }
|
||||
TOML_MEMBER_ATTR(const) const value<time>* node::as_time() const noexcept { return nullptr; }
|
||||
TOML_MEMBER_ATTR(const) const value<date_time>* node::as_date_time() const noexcept { return nullptr; }
|
||||
|
||||
TOML_MEMBER_ATTR(const) const source_region& node::source() const noexcept { return source_; }
|
||||
|
||||
#undef TOML_MEMBER_ATTR
|
||||
|
||||
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;
|
@ -1,711 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "toml_table.h"
|
||||
#include "toml_array.h"
|
||||
#include "toml_value.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_ARITHMETIC_WARNINGS;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A view of a node.
|
||||
///
|
||||
/// \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"(
|
||||
///
|
||||
/// title = "my hardware store"
|
||||
///
|
||||
/// [[products]]
|
||||
/// name = "Hammer"
|
||||
/// sku = 738594937
|
||||
/// keywords = [ "hammer", "construction", "build" ]
|
||||
///
|
||||
/// [[products]]
|
||||
/// name = "Nail"
|
||||
/// sku = 284758393
|
||||
/// color = "gray"
|
||||
///
|
||||
/// )"sv);
|
||||
///
|
||||
/// 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"] << "\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"
|
||||
/// "Hammer"
|
||||
/// [ "hammer", "construction", "build" ]
|
||||
/// "build"
|
||||
/// [ "hammer", "construction", "build", "heavy" ]
|
||||
/// has product[2]: false
|
||||
/// product[2]:
|
||||
/// \eout
|
||||
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 = ViewedType;
|
||||
|
||||
private:
|
||||
template <typename T> friend class TOML_NAMESPACE::node_view;
|
||||
|
||||
mutable viewed_type* node_ = nullptr;
|
||||
|
||||
template <typename Func>
|
||||
static constexpr bool visit_is_nothrow
|
||||
= noexcept(std::declval<viewed_type*>()->visit(std::declval<Func&&>()));
|
||||
|
||||
public:
|
||||
|
||||
/// \brief Constructs an empty node view.
|
||||
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* node() const noexcept { return node_; }
|
||||
|
||||
/// \name Type checks
|
||||
/// @{
|
||||
|
||||
/// \brief Returns the type identifier for the viewed node.
|
||||
[[nodiscard]] node_type type() const noexcept { return node_ ? node_->type() : node_type::none; }
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::table.
|
||||
[[nodiscard]] bool is_table() const noexcept { return node_ && node_->is_table(); }
|
||||
/// \brief Returns true if the viewed node is a toml::array.
|
||||
[[nodiscard]] bool is_array() const noexcept { return node_ && node_->is_array(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<>.
|
||||
[[nodiscard]] bool is_value() const noexcept { return node_ && node_->is_value(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<string>.
|
||||
[[nodiscard]] bool is_string() const noexcept { return node_ && node_->is_string(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<int64_t>.
|
||||
[[nodiscard]] bool is_integer() const noexcept { return node_ && node_->is_integer(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<double>.
|
||||
[[nodiscard]] bool is_floating_point() const noexcept { return node_ && node_->is_floating_point(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<int64_t> or toml::value<double>.
|
||||
[[nodiscard]] bool is_number() const noexcept { return node_ && node_->is_number(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<bool>.
|
||||
[[nodiscard]] bool is_boolean() const noexcept { return node_ && node_->is_boolean(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<date>.
|
||||
[[nodiscard]] bool is_date() const noexcept { return node_ && node_->is_date(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<time>.
|
||||
[[nodiscard]] bool is_time() const noexcept { return node_ && node_->is_time(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<date_time>.
|
||||
[[nodiscard]] bool is_date_time() const noexcept { return node_ && node_->is_date_time(); }
|
||||
/// \brief Returns true if the viewed node is a toml::array that contains only tables.
|
||||
[[nodiscard]] bool is_array_of_tables() const noexcept { return node_ && node_->is_array_of_tables(); }
|
||||
|
||||
/// \brief Checks if this view references a node of a specific 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 T>
|
||||
[[nodiscard]]
|
||||
bool is() const noexcept
|
||||
{
|
||||
return node_ ? node_->template is<T>() : false;
|
||||
}
|
||||
|
||||
/// \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>
|
||||
/// \conditional_return{toml::node_type::none} "is every element the same type?"
|
||||
/// \conditional_return{Anything else} "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>
|
||||
/// \conditional_return{toml::node_type::none} "is every element the same type?"
|
||||
/// \conditional_return{Anything else} "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>
|
||||
/// \conditional_return{Left as `void`} "is every element the same type?" <br>
|
||||
/// \conditional_return{Explicitly specified} "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;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Type casts
|
||||
/// @{
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::table, if it is one.
|
||||
[[nodiscard]] auto as_table() const noexcept { return as<table>(); }
|
||||
/// \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<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.
|
||||
[[nodiscard]] auto as_floating_point() const noexcept { return as<double>(); }
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<bool>, if it is one.
|
||||
[[nodiscard]] auto as_boolean() const noexcept { return as<bool>(); }
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<date>, if it is one.
|
||||
[[nodiscard]] auto as_date() const noexcept { return as<date>(); }
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<time>, if it is one.
|
||||
[[nodiscard]] auto as_time() const noexcept { return as<time>(); }
|
||||
/// \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 Gets a pointer to the viewed node as a more specific node type.
|
||||
///
|
||||
/// \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 T>
|
||||
[[nodiscard]]
|
||||
auto as() const noexcept
|
||||
{
|
||||
return node_ ? node_->template as<T>() : nullptr;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Value retrieval
|
||||
/// @{
|
||||
|
||||
/// \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 value contained by the referenced 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. 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)
|
||||
/// and within the range of the output type, or an empty optional.
|
||||
///
|
||||
/// \note 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<T>();
|
||||
return {};
|
||||
}
|
||||
|
||||
TOML_POP_WARNINGS;
|
||||
|
||||
/// \brief Gets the raw value contained by the referenced 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.
|
||||
///
|
||||
/// \note 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 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(static_cast<T&&>(default_value));
|
||||
return std::wstring{ static_cast<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(static_cast<T&&>(default_value));
|
||||
if constexpr (std::is_pointer_v<value_type>)
|
||||
return value_type{ default_value };
|
||||
else
|
||||
return static_cast<T&&>(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Gets a raw reference to the viewed node's underlying data.
|
||||
///
|
||||
/// \warning This function is dangerous if used carelessly and **WILL** break your code if the
|
||||
/// node_view didn't reference a node, or the chosen value type doesn't match the node's
|
||||
/// actual type. In debug builds an assertion will fire when invalid accesses are attempted: \cpp
|
||||
///
|
||||
/// auto tbl = toml::parse(R"(
|
||||
/// min = 32
|
||||
/// max = 45
|
||||
/// )"sv);
|
||||
///
|
||||
/// int64_t& min_ref = tbl["min"].ref<int64_t>(); // matching type
|
||||
/// double& max_ref = tbl["max"].ref<double>(); // mismatched type, hits assert()
|
||||
/// int64_t& foo_ref = tbl["foo"].ref<int64_t>(); // nonexistent key, hits assert()
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \tparam T One of the TOML value types.
|
||||
///
|
||||
/// \returns A reference to the underlying data.
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
decltype(auto) ref() const noexcept
|
||||
{
|
||||
TOML_ASSERT(
|
||||
node_
|
||||
&& "toml::node_view::ref() called on a node_view that did not reference a node"
|
||||
);
|
||||
return node_->template ref<impl::unwrap_node<T>>();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Visitation
|
||||
/// @{
|
||||
|
||||
/// \brief Invokes a visitor on the viewed node based on its concrete type.
|
||||
///
|
||||
/// \remarks Has no effect if the view does not reference a node.
|
||||
///
|
||||
/// \see node::visit()
|
||||
template <typename Func>
|
||||
decltype(auto) visit(Func&& visitor) const
|
||||
noexcept(visit_is_nothrow<Func&&>)
|
||||
{
|
||||
using return_type = decltype(node_->visit(static_cast<Func&&>(visitor)));
|
||||
if (node_)
|
||||
return node_->visit(static_cast<Func&&>(visitor));
|
||||
if constexpr (!std::is_void_v<return_type>)
|
||||
return return_type{};
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Equality
|
||||
/// @{
|
||||
|
||||
/// \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
|
||||
{
|
||||
if (lhs.node_ == &rhs)
|
||||
return true;
|
||||
const auto tbl = lhs.as<table>();
|
||||
return tbl && *tbl == rhs;
|
||||
}
|
||||
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
|
||||
{
|
||||
if (lhs.node_ == &rhs)
|
||||
return true;
|
||||
const auto arr = lhs.as<array>();
|
||||
return arr && *arr == rhs;
|
||||
}
|
||||
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 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<T>();
|
||||
return val && *val == rhs;
|
||||
}
|
||||
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 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
|
||||
{
|
||||
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 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 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<T>&, template <typename T>);
|
||||
|
||||
/// \brief Returns true if the viewed node is an array with the same contents as the RHS vector.
|
||||
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<T>&, template <typename T>);
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Subviews
|
||||
/// @{
|
||||
|
||||
/// \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.
|
||||
[[nodiscard]]
|
||||
node_view operator[] (std::string_view key) const noexcept
|
||||
{
|
||||
if (auto tbl = this->as_table())
|
||||
return node_view{ tbl->get(key) };
|
||||
return node_view{ nullptr };
|
||||
}
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Returns a view of the selected subnode.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \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.
|
||||
[[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
|
||||
{
|
||||
if (auto arr = this->as_array())
|
||||
return node_view{ arr->get(index) };
|
||||
return node_view{ nullptr };
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
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>
|
||||
inline std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& os, const node_view<T>& nv)
|
||||
{
|
||||
if (nv.node_)
|
||||
{
|
||||
nv.node_->visit([&os](const auto& n)
|
||||
{
|
||||
os << n;
|
||||
});
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
#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);
|
||||
#if TOML_HAS_CHAR8
|
||||
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
|
||||
|
||||
#endif // !TOML_HEADER_ONLY
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_ARITHMETIC_WARNINGS
|
@ -1,159 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "toml_preprocessor.h"
|
||||
#if !TOML_PARSER
|
||||
#error This header cannot not be included when TOML_PARSER is disabled.
|
||||
#endif
|
||||
//# }}
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#if TOML_EXCEPTIONS
|
||||
#include <stdexcept>
|
||||
#endif
|
||||
TOML_ENABLE_WARNINGS;
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_INIT_WARNINGS;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex);
|
||||
|
||||
#if defined(DOXYGEN) || !TOML_EXCEPTIONS
|
||||
|
||||
/// \brief An error generated when parsing fails.
|
||||
///
|
||||
/// \remarks This class inherits from std::runtime_error when exceptions are enabled.
|
||||
/// The public interface is the same regardless of exception mode.
|
||||
class parse_error final
|
||||
{
|
||||
private:
|
||||
std::string description_;
|
||||
source_region source_;
|
||||
|
||||
public:
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(std::string&& desc, source_region&& src) noexcept
|
||||
: description_{ std::move(desc) },
|
||||
source_{ std::move(src) }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(std::string&& desc, const source_region& src) noexcept
|
||||
: parse_error{ std::move(desc), source_region{ src } }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(std::string&& desc, const source_position& position, const source_path_ptr& path = {}) noexcept
|
||||
: parse_error{ std::move(desc), source_region{ position, position, path } }
|
||||
{}
|
||||
|
||||
|
||||
/// \brief Returns a textual description of the error.
|
||||
/// \remark The backing string is guaranteed to be null-terminated.
|
||||
[[nodiscard]]
|
||||
std::string_view description() const noexcept
|
||||
{
|
||||
return description_;
|
||||
}
|
||||
|
||||
/// \brief Returns the region of the source document responsible for the error.
|
||||
[[nodiscard]]
|
||||
const source_region& source() const noexcept
|
||||
{
|
||||
return source_;
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class parse_error final
|
||||
: public std::runtime_error
|
||||
{
|
||||
private:
|
||||
source_region source_;
|
||||
|
||||
public:
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
TOML_ATTR(nonnull)
|
||||
parse_error(const char* desc, source_region&& src) noexcept
|
||||
: std::runtime_error{ desc },
|
||||
source_{ std::move(src) }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
TOML_ATTR(nonnull)
|
||||
parse_error(const char* desc, const source_region& src) noexcept
|
||||
: parse_error{ desc, source_region{ src } }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
TOML_ATTR(nonnull)
|
||||
parse_error(const char* desc, const source_position& position, const source_path_ptr& path = {}) noexcept
|
||||
: parse_error{ desc, source_region{ position, position, path } }
|
||||
{}
|
||||
|
||||
[[nodiscard]]
|
||||
std::string_view description() const noexcept
|
||||
{
|
||||
return std::string_view{ what() };
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
const source_region& source() const noexcept
|
||||
{
|
||||
return source_;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
|
||||
/// \brief Prints a parse_error to a stream.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// try
|
||||
/// {
|
||||
/// auto tbl = toml::parse("enabled = trUe"sv);
|
||||
/// }
|
||||
/// catch (const toml::parse_error & err)
|
||||
/// {
|
||||
/// std::cerr << "Parsing failed:\n"sv << err << "\n";
|
||||
/// }
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// Parsing failed:
|
||||
/// Encountered unexpected character while parsing boolean; expected 'true', saw 'trU'
|
||||
/// (error occurred at line 1, column 13)
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Char The output stream's underlying character type. Must be 1 byte in size.
|
||||
/// \param lhs The stream.
|
||||
/// \param rhs The parse_error.
|
||||
///
|
||||
/// \returns The input stream.
|
||||
template <typename Char>
|
||||
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;
|
||||
lhs << rhs.source();
|
||||
lhs << ")"sv;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
#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_DISABLE_INIT_WARNINGS
|
@ -1,348 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "toml_preprocessor.h"
|
||||
#if !TOML_PARSER
|
||||
#error This header cannot not be included when TOML_PARSER is disabled.
|
||||
#endif
|
||||
//# }}
|
||||
#include "toml_table.h"
|
||||
#include "toml_parse_error.h"
|
||||
|
||||
#if defined(DOXYGEN) || !TOML_EXCEPTIONS
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_ABI_NAMESPACE_START(noex);
|
||||
|
||||
/// \brief The result of a parsing operation.
|
||||
///
|
||||
/// \detail A parse_result is effectively a discriminated union containing either a toml::table
|
||||
/// or a toml::parse_error. Most member functions assume a particular one of these two states,
|
||||
/// and calling them when in the wrong state will cause errors (e.g. attempting to access the
|
||||
/// error object when parsing was successful). \cpp
|
||||
/// parse_result result = toml::parse_file("config.toml");
|
||||
/// if (result)
|
||||
/// do_stuff_with_a_table(result); //implicitly converts to table&
|
||||
/// else
|
||||
/// std::cerr << "Parse failed:\n"sv << result.error() << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// example output:
|
||||
///
|
||||
/// Parse failed:
|
||||
/// Encountered unexpected character while parsing boolean; expected 'true', saw 'trU'
|
||||
/// (error occurred at line 1, column 13 of 'config.toml')
|
||||
/// \eout
|
||||
///
|
||||
/// Getting node_views (`operator[]`) and using the iterator accessor functions (`begin(), end()` etc.) are
|
||||
/// unconditionally safe; when parsing fails these just return 'empty' values. A ranged-for loop on a failed
|
||||
/// parse_result is also safe since `begin()` and `end()` return the same iterator and will not lead to any
|
||||
/// dereferences and iterations.
|
||||
///
|
||||
/// \availability <strong>This type only exists when exceptions are disabled.</strong>
|
||||
/// Otherwise parse_result is just an alias for toml::table: \cpp
|
||||
/// #if TOML_EXCEPTIONS
|
||||
/// using parse_result = table;
|
||||
/// #else
|
||||
/// class parse_result final { // ...
|
||||
/// #endif
|
||||
/// \ecpp
|
||||
class parse_result
|
||||
{
|
||||
private:
|
||||
struct storage_t
|
||||
{
|
||||
static constexpr size_t size_
|
||||
= (sizeof(toml::table) < sizeof(parse_error) ? sizeof(parse_error) : sizeof(toml::table));
|
||||
static constexpr size_t align_ =
|
||||
(alignof(toml::table) < alignof(parse_error) ? alignof(parse_error) : alignof(toml::table));
|
||||
|
||||
alignas(align_) unsigned char bytes[size_];
|
||||
};
|
||||
|
||||
mutable storage_t storage_;
|
||||
bool err_;
|
||||
|
||||
template <typename Type>
|
||||
[[nodiscard]]
|
||||
TOML_ALWAYS_INLINE
|
||||
static Type* get_as(storage_t& s) noexcept
|
||||
{
|
||||
return TOML_LAUNDER(reinterpret_cast<Type*>(s.bytes));
|
||||
}
|
||||
|
||||
void destroy() noexcept
|
||||
{
|
||||
if (err_)
|
||||
get_as<parse_error>(storage_)->~parse_error();
|
||||
else
|
||||
get_as<toml::table>(storage_)->~table();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// \brief A BidirectionalIterator for iterating over key-value pairs in a wrapped toml::table.
|
||||
using iterator = table_iterator;
|
||||
|
||||
/// \brief A BidirectionalIterator for iterating over const key-value pairs in a wrapped toml::table.
|
||||
using const_iterator = const_table_iterator;
|
||||
|
||||
/// \brief Returns true if parsing succeeeded.
|
||||
[[nodiscard]] bool succeeded() const noexcept { return !err_; }
|
||||
/// \brief Returns true if parsing failed.
|
||||
[[nodiscard]] bool failed() const noexcept { return err_; }
|
||||
/// \brief Returns true if parsing succeeded.
|
||||
[[nodiscard]] explicit operator bool() const noexcept { return !err_; }
|
||||
|
||||
/// \brief Returns the internal toml::table.
|
||||
[[nodiscard]]
|
||||
toml::table& table() & noexcept
|
||||
{
|
||||
TOML_ASSERT(!err_);
|
||||
return *get_as<toml::table>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table (rvalue overload).
|
||||
[[nodiscard]]
|
||||
toml::table&& table() && noexcept
|
||||
{
|
||||
TOML_ASSERT(!err_);
|
||||
return static_cast<toml::table&&>(*get_as<toml::table>(storage_));
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table (const lvalue overload).
|
||||
[[nodiscard]]
|
||||
const toml::table& table() const& noexcept
|
||||
{
|
||||
TOML_ASSERT(!err_);
|
||||
return *get_as<const toml::table>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error.
|
||||
[[nodiscard]]
|
||||
parse_error& error() & noexcept
|
||||
{
|
||||
TOML_ASSERT(err_);
|
||||
return *get_as<parse_error>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error (rvalue overload).
|
||||
[[nodiscard]]
|
||||
parse_error&& error() && noexcept
|
||||
{
|
||||
TOML_ASSERT(err_);
|
||||
return static_cast<parse_error&&>(*get_as<parse_error>(storage_));
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error (const lvalue overload).
|
||||
[[nodiscard]]
|
||||
const parse_error& error() const& noexcept
|
||||
{
|
||||
TOML_ASSERT(err_);
|
||||
return *get_as<const parse_error>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table.
|
||||
[[nodiscard]] operator toml::table& () noexcept { return table(); }
|
||||
/// \brief Returns the internal toml::table (rvalue overload).
|
||||
[[nodiscard]] operator toml::table&& () noexcept { return std::move(table()); }
|
||||
/// \brief Returns the internal toml::table (const lvalue overload).
|
||||
[[nodiscard]] operator const toml::table& () const noexcept { return table(); }
|
||||
|
||||
/// \brief Returns the internal toml::parse_error.
|
||||
[[nodiscard]] explicit operator parse_error& () noexcept { return error(); }
|
||||
/// \brief Returns the internal toml::parse_error (rvalue overload).
|
||||
[[nodiscard]] explicit operator parse_error && () noexcept { return std::move(error()); }
|
||||
/// \brief Returns the internal toml::parse_error (const lvalue overload).
|
||||
[[nodiscard]] explicit operator const parse_error& () const noexcept { return error(); }
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_result() noexcept
|
||||
: err_{ true }
|
||||
{
|
||||
::new (static_cast<void*>(storage_.bytes)) parse_error{ std::string{}, source_region{} };
|
||||
}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit parse_result(toml::table&& tbl) noexcept
|
||||
: err_{ false }
|
||||
{
|
||||
::new (static_cast<void*>(storage_.bytes)) toml::table{ std::move(tbl) };
|
||||
}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit parse_result(parse_error&& err) noexcept
|
||||
: err_{ true }
|
||||
{
|
||||
::new (static_cast<void*>(storage_.bytes)) parse_error{ std::move(err) };
|
||||
}
|
||||
|
||||
/// \brief Move constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_result(parse_result&& res) noexcept
|
||||
: err_{ res.err_ }
|
||||
{
|
||||
if (err_)
|
||||
::new (static_cast<void*>(storage_.bytes)) parse_error{ std::move(res).error() };
|
||||
else
|
||||
::new (static_cast<void*>(storage_.bytes)) toml::table{ std::move(res).table() };
|
||||
}
|
||||
|
||||
/// \brief Move-assignment operator.
|
||||
parse_result& operator=(parse_result&& rhs) noexcept
|
||||
{
|
||||
if (err_ != rhs.err_)
|
||||
{
|
||||
destroy();
|
||||
err_ = rhs.err_;
|
||||
if (err_)
|
||||
::new (static_cast<void*>(storage_.bytes)) parse_error{ std::move(rhs).error() };
|
||||
else
|
||||
::new (static_cast<void*>(storage_.bytes)) toml::table{ std::move(rhs).table() };
|
||||
}
|
||||
else
|
||||
{
|
||||
if (err_)
|
||||
error() = std::move(rhs).error();
|
||||
else
|
||||
table() = std::move(rhs).table();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Destructor.
|
||||
~parse_result() noexcept
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
/// \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
|
||||
[[nodiscard]]
|
||||
node_view<node> operator[] (string_view key) noexcept
|
||||
{
|
||||
return 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
|
||||
[[nodiscard]]
|
||||
node_view<const node> operator[] (string_view key) const noexcept
|
||||
{
|
||||
return 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.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \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<node> operator[] (std::wstring_view key) noexcept
|
||||
{
|
||||
return err_ ? node_view<node>{} : table()[key];
|
||||
}
|
||||
|
||||
/// \brief Gets a node_view for the selected key-value pair in the wrapped table (const overload).
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \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[] (std::wstring_view key) const noexcept
|
||||
{
|
||||
return 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 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]]
|
||||
const_table_iterator begin() const noexcept
|
||||
{
|
||||
return 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 cbegin() const noexcept
|
||||
{
|
||||
return 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
|
||||
{
|
||||
return 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
|
||||
{
|
||||
return 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
|
||||
{
|
||||
return err_ ? const_table_iterator{} : table().cend();
|
||||
}
|
||||
|
||||
/// \brief Prints the held error or table object out to a text stream.
|
||||
template <typename Char>
|
||||
friend std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& os, const parse_result& result)
|
||||
{
|
||||
return result.err_ ? (os << result.error()) : (os << result.table());
|
||||
}
|
||||
};
|
||||
|
||||
TOML_ABI_NAMESPACE_END;
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
#endif // !TOML_EXCEPTIONS
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,353 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "toml_preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "toml_table.h"
|
||||
#include "toml_node_view.h"
|
||||
|
||||
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( 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++)
|
||||
{
|
||||
if (!pairs[i].value) // empty node_views
|
||||
continue;
|
||||
map.insert_or_assign(
|
||||
std::move(pairs[i].key),
|
||||
std::move(pairs[i].value)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#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; }
|
||||
TOML_MEMBER_ATTR(const) bool table::is_table() const noexcept { return true; }
|
||||
TOML_MEMBER_ATTR(const) bool table::is_array() const noexcept { return false; }
|
||||
TOML_MEMBER_ATTR(const) bool table::is_value() const noexcept { return false; }
|
||||
TOML_MEMBER_ATTR(const) const table* table::as_table() const noexcept { return this; }
|
||||
TOML_MEMBER_ATTR(const) table* table::as_table() noexcept { return this; }
|
||||
|
||||
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 { 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 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
|
||||
bool table::is_homogeneous(node_type ntype) const noexcept
|
||||
{
|
||||
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[] (std::string_view key) const noexcept
|
||||
{
|
||||
return node_view<const node>{ this->get(key) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::erase(iterator pos) noexcept
|
||||
{
|
||||
return { map.erase(pos.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::erase(const_iterator pos) noexcept
|
||||
{
|
||||
return { map.erase(pos.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::erase(const_iterator first, const_iterator last) noexcept
|
||||
{
|
||||
return { map.erase(first.raw_, last.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::erase(std::string_view key) noexcept
|
||||
{
|
||||
if (auto it = map.find(key); it != map.end())
|
||||
{
|
||||
map.erase(it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node* table::get(std::string_view key) noexcept
|
||||
{
|
||||
return do_get(map, key);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
const node* table::get(std::string_view key) const noexcept
|
||||
{
|
||||
return do_get(map, key);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::find(std::string_view key) noexcept
|
||||
{
|
||||
return { map.find(key) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::const_iterator table::find(std::string_view key) const noexcept
|
||||
{
|
||||
return { map.find(key) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::contains(std::string_view key) const noexcept
|
||||
{
|
||||
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_EXTERNAL_LINKAGE
|
||||
bool operator == (const table& lhs, const table& rhs) noexcept
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.map.size() != rhs.map.size())
|
||||
return false;
|
||||
|
||||
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;
|
||||
|
||||
const auto lhs_type = l->second->type();
|
||||
const node& rhs_ = *r->second;
|
||||
const auto rhs_type = rhs_.type();
|
||||
if (lhs_type != rhs_type)
|
||||
return false;
|
||||
|
||||
const bool equal = l->second->visit([&](const auto& lhs_) noexcept
|
||||
{
|
||||
return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_);
|
||||
});
|
||||
if (!equal)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool operator != (const table& lhs, const table& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
@ -1,974 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "toml_preprocessor.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
|
||||
/// \cond
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_ascii_whitespace(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint == U'\t' || codepoint == U' ';
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
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")
|
||||
|
||||
return codepoint == U'\u00A0' // no-break space
|
||||
|| codepoint == U'\u1680' // ogham space mark
|
||||
|| (codepoint >= U'\u2000' && codepoint <= U'\u200A') // em quad -> hair space
|
||||
|| codepoint == U'\u202F' // narrow no-break space
|
||||
|| codepoint == U'\u205F' // medium mathematical space
|
||||
|| codepoint == U'\u3000' // ideographic space
|
||||
;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_whitespace(char32_t codepoint) noexcept
|
||||
{
|
||||
return is_ascii_whitespace(codepoint) || is_non_ascii_whitespace(codepoint);
|
||||
}
|
||||
|
||||
template <bool IncludeCarriageReturn = true>
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_ascii_line_break(char32_t codepoint) noexcept
|
||||
{
|
||||
constexpr auto low_range_end = IncludeCarriageReturn ? U'\r' : U'\f';
|
||||
return (codepoint >= U'\n' && codepoint <= low_range_end);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
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")
|
||||
|
||||
return codepoint == U'\u0085' // next line
|
||||
|| codepoint == U'\u2028' // line separator
|
||||
|| codepoint == U'\u2029' // paragraph separator
|
||||
;
|
||||
}
|
||||
|
||||
template <bool IncludeCarriageReturn = true>
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_line_break(char32_t codepoint) noexcept
|
||||
{
|
||||
return is_ascii_line_break<IncludeCarriageReturn>(codepoint) || is_non_ascii_line_break(codepoint);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_string_delimiter(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint == U'"' || codepoint == U'\'';
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_ascii_letter(char32_t codepoint) noexcept
|
||||
{
|
||||
return (codepoint >= U'a' && codepoint <= U'z')
|
||||
|| (codepoint >= U'A' && codepoint <= U'Z');
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_binary_digit(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint == U'0' || codepoint == U'1';
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_octal_digit(char32_t codepoint) noexcept
|
||||
{
|
||||
return (codepoint >= U'0' && codepoint <= U'7');
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
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)
|
||||
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>)
|
||||
return codepoint >= 0x41u // >= 'A'
|
||||
? 10u + (codepoint | 0x20u) - 0x61u // - 'a'
|
||||
: codepoint - 0x30u // - '0'
|
||||
;
|
||||
else
|
||||
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
|
||||
{
|
||||
return is_ascii_letter(codepoint)
|
||||
|| is_decimal_digit(codepoint)
|
||||
|| codepoint == U'-'
|
||||
|| codepoint == U'_'
|
||||
#if TOML_LANG_UNRELEASED // toml/issues/644 ('+' in bare keys) & toml/issues/687 (unicode bare keys)
|
||||
|| codepoint == U'+'
|
||||
|| is_non_ascii_letter(codepoint)
|
||||
|| is_non_ascii_number(codepoint)
|
||||
|| is_combining_mark(codepoint)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_value_terminator(char32_t codepoint) noexcept
|
||||
{
|
||||
return is_ascii_line_break(codepoint)
|
||||
|| is_ascii_whitespace(codepoint)
|
||||
|| codepoint == U']'
|
||||
|| codepoint == U'}'
|
||||
|| codepoint == U','
|
||||
|| codepoint == U'#'
|
||||
|| is_non_ascii_line_break(codepoint)
|
||||
|| is_non_ascii_whitespace(codepoint)
|
||||
;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_control_character(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint <= U'\u001F' || codepoint == U'\u007F';
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_nontab_control_character(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint <= U'\u0008'
|
||||
|| (codepoint >= U'\u000A' && codepoint <= U'\u001F')
|
||||
|| codepoint == U'\u007F';
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_unicode_surrogate(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint >= 0xD800u && codepoint <= 0xDFFF;
|
||||
}
|
||||
|
||||
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{};
|
||||
|
||||
static constexpr uint8_t state_table[]
|
||||
{
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
|
||||
|
||||
0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
|
||||
12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
|
||||
12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
|
||||
12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
|
||||
12,36,12,12,12,12,12,12,12,12,12,12
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool error() const noexcept
|
||||
{
|
||||
return state == uint_least32_t{ 12u };
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool has_code_point() const noexcept
|
||||
{
|
||||
return state == uint_least32_t{};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool needs_more_input() const noexcept
|
||||
{
|
||||
return state > uint_least32_t{} && state != uint_least32_t{ 12u };
|
||||
}
|
||||
|
||||
constexpr void operator () (uint8_t byte) noexcept
|
||||
{
|
||||
TOML_ASSERT(!error());
|
||||
|
||||
const auto type = state_table[byte];
|
||||
|
||||
codepoint = static_cast<char32_t>(
|
||||
has_code_point()
|
||||
? (uint_least32_t{ 255u } >> type) & byte
|
||||
: (byte & uint_least32_t{ 63u }) | (static_cast<uint_least32_t>(codepoint) << 6)
|
||||
);
|
||||
|
||||
state = state_table[state + uint_least32_t{ 256u } + type];
|
||||
}
|
||||
};
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
/// \endcond
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_SWITCH_WARNINGS
|
@ -1,383 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "toml_preprocessor.h"
|
||||
#if !TOML_PARSER
|
||||
#error This header cannot not be included when TOML_PARSER is disabled.
|
||||
#endif
|
||||
//# }}
|
||||
#include "toml_utf8.h"
|
||||
#include "toml_parse_error.h"
|
||||
|
||||
/// \cond
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
template <typename T>
|
||||
class utf8_byte_stream;
|
||||
|
||||
inline constexpr auto utf8_byte_order_mark = "\xEF\xBB\xBF"sv;
|
||||
|
||||
template <typename Char>
|
||||
class TOML_API utf8_byte_stream<std::basic_string_view<Char>> final
|
||||
{
|
||||
static_assert(sizeof(Char) == 1_sz);
|
||||
|
||||
private:
|
||||
std::basic_string_view<Char> source;
|
||||
size_t position = {};
|
||||
|
||||
public:
|
||||
explicit constexpr utf8_byte_stream(std::basic_string_view<Char> sv) noexcept
|
||||
: source{ sv }
|
||||
{
|
||||
// trim trailing nulls
|
||||
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'
|
||||
{
|
||||
actual_len = i + 1_sz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (initial_len != actual_len)
|
||||
source = source.substr(0_sz, actual_len);
|
||||
|
||||
// skip bom
|
||||
if (actual_len >= 3_sz && memcmp(utf8_byte_order_mark.data(), source.data(), 3_sz) == 0)
|
||||
position += 3_sz;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ALWAYS_INLINE
|
||||
constexpr bool eof() const noexcept
|
||||
{
|
||||
return position >= source.length();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ALWAYS_INLINE
|
||||
constexpr bool peek_eof() const noexcept
|
||||
{
|
||||
return eof();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ALWAYS_INLINE
|
||||
constexpr bool error() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr unsigned int operator() () noexcept
|
||||
{
|
||||
if (position >= source.length())
|
||||
return 0xFFFFFFFFu;
|
||||
return static_cast<unsigned int>(static_cast<uint8_t>(source[position++]));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
class TOML_API utf8_byte_stream<std::basic_istream<Char>> final
|
||||
{
|
||||
static_assert(sizeof(Char) == 1_sz);
|
||||
|
||||
private:
|
||||
std::basic_istream<Char>* source;
|
||||
|
||||
public:
|
||||
explicit utf8_byte_stream(std::basic_istream<Char>& stream)
|
||||
: source{ &stream }
|
||||
{
|
||||
if (!source->good()) // eof, fail, bad
|
||||
return;
|
||||
|
||||
const auto initial_pos = source->tellg();
|
||||
Char bom[3];
|
||||
source->read(bom, 3);
|
||||
if (source->bad() || (source->gcount() == 3 && memcmp(utf8_byte_order_mark.data(), bom, 3_sz) == 0))
|
||||
return;
|
||||
|
||||
source->clear();
|
||||
source->seekg(initial_pos, std::basic_istream<Char>::beg);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TOML_ALWAYS_INLINE
|
||||
bool eof() const noexcept
|
||||
{
|
||||
return source->eof();
|
||||
}
|
||||
|
||||
[[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
|
||||
bool error() const noexcept
|
||||
{
|
||||
return !(*source);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
unsigned int operator() ()
|
||||
{
|
||||
auto val = source->get();
|
||||
if (val == std::basic_istream<Char>::traits_type::eof())
|
||||
return 0xFFFFFFFFu;
|
||||
return static_cast<unsigned int>(val);
|
||||
}
|
||||
};
|
||||
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_LARGE_FILES, lf, sf);
|
||||
|
||||
struct utf8_codepoint final
|
||||
{
|
||||
char32_t value;
|
||||
char bytes[4];
|
||||
source_position position;
|
||||
|
||||
[[nodiscard]]
|
||||
std::string_view as_view() const noexcept
|
||||
{
|
||||
return bytes[3]
|
||||
? std::string_view{ bytes, 4_sz }
|
||||
: std::string_view{ bytes };
|
||||
}
|
||||
|
||||
[[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
|
||||
#else
|
||||
#define TOML_ERROR_CHECK if (err) return nullptr
|
||||
#define TOML_ERROR err.emplace
|
||||
#endif
|
||||
|
||||
struct TOML_ABSTRACT_BASE utf8_reader_interface
|
||||
{
|
||||
[[nodiscard]]
|
||||
virtual const source_path_ptr& source_path() const noexcept = 0;
|
||||
|
||||
[[nodiscard]]
|
||||
virtual const utf8_codepoint* read_next() = 0;
|
||||
|
||||
[[nodiscard]]
|
||||
virtual bool peek_eof() const = 0;
|
||||
|
||||
#if !TOML_EXCEPTIONS
|
||||
|
||||
[[nodiscard]]
|
||||
virtual optional<parse_error>&& error() noexcept = 0;
|
||||
|
||||
#endif
|
||||
|
||||
virtual ~utf8_reader_interface() noexcept = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TOML_EMPTY_BASES TOML_API utf8_reader final
|
||||
: public utf8_reader_interface
|
||||
{
|
||||
private:
|
||||
utf8_byte_stream<T> stream;
|
||||
utf8_decoder decoder;
|
||||
utf8_codepoint codepoints[2];
|
||||
size_t cp_idx = 1;
|
||||
uint8_t current_byte_count{};
|
||||
source_path_ptr source_path_;
|
||||
#if !TOML_EXCEPTIONS
|
||||
optional<parse_error> err;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
template <typename U, typename String = std::string_view>
|
||||
explicit utf8_reader(U && source, String&& source_path = {})
|
||||
noexcept(std::is_nothrow_constructible_v<utf8_byte_stream<T>, U&&>)
|
||||
: stream{ static_cast<U&&>(source) }
|
||||
{
|
||||
std::memset(codepoints, 0, sizeof(codepoints));
|
||||
codepoints[0].position = { 1, 1 };
|
||||
codepoints[1].position = { 1, 1 };
|
||||
|
||||
if (!source_path.empty())
|
||||
source_path_ = std::make_shared<const std::string>(static_cast<String&&>(source_path));
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
const source_path_ptr& source_path() const noexcept override
|
||||
{
|
||||
return source_path_;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
const utf8_codepoint* read_next() override
|
||||
{
|
||||
TOML_ERROR_CHECK;
|
||||
|
||||
auto& prev = codepoints[(cp_idx - 1_sz) % 2_sz];
|
||||
|
||||
if (stream.eof())
|
||||
return nullptr;
|
||||
else if (stream.error())
|
||||
TOML_ERROR("An error occurred while reading from the underlying stream", prev.position, source_path_ );
|
||||
else if (decoder.error())
|
||||
TOML_ERROR( "Encountered invalid utf-8 sequence", prev.position, source_path_ );
|
||||
|
||||
TOML_ERROR_CHECK;
|
||||
|
||||
while (true)
|
||||
{
|
||||
uint8_t next_byte;
|
||||
{
|
||||
unsigned int next_byte_raw{ 0xFFFFFFFFu };
|
||||
if constexpr (noexcept(stream()) || !TOML_EXCEPTIONS)
|
||||
{
|
||||
next_byte_raw = stream();
|
||||
}
|
||||
#if TOML_EXCEPTIONS
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
next_byte_raw = stream();
|
||||
}
|
||||
catch (const std::exception& exc)
|
||||
{
|
||||
throw parse_error{ exc.what(), prev.position, source_path_ };
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
throw parse_error{ "An unspecified error occurred", prev.position, source_path_ };
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (next_byte_raw >= 256u)
|
||||
{
|
||||
if (stream.eof())
|
||||
{
|
||||
if (decoder.needs_more_input())
|
||||
TOML_ERROR("Encountered EOF during incomplete utf-8 code point sequence",
|
||||
prev.position, source_path_);
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
TOML_ERROR("An error occurred while reading from the underlying stream",
|
||||
prev.position, source_path_);
|
||||
}
|
||||
|
||||
TOML_ERROR_CHECK;
|
||||
next_byte = static_cast<uint8_t>(next_byte_raw);
|
||||
}
|
||||
|
||||
decoder(next_byte);
|
||||
if (decoder.error())
|
||||
TOML_ERROR( "Encountered invalid utf-8 sequence", prev.position, source_path_ );
|
||||
|
||||
TOML_ERROR_CHECK;
|
||||
|
||||
auto& current = codepoints[cp_idx % 2_sz];
|
||||
current.bytes[current_byte_count++] = static_cast<char>(next_byte);
|
||||
if (decoder.has_code_point())
|
||||
{
|
||||
//store codepoint
|
||||
current.value = decoder.codepoint;
|
||||
|
||||
//reset prev (will be the next 'current')
|
||||
std::memset(prev.bytes, 0, sizeof(prev.bytes));
|
||||
current_byte_count = {};
|
||||
if (is_line_break<false>(current.value))
|
||||
prev.position = { static_cast<source_index>(current.position.line + 1), 1 };
|
||||
else
|
||||
prev.position = { current.position.line, static_cast<source_index>(current.position.column + 1) };
|
||||
cp_idx++;
|
||||
return ¤t;
|
||||
}
|
||||
}
|
||||
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
bool peek_eof() const override
|
||||
{
|
||||
return stream.peek_eof();
|
||||
}
|
||||
|
||||
#if !TOML_EXCEPTIONS
|
||||
|
||||
[[nodiscard]]
|
||||
optional<parse_error>&& error() noexcept override
|
||||
{
|
||||
return std::move(err);
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
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_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>>;
|
||||
|
||||
class TOML_EMPTY_BASES TOML_API utf8_buffered_reader final
|
||||
: public utf8_reader_interface
|
||||
{
|
||||
public:
|
||||
static constexpr size_t max_history_length = 72;
|
||||
|
||||
private:
|
||||
static constexpr size_t history_buffer_size = max_history_length - 1; //'head' is stored in the reader
|
||||
utf8_reader_interface& reader;
|
||||
struct
|
||||
{
|
||||
|
||||
utf8_codepoint buffer[history_buffer_size];
|
||||
size_t count, first;
|
||||
}
|
||||
history = {};
|
||||
const utf8_codepoint* head = {};
|
||||
size_t negative_offset = {};
|
||||
|
||||
public:
|
||||
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
|
||||
optional<parse_error>&& error() noexcept override;
|
||||
#endif
|
||||
};
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
/// \endcond
|
@ -1,972 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "toml_node.h"
|
||||
#include "toml_print_to_stream.h"
|
||||
|
||||
#ifndef DOXYGEN
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
#define TOML_SA_VALUE_MESSAGE_WSTRING TOML_SA_LIST_SEP "std::wstring"
|
||||
#else
|
||||
#define TOML_SA_VALUE_MESSAGE_WSTRING
|
||||
#endif
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
#define TOML_SA_VALUE_MESSAGE_U8STRING_VIEW TOML_SA_LIST_SEP "std::u8string_view"
|
||||
#define TOML_SA_VALUE_MESSAGE_CONST_CHAR8 TOML_SA_LIST_SEP "const char8_t*"
|
||||
#else
|
||||
#define TOML_SA_VALUE_MESSAGE_U8STRING_VIEW
|
||||
#define TOML_SA_VALUE_MESSAGE_CONST_CHAR8
|
||||
#endif
|
||||
|
||||
#define TOML_SA_VALUE_EXACT_FUNC_MESSAGE(type_arg) \
|
||||
"The " type_arg " must be one of:" \
|
||||
TOML_SA_LIST_NEW "A native TOML value type" \
|
||||
TOML_SA_NATIVE_VALUE_TYPE_LIST \
|
||||
\
|
||||
TOML_SA_LIST_NXT "A non-view type capable of losslessly representing a native TOML value type" \
|
||||
TOML_SA_LIST_BEG "std::string" \
|
||||
TOML_SA_VALUE_MESSAGE_WSTRING \
|
||||
TOML_SA_LIST_SEP "any signed integer type >= 64 bits" \
|
||||
TOML_SA_LIST_SEP "any floating-point type >= 64 bits" \
|
||||
TOML_SA_LIST_END \
|
||||
\
|
||||
TOML_SA_LIST_NXT "An immutable view type not requiring additional temporary storage" \
|
||||
TOML_SA_LIST_BEG "std::string_view" \
|
||||
TOML_SA_VALUE_MESSAGE_U8STRING_VIEW \
|
||||
TOML_SA_LIST_SEP "const char*" \
|
||||
TOML_SA_VALUE_MESSAGE_CONST_CHAR8 \
|
||||
TOML_SA_LIST_END
|
||||
|
||||
#define TOML_SA_VALUE_FUNC_MESSAGE(type_arg) \
|
||||
"The " type_arg " must be one of:" \
|
||||
TOML_SA_LIST_NEW "A native TOML value type" \
|
||||
TOML_SA_NATIVE_VALUE_TYPE_LIST \
|
||||
\
|
||||
TOML_SA_LIST_NXT "A non-view type capable of losslessly representing a native TOML value type" \
|
||||
TOML_SA_LIST_BEG "std::string" \
|
||||
TOML_SA_VALUE_MESSAGE_WSTRING \
|
||||
TOML_SA_LIST_SEP "any signed integer type >= 64 bits" \
|
||||
TOML_SA_LIST_SEP "any floating-point type >= 64 bits" \
|
||||
TOML_SA_LIST_END \
|
||||
\
|
||||
TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type" \
|
||||
TOML_SA_LIST_BEG "any other integer type" \
|
||||
TOML_SA_LIST_SEP "any floating-point type >= 32 bits" \
|
||||
TOML_SA_LIST_END \
|
||||
\
|
||||
TOML_SA_LIST_NXT "An immutable view type not requiring additional temporary storage" \
|
||||
TOML_SA_LIST_BEG "std::string_view" \
|
||||
TOML_SA_VALUE_MESSAGE_U8STRING_VIEW \
|
||||
TOML_SA_LIST_SEP "const char*" \
|
||||
TOML_SA_VALUE_MESSAGE_CONST_CHAR8 \
|
||||
TOML_SA_LIST_END
|
||||
#endif // !DOXYGEN
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_ARITHMETIC_WARNINGS;
|
||||
|
||||
/// \cond
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
template <typename T, typename...>
|
||||
struct native_value_maker
|
||||
{
|
||||
template <typename... Args>
|
||||
[[nodiscard]]
|
||||
static T make(Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args&&...>)
|
||||
{
|
||||
return T(static_cast<Args&&>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct native_value_maker<T, T>
|
||||
{
|
||||
template <typename U>
|
||||
[[nodiscard]]
|
||||
TOML_ALWAYS_INLINE
|
||||
static U&& make(U&& val) noexcept
|
||||
{
|
||||
return static_cast<U&&>(val);
|
||||
}
|
||||
};
|
||||
|
||||
#if TOML_HAS_CHAR8 || TOML_WINDOWS_COMPAT
|
||||
|
||||
struct string_maker
|
||||
{
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
static std::string make(T&& arg) noexcept
|
||||
{
|
||||
#if TOML_HAS_CHAR8
|
||||
if constexpr (is_one_of<std::decay_t<T>, char8_t*, const char8_t*>)
|
||||
return std::string(reinterpret_cast<const char*>(static_cast<const char8_t*>(arg)));
|
||||
else if constexpr (is_one_of<remove_cvref_t<T>, std::u8string, std::u8string_view>)
|
||||
return std::string(reinterpret_cast<const char*>(static_cast<const char8_t*>(arg.data())), arg.length());
|
||||
#endif // TOML_HAS_CHAR8
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
if constexpr (is_wide_string<T>)
|
||||
return narrow(static_cast<T&&>(arg));
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
}
|
||||
};
|
||||
#if TOML_HAS_CHAR8
|
||||
template <> struct native_value_maker<std::string, char8_t*> : string_maker {};
|
||||
template <> struct native_value_maker<std::string, const char8_t*> : string_maker {};
|
||||
template <> struct native_value_maker<std::string, std::u8string> : string_maker {};
|
||||
template <> struct native_value_maker<std::string, std::u8string_view> : string_maker {};
|
||||
#endif // TOML_HAS_CHAR8
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
template <> struct native_value_maker<std::string, wchar_t*> : string_maker {};
|
||||
template <> struct native_value_maker<std::string, const wchar_t*> : string_maker {};
|
||||
template <> struct native_value_maker<std::string, std::wstring> : string_maker {};
|
||||
template <> struct native_value_maker<std::string, std::wstring_view> : string_maker {};
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
#endif // TOML_HAS_CHAR8 || TOML_WINDOWS_COMPAT
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(const)
|
||||
inline optional<T> node_integer_cast(int64_t val) noexcept
|
||||
{
|
||||
static_assert(node_type_of<T> == node_type::integer);
|
||||
static_assert(!is_cvref<T>);
|
||||
|
||||
using traits = value_traits<T>;
|
||||
if constexpr (!traits::is_signed)
|
||||
{
|
||||
if constexpr ((sizeof(T) * CHAR_BIT) < 63) // 63 bits == int64_max
|
||||
{
|
||||
using common_t = decltype(int64_t{} + T{});
|
||||
if (val < int64_t{} || static_cast<common_t>(val) > static_cast<common_t>(traits::max))
|
||||
return {};
|
||||
}
|
||||
else
|
||||
{
|
||||
if (val < int64_t{})
|
||||
return {};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (val < traits::min || val > traits::max)
|
||||
return {};
|
||||
}
|
||||
return { static_cast<T>(val) };
|
||||
}
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
/// \endcond
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A TOML value.
|
||||
///
|
||||
/// \tparam ValueType The value's native TOML data type. Can be one of:
|
||||
/// - std::string
|
||||
/// - toml::date
|
||||
/// - toml::time
|
||||
/// - toml::date_time
|
||||
/// - int64_t
|
||||
/// - double
|
||||
/// - bool
|
||||
template <typename ValueType>
|
||||
class TOML_API value final : public node
|
||||
{
|
||||
static_assert(
|
||||
impl::is_native<ValueType> && !impl::is_cvref<ValueType>,
|
||||
"A toml::value<> must model one of the native TOML value types:"
|
||||
TOML_SA_NATIVE_VALUE_TYPE_LIST
|
||||
);
|
||||
|
||||
private:
|
||||
friend class TOML_PARSER_TYPENAME;
|
||||
|
||||
/// \cond
|
||||
|
||||
template <typename T, typename U>
|
||||
[[nodiscard]]
|
||||
TOML_ALWAYS_INLINE
|
||||
TOML_ATTR(const)
|
||||
static auto as_value([[maybe_unused]] U* ptr) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<value_type, T>)
|
||||
return ptr;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ValueType val_;
|
||||
value_flags flags_ = value_flags::none;
|
||||
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
void lh_ctor() noexcept
|
||||
{
|
||||
TOML_VALUE_CREATED;
|
||||
}
|
||||
|
||||
void lh_dtor() noexcept
|
||||
{
|
||||
TOML_VALUE_DESTROYED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \endcond
|
||||
|
||||
public:
|
||||
|
||||
/// \brief The value's underlying data type.
|
||||
using value_type = ValueType;
|
||||
|
||||
/// \brief A type alias for 'value arguments'.
|
||||
/// \details This differs according to the value's type argument:
|
||||
/// - ints, floats, booleans: `value_type`
|
||||
/// - strings: `string_view`
|
||||
/// - everything else: `const value_type&`
|
||||
using value_arg = std::conditional_t<
|
||||
std::is_same_v<value_type, std::string>,
|
||||
std::string_view,
|
||||
std::conditional_t<impl::is_one_of<value_type, double, int64_t, bool>, value_type, const value_type&>
|
||||
>;
|
||||
|
||||
/// \brief Constructs a toml value.
|
||||
///
|
||||
/// \tparam Args Constructor argument types.
|
||||
/// \param args Arguments to forward to the internal value's constructor.
|
||||
template <typename... Args>
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit value(Args&&... args)
|
||||
noexcept(noexcept(value_type(
|
||||
impl::native_value_maker<value_type, std::decay_t<Args>...>::make(static_cast<Args&&>(args)...)
|
||||
)))
|
||||
: val_(impl::native_value_maker<value_type, std::decay_t<Args>...>::make(static_cast<Args&&>(args)...))
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
lh_ctor();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// \brief Copy constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
value(const value& other) noexcept
|
||||
: node( other ),
|
||||
val_{ other.val_ },
|
||||
flags_{ other.flags_ }
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
lh_ctor();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// \brief Move constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
value(value&& other) noexcept
|
||||
: node( std::move(other) ),
|
||||
val_{ std::move(other.val_) },
|
||||
flags_{ other.flags_ }
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
lh_ctor();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// \brief Copy-assignment operator.
|
||||
value& operator= (const value& rhs) noexcept
|
||||
{
|
||||
node::operator=(rhs);
|
||||
val_ = rhs.val_;
|
||||
flags_ = rhs.flags_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Move-assignment operator.
|
||||
value& operator= (value&& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
val_ = std::move(rhs.val_);
|
||||
flags_ = rhs.flags_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
~value() noexcept override
|
||||
{
|
||||
lh_dtor();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \name Type checks
|
||||
/// @{
|
||||
|
||||
/// \brief Returns the value's node type identifier.
|
||||
///
|
||||
/// \returns One of:
|
||||
/// - node_type::string
|
||||
/// - node_type::integer
|
||||
/// - node_type::floating_point
|
||||
/// - node_type::boolean
|
||||
/// - node_type::date
|
||||
/// - node_type::time
|
||||
/// - node_type::date_time
|
||||
[[nodiscard]] node_type type() const noexcept override { return impl::node_type_of<value_type>; }
|
||||
|
||||
[[nodiscard]] bool is_table() const noexcept override { return false; }
|
||||
[[nodiscard]] bool is_array() const noexcept override { return false; }
|
||||
[[nodiscard]] bool is_value() const noexcept override { return true; }
|
||||
|
||||
[[nodiscard]] bool is_string() const noexcept override { return std::is_same_v<value_type, std::string>; }
|
||||
[[nodiscard]] bool is_integer() const noexcept override { return std::is_same_v<value_type, int64_t>; }
|
||||
[[nodiscard]] bool is_floating_point() const noexcept override { return std::is_same_v<value_type, double>; }
|
||||
[[nodiscard]] bool is_number() const noexcept override { return impl::is_one_of<value_type, int64_t, double>; }
|
||||
[[nodiscard]] bool is_boolean() const noexcept override { return std::is_same_v<value_type, bool>; }
|
||||
[[nodiscard]] bool is_date() const noexcept override { return std::is_same_v<value_type, date>; }
|
||||
[[nodiscard]] bool is_time() const noexcept override { return std::is_same_v<value_type, time>; }
|
||||
[[nodiscard]] bool is_date_time() const noexcept override { return std::is_same_v<value_type, date_time>; }
|
||||
|
||||
[[nodiscard]]
|
||||
bool is_homogeneous(node_type ntype) const noexcept override
|
||||
{
|
||||
return ntype == node_type::none || ntype == impl::node_type_of<value_type>;
|
||||
}
|
||||
[[nodiscard]]
|
||||
bool is_homogeneous(node_type ntype, toml::node*& first_nonmatch) noexcept override
|
||||
{
|
||||
if (ntype != node_type::none && ntype != impl::node_type_of<value_type>)
|
||||
{
|
||||
first_nonmatch = this;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
[[nodiscard]]
|
||||
bool is_homogeneous(node_type ntype, const toml::node*& first_nonmatch) const noexcept override
|
||||
{
|
||||
if (ntype != node_type::none && ntype != impl::node_type_of<value_type>)
|
||||
{
|
||||
first_nonmatch = this;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
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 value::is_homogeneous() must be void or one of:"
|
||||
TOML_SA_UNWRAPPED_NODE_TYPE_LIST
|
||||
);
|
||||
|
||||
using type = impl::unwrap_node<ElemType>;
|
||||
if constexpr (std::is_void_v<type>)
|
||||
return true;
|
||||
else
|
||||
return impl::node_type_of<type> == impl::node_type_of<value_type>;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Type casts
|
||||
/// @{
|
||||
|
||||
[[nodiscard]] value<std::string>* as_string() noexcept override { return as_value<std::string>(this); }
|
||||
[[nodiscard]] value<int64_t>* as_integer() noexcept override { return as_value<int64_t>(this); }
|
||||
[[nodiscard]] value<double>* as_floating_point() noexcept override { return as_value<double>(this); }
|
||||
[[nodiscard]] value<bool>* as_boolean() noexcept override { return as_value<bool>(this); }
|
||||
[[nodiscard]] value<date>* as_date() noexcept override { return as_value<date>(this); }
|
||||
[[nodiscard]] value<time>* as_time() noexcept override { return as_value<time>(this); }
|
||||
[[nodiscard]] value<date_time>* as_date_time() noexcept override { return as_value<date_time>(this); }
|
||||
|
||||
[[nodiscard]] const value<std::string>* as_string() const noexcept override { return as_value<std::string>(this); }
|
||||
[[nodiscard]] const value<int64_t>* as_integer() const noexcept override { return as_value<int64_t>(this); }
|
||||
[[nodiscard]] const value<double>* as_floating_point() const noexcept override { return as_value<double>(this); }
|
||||
[[nodiscard]] const value<bool>* as_boolean() const noexcept override { return as_value<bool>(this); }
|
||||
[[nodiscard]] const value<date>* as_date() const noexcept override { return as_value<date>(this); }
|
||||
[[nodiscard]] const value<time>* as_time() const noexcept override { return as_value<time>(this); }
|
||||
[[nodiscard]] const value<date_time>* as_date_time() const noexcept override { return as_value<date_time>(this); }
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Value retrieval
|
||||
/// @{
|
||||
|
||||
/// \brief Returns a reference to the underlying value.
|
||||
[[nodiscard]] value_type& get() & noexcept { return val_; }
|
||||
/// \brief Returns a reference to the underlying value (rvalue overload).
|
||||
[[nodiscard]] value_type&& get() && noexcept { return static_cast<value_type&&>(val_); }
|
||||
/// \brief Returns a reference to the underlying value (const overload).
|
||||
[[nodiscard]] const value_type& get() const & noexcept { return val_; }
|
||||
|
||||
/// \brief Returns a reference to the underlying value.
|
||||
[[nodiscard]] value_type& operator* () & noexcept { return val_; }
|
||||
/// \brief Returns a reference to the underlying value (rvalue overload).
|
||||
[[nodiscard]] value_type&& operator* () && noexcept { return static_cast<value_type&&>(val_); }
|
||||
/// \brief Returns a reference to the underlying value (const overload).
|
||||
[[nodiscard]] const value_type& operator* () const& noexcept { return val_; }
|
||||
|
||||
/// \brief Returns a reference to the underlying value.
|
||||
[[nodiscard]] explicit operator value_type& () & noexcept { return val_; }
|
||||
/// \brief Returns a reference to the underlying value (rvalue overload).
|
||||
[[nodiscard]] explicit operator value_type && () && noexcept { return static_cast<value_type&&>(val_); }
|
||||
/// \brief Returns a reference to the underlying value (const overload).
|
||||
[[nodiscard]] explicit operator const value_type& () const& noexcept { return val_; }
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Metadata
|
||||
/// @{
|
||||
|
||||
/// \brief Returns the metadata flags associated with this value.
|
||||
[[nodiscard]] value_flags flags() const noexcept
|
||||
{
|
||||
return flags_;
|
||||
}
|
||||
|
||||
/// \brief Sets the metadata flags associated with this value.
|
||||
/// \returns A reference to the value object.
|
||||
value& flags(value_flags new_flags) noexcept
|
||||
{
|
||||
flags_ = new_flags;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \brief Prints the value out to a stream as formatted TOML.
|
||||
template <typename Char, typename T>
|
||||
friend std::basic_ostream<Char>& operator << (std::basic_ostream<Char>& lhs, const value<T>& rhs);
|
||||
// implemented in toml_default_formatter.h
|
||||
|
||||
/// \brief Value-assignment operator.
|
||||
value& operator= (value_arg rhs) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<value_type, std::string>)
|
||||
val_.assign(rhs);
|
||||
else
|
||||
val_ = rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T = value_type, typename = std::enable_if_t<std::is_same_v<T, std::string>>>
|
||||
value& operator= (std::string&& rhs) noexcept
|
||||
{
|
||||
val_ = std::move(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \name Equality
|
||||
/// @{
|
||||
|
||||
/// \brief Value equality operator.
|
||||
[[nodiscard]]
|
||||
friend bool operator == (const value& lhs, value_arg rhs) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<value_type, double>)
|
||||
{
|
||||
const auto lhs_class = impl::fpclassify(lhs.val_);
|
||||
const auto rhs_class = impl::fpclassify(rhs);
|
||||
if (lhs_class == impl::fp_class::nan && rhs_class == impl::fp_class::nan)
|
||||
return true;
|
||||
if ((lhs_class == impl::fp_class::nan) != (rhs_class == impl::fp_class::nan))
|
||||
return false;
|
||||
}
|
||||
return lhs.val_ == rhs;
|
||||
}
|
||||
TOML_ASYMMETRICAL_EQUALITY_OPS(const value&, value_arg, );
|
||||
|
||||
/// \brief Value less-than operator.
|
||||
[[nodiscard]] friend bool operator < (const value& lhs, value_arg rhs) noexcept { return lhs.val_ < rhs; }
|
||||
/// \brief Value less-than operator.
|
||||
[[nodiscard]] friend bool operator < (value_arg lhs, const value& rhs) noexcept { return lhs < rhs.val_; }
|
||||
/// \brief Value less-than-or-equal-to operator.
|
||||
[[nodiscard]] friend bool operator <= (const value& lhs, value_arg rhs) noexcept { return lhs.val_ <= rhs; }
|
||||
/// \brief Value less-than-or-equal-to operator.
|
||||
[[nodiscard]] friend bool operator <= (value_arg lhs, const value& rhs) noexcept { return lhs <= rhs.val_; }
|
||||
|
||||
/// \brief Value greater-than operator.
|
||||
[[nodiscard]] friend bool operator > (const value& lhs, value_arg rhs) noexcept { return lhs.val_ > rhs; }
|
||||
/// \brief Value greater-than operator.
|
||||
[[nodiscard]] friend bool operator > (value_arg lhs, const value& rhs) noexcept { return lhs > rhs.val_; }
|
||||
/// \brief Value greater-than-or-equal-to operator.
|
||||
[[nodiscard]] friend bool operator >= (const value& lhs, value_arg rhs) noexcept { return lhs.val_ >= rhs; }
|
||||
/// \brief Value greater-than-or-equal-to operator.
|
||||
[[nodiscard]] friend bool operator >= (value_arg lhs, const value& rhs) noexcept { return lhs >= rhs.val_; }
|
||||
|
||||
/// \brief Equality operator.
|
||||
///
|
||||
/// \param lhs The LHS value.
|
||||
/// \param rhs The RHS value.
|
||||
///
|
||||
/// \returns True if the values were of the same type and contained the same value.
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
friend bool operator == (const value& lhs, const value<T>& rhs) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<value_type, T>)
|
||||
return lhs == rhs.val_; //calls asymmetrical value-equality operator defined above
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Inequality operator.
|
||||
///
|
||||
/// \param lhs The LHS value.
|
||||
/// \param rhs The RHS value.
|
||||
///
|
||||
/// \returns True if the values were not of the same type, or did not contain the same value.
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
friend bool operator != (const value& lhs, const value<T>& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
/// \brief Less-than operator.
|
||||
///
|
||||
/// \param lhs The LHS toml::value.
|
||||
/// \param rhs The RHS toml::value.
|
||||
///
|
||||
/// \returns \conditional_return{Same value types}
|
||||
/// `lhs.get() < rhs.get()`
|
||||
/// \conditional_return{Different value types}
|
||||
/// `lhs.type() < rhs.type()`
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
friend bool operator < (const value& lhs, const value<T>& rhs) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<value_type, T>)
|
||||
return lhs.val_ < rhs.val_;
|
||||
else
|
||||
return impl::node_type_of<value_type> < impl::node_type_of<T>;
|
||||
}
|
||||
|
||||
/// \brief Less-than-or-equal-to operator.
|
||||
///
|
||||
/// \param lhs The LHS toml::value.
|
||||
/// \param rhs The RHS toml::value.
|
||||
///
|
||||
/// \returns \conditional_return{Same value types}
|
||||
/// `lhs.get() <= rhs.get()`
|
||||
/// \conditional_return{Different value types}
|
||||
/// `lhs.type() <= rhs.type()`
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
friend bool operator <= (const value& lhs, const value<T>& rhs) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<value_type, T>)
|
||||
return lhs.val_ <= rhs.val_;
|
||||
else
|
||||
return impl::node_type_of<value_type> <= impl::node_type_of<T>;
|
||||
}
|
||||
|
||||
/// \brief Greater-than operator.
|
||||
///
|
||||
/// \param lhs The LHS toml::value.
|
||||
/// \param rhs The RHS toml::value.
|
||||
///
|
||||
/// \returns \conditional_return{Same value types}
|
||||
/// `lhs.get() > rhs.get()`
|
||||
/// \conditional_return{Different value types}
|
||||
/// `lhs.type() > rhs.type()`
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
friend bool operator > (const value& lhs, const value<T>& rhs) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<value_type, T>)
|
||||
return lhs.val_ > rhs.val_;
|
||||
else
|
||||
return impl::node_type_of<value_type> > impl::node_type_of<T>;
|
||||
}
|
||||
|
||||
/// \brief Greater-than-or-equal-to operator.
|
||||
///
|
||||
/// \param lhs The LHS toml::value.
|
||||
/// \param rhs The RHS toml::value.
|
||||
///
|
||||
/// \returns \conditional_return{Same value types}
|
||||
/// `lhs.get() >= rhs.get()`
|
||||
/// \conditional_return{Different value types}
|
||||
/// `lhs.type() >= rhs.type()`
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
friend bool operator >= (const value& lhs, const value<T>& rhs) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<value_type, T>)
|
||||
return lhs.val_ >= rhs.val_;
|
||||
else
|
||||
return impl::node_type_of<value_type> >= impl::node_type_of<T>;
|
||||
}
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
/// \cond
|
||||
template <typename T>
|
||||
value(T) -> value<impl::native_type_of<impl::remove_cvref_t<T>>>;
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_INIT_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
|
||||
#if !TOML_HEADER_ONLY
|
||||
extern template class TOML_API value<std::string>;
|
||||
extern template class TOML_API value<int64_t>;
|
||||
extern template class TOML_API value<double>;
|
||||
extern template class TOML_API value<bool>;
|
||||
extern template class TOML_API value<date>;
|
||||
extern template class TOML_API value<time>;
|
||||
extern template class TOML_API value<date_time>;
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
inline decltype(auto) node::get_value_exact() const noexcept
|
||||
{
|
||||
using namespace impl;
|
||||
|
||||
static_assert(node_type_of<T> != node_type::none);
|
||||
static_assert(node_type_of<T> != node_type::table);
|
||||
static_assert(node_type_of<T> != node_type::array);
|
||||
static_assert(is_native<T> || can_represent_native<T>);
|
||||
static_assert(!is_cvref<T>);
|
||||
TOML_ASSERT(this->type() == node_type_of<T>);
|
||||
|
||||
if constexpr (node_type_of<T> == node_type::string)
|
||||
{
|
||||
const auto& str = *ref_cast<std::string>();
|
||||
if constexpr (std::is_same_v<T, std::string>)
|
||||
return str;
|
||||
else if constexpr (std::is_same_v<T, std::string_view>)
|
||||
return T{ str };
|
||||
else if constexpr (std::is_same_v<T, const char*>)
|
||||
return str.c_str();
|
||||
|
||||
else if constexpr (std::is_same_v<T, std::wstring>)
|
||||
{
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
return widen(str);
|
||||
#else
|
||||
static_assert(dependent_false<T>, "Evaluated unreachable branch!");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
|
||||
// char -> char8_t (potentially unsafe - the feature is 'experimental'!)
|
||||
else if constexpr (is_one_of<T, std::u8string, std::u8string_view>)
|
||||
return T(reinterpret_cast<const char8_t*>(str.c_str()), str.length());
|
||||
else if constexpr (std::is_same_v<T, const char8_t*>)
|
||||
return reinterpret_cast<const char8_t*>(str.c_str());
|
||||
else
|
||||
static_assert(dependent_false<T>, "Evaluated unreachable branch!");
|
||||
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return static_cast<T>(*ref_cast<native_type_of<T>>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline optional<T> node::value_exact() const noexcept
|
||||
{
|
||||
using namespace impl;
|
||||
|
||||
static_assert(
|
||||
!is_wide_string<T> || TOML_WINDOWS_COMPAT,
|
||||
"Retrieving values as wide-character strings with node::value_exact() is only "
|
||||
"supported on Windows with TOML_WINDOWS_COMPAT enabled."
|
||||
);
|
||||
|
||||
static_assert(
|
||||
(is_native<T> || can_represent_native<T>) && !is_cvref<T>,
|
||||
TOML_SA_VALUE_EXACT_FUNC_MESSAGE("return type of node::value_exact()")
|
||||
);
|
||||
|
||||
// prevent additional compiler error spam when the static_assert fails by gating behind if constexpr
|
||||
if constexpr ((is_native<T> || can_represent_native<T>) && !is_cvref<T>)
|
||||
{
|
||||
if (type() == node_type_of<T>)
|
||||
return { this->get_value_exact<T>() };
|
||||
else
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline optional<T> node::value() const noexcept
|
||||
{
|
||||
using namespace impl;
|
||||
|
||||
static_assert(
|
||||
!is_wide_string<T> || TOML_WINDOWS_COMPAT,
|
||||
"Retrieving values as wide-character strings with node::value() is only "
|
||||
"supported on Windows with TOML_WINDOWS_COMPAT enabled."
|
||||
);
|
||||
static_assert(
|
||||
(is_native<T> || can_represent_native<T> || can_partially_represent_native<T>) && !is_cvref<T>,
|
||||
TOML_SA_VALUE_FUNC_MESSAGE("return type of node::value()")
|
||||
);
|
||||
|
||||
// when asking for strings, dates, times and date_times there's no 'fuzzy' conversion
|
||||
// semantics to be mindful of so the exact retrieval is enough.
|
||||
if constexpr (is_natively_one_of<T, std::string, time, date, date_time>)
|
||||
{
|
||||
if (type() == node_type_of<T>)
|
||||
return { this->get_value_exact<T>() };
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
// everything else requires a bit of logicking.
|
||||
else
|
||||
{
|
||||
switch (type())
|
||||
{
|
||||
// int -> *
|
||||
case node_type::integer:
|
||||
{
|
||||
// int -> int
|
||||
if constexpr (is_natively_one_of<T, int64_t>)
|
||||
{
|
||||
if constexpr (is_native<T> || can_represent_native<T>)
|
||||
return static_cast<T>(*ref_cast<int64_t>());
|
||||
else
|
||||
return node_integer_cast<T>(*ref_cast<int64_t>());
|
||||
}
|
||||
|
||||
// int -> float
|
||||
else if constexpr (is_natively_one_of<T, double>)
|
||||
{
|
||||
const int64_t val = *ref_cast<int64_t>();
|
||||
if constexpr (std::numeric_limits<T>::digits < 64)
|
||||
{
|
||||
constexpr auto largest_whole_float = (int64_t{ 1 } << std::numeric_limits<T>::digits);
|
||||
if (val < -largest_whole_float || val > largest_whole_float)
|
||||
return {};
|
||||
}
|
||||
return static_cast<T>(val);
|
||||
}
|
||||
|
||||
// int -> bool
|
||||
else if constexpr (is_natively_one_of<T, bool>)
|
||||
return static_cast<bool>(*ref_cast<int64_t>());
|
||||
|
||||
// int -> anything else
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
// float -> *
|
||||
case node_type::floating_point:
|
||||
{
|
||||
// float -> float
|
||||
if constexpr (is_natively_one_of<T, double>)
|
||||
{
|
||||
if constexpr (is_native<T> || can_represent_native<T>)
|
||||
return { static_cast<T>(*ref_cast<double>()) };
|
||||
else
|
||||
{
|
||||
const double val = *ref_cast<double>();
|
||||
if (impl::fpclassify(val) == fp_class::ok
|
||||
&& (val < (std::numeric_limits<T>::lowest)() || val > (std::numeric_limits<T>::max)()))
|
||||
return {};
|
||||
return { static_cast<T>(val) };
|
||||
}
|
||||
}
|
||||
|
||||
// float -> int
|
||||
else if constexpr (is_natively_one_of<T, int64_t>)
|
||||
{
|
||||
const double val = *ref_cast<double>();
|
||||
if (impl::fpclassify(val) == fp_class::ok
|
||||
&& static_cast<double>(static_cast<int64_t>(val)) == val)
|
||||
return node_integer_cast<T>(static_cast<int64_t>(val));
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
// float -> anything else
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
// bool -> *
|
||||
case node_type::boolean:
|
||||
{
|
||||
// bool -> bool
|
||||
if constexpr (is_natively_one_of<T, bool>)
|
||||
return { *ref_cast<bool>() };
|
||||
|
||||
// bool -> int
|
||||
else if constexpr (is_natively_one_of<T, int64_t>)
|
||||
return { static_cast<T>(*ref_cast<bool>()) };
|
||||
|
||||
// bool -> anything else
|
||||
else
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// non-values, or 'exact' types covered above
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline auto node::value_or(T&& default_value) const noexcept
|
||||
{
|
||||
using namespace impl;
|
||||
|
||||
static_assert(
|
||||
!is_wide_string<T> || TOML_WINDOWS_COMPAT,
|
||||
"Retrieving values as wide-character strings with node::value_or() is only "
|
||||
"supported on Windows with TOML_WINDOWS_COMPAT enabled."
|
||||
);
|
||||
|
||||
|
||||
if constexpr (is_wide_string<T>)
|
||||
{
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
if (type() == node_type::string)
|
||||
return widen(*ref_cast<std::string>());
|
||||
return std::wstring{ static_cast<T&&>(default_value) };
|
||||
|
||||
#else
|
||||
|
||||
static_assert(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>
|
||||
>;
|
||||
using traits = value_traits<value_type>;
|
||||
|
||||
static_assert(
|
||||
traits::is_native || traits::can_represent_native || traits::can_partially_represent_native,
|
||||
"The default value type of node::value_or() must be one of:"
|
||||
TOML_SA_LIST_NEW "A native TOML value type"
|
||||
TOML_SA_NATIVE_VALUE_TYPE_LIST
|
||||
|
||||
TOML_SA_LIST_NXT "A non-view type capable of losslessly representing a native TOML value type"
|
||||
TOML_SA_LIST_BEG "std::string"
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
TOML_SA_LIST_SEP "std::wstring"
|
||||
#endif
|
||||
TOML_SA_LIST_SEP "any signed integer type >= 64 bits"
|
||||
TOML_SA_LIST_SEP "any floating-point type >= 64 bits"
|
||||
TOML_SA_LIST_END
|
||||
|
||||
TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type"
|
||||
TOML_SA_LIST_BEG "any other integer type"
|
||||
TOML_SA_LIST_SEP "any floating-point type >= 32 bits"
|
||||
TOML_SA_LIST_END
|
||||
|
||||
TOML_SA_LIST_NXT "A compatible view type"
|
||||
TOML_SA_LIST_BEG "std::string_view"
|
||||
#if TOML_HAS_CHAR8
|
||||
TOML_SA_LIST_SEP "std::u8string_view"
|
||||
#endif
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
TOML_SA_LIST_SEP "std::wstring_view"
|
||||
#endif
|
||||
TOML_SA_LIST_SEP "const char*"
|
||||
#if TOML_HAS_CHAR8
|
||||
TOML_SA_LIST_SEP "const char8_t*"
|
||||
#endif
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
TOML_SA_LIST_SEP "const wchar_t*"
|
||||
#endif
|
||||
TOML_SA_LIST_END
|
||||
);
|
||||
|
||||
// prevent additional compiler error spam when the static_assert fails by gating behind if constexpr
|
||||
if constexpr (traits::is_native || traits::can_represent_native || traits::can_partially_represent_native)
|
||||
{
|
||||
if constexpr (traits::is_native)
|
||||
{
|
||||
if (type() == node_type_of<value_type>)
|
||||
return *ref_cast<typename traits::native_type>();
|
||||
}
|
||||
if (auto val = this->value<value_type>())
|
||||
return *val;
|
||||
if constexpr (std::is_pointer_v<value_type>)
|
||||
return value_type{ default_value };
|
||||
else
|
||||
return static_cast<T&&>(default_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !TOML_HEADER_ONLY
|
||||
|
||||
#define TOML_EXTERN(name, T) \
|
||||
extern template TOML_API optional<T> 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);
|
||||
#if TOML_HAS_CHAR8
|
||||
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
|
||||
|
||||
#endif // !TOML_HEADER_ONLY
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_INIT_WARNINGS, TOML_DISABLE_SWITCH_WARNINGS
|
||||
/// \endcond
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_ARITHMETIC_WARNINGS
|
@ -1,7 +1,7 @@
|
||||
project(
|
||||
'tomlplusplus',
|
||||
'cpp',
|
||||
version: '2.5.0',
|
||||
version: '2.6.0',
|
||||
meson_version: '>=0.53.0',
|
||||
license: 'MIT',
|
||||
default_options: [ # https://mesonbuild.com/Builtin-options.html
|
||||
|
@ -35,59 +35,60 @@
|
||||
</ImportGroup>
|
||||
<Import Project="$(ProjectDir)\toml++.props" />
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\toml++\impl\array.h" />
|
||||
<ClInclude Include="include\toml++\impl\array_impl.h" />
|
||||
<ClInclude Include="include\toml++\impl\common.h" />
|
||||
<ClInclude Include="include\toml++\impl\date_time.h" />
|
||||
<ClInclude Include="include\toml++\impl\default_formatter.h" />
|
||||
<ClInclude Include="include\toml++\impl\default_formatter_impl.h" />
|
||||
<ClInclude Include="include\toml++\impl\formatter.h" />
|
||||
<ClInclude Include="include\toml++\impl\json_formatter.h" />
|
||||
<ClInclude Include="include\toml++\impl\json_formatter_impl.h" />
|
||||
<ClInclude Include="include\toml++\impl\node.h" />
|
||||
<ClInclude Include="include\toml++\impl\node_impl.h" />
|
||||
<ClInclude Include="include\toml++\impl\node_view.h" />
|
||||
<ClInclude Include="include\toml++\impl\parse_error.h" />
|
||||
<ClInclude Include="include\toml++\impl\parse_result.h" />
|
||||
<ClInclude Include="include\toml++\impl\parser.h" />
|
||||
<ClInclude Include="include\toml++\impl\parser_impl.h" />
|
||||
<ClInclude Include="include\toml++\impl\preprocessor.h" />
|
||||
<ClInclude Include="include\toml++\impl\print_to_stream.h" />
|
||||
<ClInclude Include="include\toml++\impl\table.h" />
|
||||
<ClInclude Include="include\toml++\impl\table_impl.h" />
|
||||
<ClInclude Include="include\toml++\impl\template_instantiations.h" />
|
||||
<ClInclude Include="include\toml++\impl\utf8.h" />
|
||||
<ClInclude Include="include\toml++\impl\utf8_streams.h" />
|
||||
<ClInclude Include="include\toml++\impl\utf8_streams_impl.h" />
|
||||
<ClInclude Include="include\toml++\impl\value.h" />
|
||||
<ClInclude Include="include\toml++\impl\version.h" />
|
||||
<ClInclude Include="include\toml++\toml.h" />
|
||||
<ClInclude Include="include\toml++\toml_array.h" />
|
||||
<ClInclude Include="include\toml++\toml_array.hpp" />
|
||||
<ClInclude Include="include\toml++\toml_common.h" />
|
||||
<ClInclude Include="include\toml++\toml_date_time.h" />
|
||||
<ClInclude Include="include\toml++\toml_default_formatter.h" />
|
||||
<ClInclude Include="include\toml++\toml_default_formatter.hpp" />
|
||||
<ClInclude Include="include\toml++\toml_formatter.h" />
|
||||
<ClInclude Include="include\toml++\toml_json_formatter.h" />
|
||||
<ClInclude Include="include\toml++\toml_json_formatter.hpp" />
|
||||
<ClInclude Include="include\toml++\toml_node.h" />
|
||||
<ClInclude Include="include\toml++\toml_node.hpp" />
|
||||
<ClInclude Include="include\toml++\toml_parser.h" />
|
||||
<ClInclude Include="include\toml++\toml_node_view.h" />
|
||||
<ClInclude Include="include\toml++\toml_parser.hpp" />
|
||||
<ClInclude Include="include\toml++\toml_parse_error.h" />
|
||||
<ClInclude Include="include\toml++\toml_parse_result.h" />
|
||||
<ClInclude Include="include\toml++\toml_preprocessor.h" />
|
||||
<ClInclude Include="include\toml++\toml_print_to_stream.h" />
|
||||
<ClInclude Include="include\toml++\toml_table.hpp" />
|
||||
<ClInclude Include="include\toml++\toml_table.h" />
|
||||
<ClInclude Include="include\toml++\toml_utf8.h" />
|
||||
<ClInclude Include="include\toml++\toml_utf8_streams.h" />
|
||||
<ClInclude Include="include\toml++\toml_utf8_streams.hpp" />
|
||||
<ClInclude Include="include\toml++\toml_value.h" />
|
||||
<ClInclude Include="include\toml++\toml_instantiations.hpp" />
|
||||
<ClInclude Include="include\toml++\toml_version.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include=".circleci\config.yml" />
|
||||
<None Include=".clang-format" />
|
||||
<None Include=".editorconfig" />
|
||||
<None Include=".gitattributes" />
|
||||
<None Include=".gitignore" />
|
||||
<None Include=".runsettings" />
|
||||
<None Include="CODE_OF_CONDUCT.md" />
|
||||
<None Include="CONTRIBUTING.md" />
|
||||
<None Include="LICENSE" />
|
||||
<None Include="README.md" />
|
||||
<None Include="cmake\install-rules.cmake" />
|
||||
<None Include="cmake\project-is-top-level.cmake" />
|
||||
<None Include="cmake\tomlplusplus.cmake.in" />
|
||||
<None Include="cmake\tomlplusplusConfig.cmake" />
|
||||
<None Include="cmake\variables.cmake" />
|
||||
<None Include="CODE_OF_CONDUCT.md" />
|
||||
<None Include="CONTRIBUTING.md" />
|
||||
<None Include="cpp.hint" />
|
||||
<None Include="docs\pages\main_page.dox" />
|
||||
<None Include="docs\poxy.toml" />
|
||||
<None Include="LICENSE" />
|
||||
<None Include="meson.build" />
|
||||
<None Include="README.md" />
|
||||
<None Include="toml++.props" />
|
||||
<None Include="tools\ci_single_header_check.py" />
|
||||
<None Include="tools\generate_conformance_tests.py" />
|
||||
<None Include="tools\generate_single_header.py" />
|
||||
<None Include="tools\generate_windows_test_targets.py" />
|
||||
<None Include="tools\utils.py" />
|
||||
<None Include="toml++.props" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="toml++.natvis" />
|
||||
|
@ -4,88 +4,87 @@
|
||||
<ClInclude Include="include\toml++\toml.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_array.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\array.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_array.hpp">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\array_impl.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_common.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\common.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_date_time.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\date_time.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_default_formatter.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\default_formatter.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_default_formatter.hpp">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\default_formatter_impl.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_formatter.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\formatter.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_instantiations.hpp">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\json_formatter.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_json_formatter.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\json_formatter_impl.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_json_formatter.hpp">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\node.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_node.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\node_impl.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_node.hpp">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\node_view.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_node_view.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\parse_error.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_parse_error.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\parse_result.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_parser.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\parser.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_parser.hpp">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\parser_impl.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_preprocessor.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\preprocessor.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_print_to_stream.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\print_to_stream.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_table.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\table.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_table.hpp">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\table_impl.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_utf8.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\template_instantiations.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_utf8_streams.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\utf8.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_utf8_streams.hpp">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\utf8_streams.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_value.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\utf8_streams_impl.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_version.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\value.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\toml_parse_result.h">
|
||||
<Filter>include</Filter>
|
||||
<ClInclude Include="include\toml++\impl\version.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="toml++.props" />
|
||||
<None Include=".editorconfig" />
|
||||
<None Include=".gitattributes" />
|
||||
<None Include=".gitignore" />
|
||||
<None Include="CODE_OF_CONDUCT.md" />
|
||||
@ -134,6 +133,8 @@
|
||||
<None Include="cmake\tomlplusplus.cmake.in">
|
||||
<Filter>cmake</Filter>
|
||||
</None>
|
||||
<None Include=".clang-format" />
|
||||
<None Include=".editorconfig" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include=".circleci">
|
||||
@ -154,6 +155,9 @@
|
||||
<Filter Include="cmake">
|
||||
<UniqueIdentifier>{47351d16-986b-4f4b-bd5e-b7c66a7a68d3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="include\impl">
|
||||
<UniqueIdentifier>{4e42aaa3-98cd-4678-9c1c-ffa3eaf519d7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="toml++.natvis" />
|
||||
|
@ -10,43 +10,51 @@ import re
|
||||
from pathlib import Path
|
||||
from io import StringIO
|
||||
|
||||
|
||||
|
||||
|
||||
class Preprocessor:
|
||||
|
||||
__re_strip_blocks = re.compile(r'//[#!]\s*[{][{].*?//[#!]\s*[}][}]*?\n', re.I | re.S)
|
||||
__re_includes = re.compile(r'^\s*#\s*include\s+"(.+?)"', re.I | re.M)
|
||||
|
||||
def __preprocess(self, match):
|
||||
def __init__(self, file):
|
||||
self.__processed_includes = []
|
||||
self.__current_level = 0
|
||||
self.__directory_stack = [ Path.cwd() ]
|
||||
self.__entry_root = ''
|
||||
self.__string = self.__preprocess(file)
|
||||
|
||||
raw_incl = match if isinstance(match, str) else match.group(1)
|
||||
incl = raw_incl.strip().lower()
|
||||
def __preprocess(self, incl):
|
||||
|
||||
if not isinstance(incl, (Path, str)): # a regex match object
|
||||
incl = incl.group(1).strip()
|
||||
if isinstance(incl, str):
|
||||
incl = Path(incl.strip().replace('\\',r'/'))
|
||||
if not incl.is_absolute():
|
||||
incl = Path(self.__directory_stack[-1], incl).resolve()
|
||||
if incl in self.__processed_includes:
|
||||
return ''
|
||||
if self.__current_level == 0 and self.__entry_root == '':
|
||||
self.__entry_root = str(incl.parent).replace('\\',r'/')
|
||||
|
||||
self.__processed_includes.append(incl)
|
||||
text = utils.read_all_text_from_file(Path(utils.entry_script_dir(), '..', 'include', 'toml++', incl).resolve(), logger=True).strip() + '\n'
|
||||
self.__directory_stack.append(incl.parent)
|
||||
|
||||
text = utils.read_all_text_from_file(incl, logger=True).strip() + '\n'
|
||||
text = text.replace('\r\n', '\n') # convert windows newlines
|
||||
text = self.__re_strip_blocks.sub('', text, 0) # strip {{ }} blocks
|
||||
self.__current_level += 1
|
||||
text = self.__re_includes.sub(lambda m : self.__preprocess(m), text, 0)
|
||||
self.__current_level -= 1
|
||||
|
||||
if (self.__current_level == 1):
|
||||
header_text = '↓ ' + raw_incl
|
||||
lpad = 20 + ((25 * (self.__header_indent % 4)) - int((len(header_text) + 4) / 2))
|
||||
self.__header_indent += 1
|
||||
text = '#if 1 {}\n{}\n\n#endif {}\n'.format(
|
||||
utils.make_divider(header_text, lpad, line_length=113),
|
||||
text,
|
||||
utils.make_divider('↑ ' + raw_incl, lpad, line_length=113)
|
||||
)
|
||||
if self.__current_level == 1:
|
||||
header = str(incl).replace('\\',r'/')
|
||||
if header.startswith(self.__entry_root):
|
||||
header = header[len(self.__entry_root):].strip('/')
|
||||
header = utils.make_divider(header, 10, pattern = r'*')
|
||||
text = f'{header}\n\n{text}'
|
||||
|
||||
return '\n\n' + text + '\n\n' # will get merged later
|
||||
|
||||
def __init__(self, file):
|
||||
self.__processed_includes = []
|
||||
self.__header_indent = 0
|
||||
self.__current_level = 0
|
||||
self.__string = self.__preprocess(file)
|
||||
self.__directory_stack.pop()
|
||||
return '\n\n' + text + '\n\n'
|
||||
|
||||
def __str__(self):
|
||||
return self.__string
|
||||
@ -55,99 +63,74 @@ class Preprocessor:
|
||||
|
||||
def main():
|
||||
|
||||
# establish local directories
|
||||
root_dir = utils.entry_script_dir().parent
|
||||
include_dir = Path(root_dir, 'include', 'toml++')
|
||||
|
||||
# preprocess header(s)
|
||||
source_text = str(Preprocessor('toml.h'))
|
||||
toml_h = str(Preprocessor(Path(include_dir, 'toml.h')))
|
||||
|
||||
# strip various things:
|
||||
# 'pragma once'
|
||||
source_text = re.sub(r'^\s*#\s*pragma\s+once\s*$', '', source_text, 0, re.I | re.M)
|
||||
# clang-format directives
|
||||
source_text = re.sub(r'^\s*//\s*clang-format\s+.+?$', '', source_text, 0, re.I | re.M)
|
||||
# spdx license identifiers
|
||||
source_text = re.sub(r'^\s*//\s*SPDX-License-Identifier:.+?$', '', source_text, 0, re.I | re.M)
|
||||
# 'magic' comment blocks (incl. doxygen)
|
||||
source_text = re.sub('(?:(?:\n|^)[ \t]*//[/#!<]+[^\n]*)+\n', '\n', source_text, 0, re.I | re.M)
|
||||
# 'magic' comments (incl. doxygen)
|
||||
source_text = re.sub('(?://[/#!<].*?)\n', '\n', source_text, 0, re.I | re.M)
|
||||
# remove trailing whitespace
|
||||
source_text = re.sub('([^ \t])[ \t]+\n', '\\1\n', source_text, 0, re.I | re.M)
|
||||
# bookended namespace blocks
|
||||
source_text = re.sub('}\n+TOML_NAMESPACE_END\n+TOML_NAMESPACE_START\n+{\n+', '\n', source_text, 0, re.I | re.M)
|
||||
source_text = re.sub('}\n+TOML_IMPL_NAMESPACE_END\n+TOML_IMPL_NAMESPACE_START\n+{\n+', '\n', source_text, 0, re.I | re.M)
|
||||
# blank lines before some preprocessor directives
|
||||
#source_text = re.sub('\n+\n(\s*)#\s*(elif|else|endif)(.*?)\n', '\n\\1#\\2\\3\n', source_text, 0, re.I | re.M)
|
||||
# blank lines after some preprocessor directives
|
||||
#source_text = re.sub('#\s*(if|ifn?def|elif|else)(.*?)\n\n+', '#\\1\\2\n', source_text, 0, re.I | re.M)
|
||||
# blank lines after opening braces
|
||||
source_text = re.sub('[{]\s*\n\s*\n+', '{\n', source_text, 0, re.I | re.M)
|
||||
# double newlines
|
||||
source_text = re.sub('\n(?:[ \t]*\n[ \t]*)+\n', '\n\n', source_text, 0, re.I | re.M)
|
||||
|
||||
# source_text = re.sub( # blank lines between various preprocessor directives
|
||||
# '[#](endif(?:\s*//[^\n]*)?)\n{2,}[#](ifn?(?:def)?|define)',
|
||||
# '#\\1\n#\\2',
|
||||
# source_text, 0, re.I | re.M
|
||||
# )
|
||||
return_type_pattern \
|
||||
= r'(?:' \
|
||||
+ r'(?:\[\[nodiscard\]\]\s*)?' \
|
||||
+ r'(?:(?:friend|explicit|virtual|inline|const|operator)\s+)*' \
|
||||
+ r'(?:' \
|
||||
+ r'bool|int64_t|(?:const_)?iterator|double|void' \
|
||||
+ r'|node(?:_(?:view|of)<.+?>|)?|table|array|value(?:<.+?>)?' \
|
||||
+ r'|T|U|parse_(?:error|result)' \
|
||||
+ r')' \
|
||||
+ r'(?:\s*[&*]+)?' \
|
||||
+ r'(?:\s*[(]\s*[)])?' \
|
||||
+ r'\s+' \
|
||||
+ r')'
|
||||
blank_lines_between_returns_pattern = '({}[^\n]+)\n\n([ \t]*{})'.format(return_type_pattern, return_type_pattern)
|
||||
for i in range(0, 5): # remove blank lines between simple one-liner definitions
|
||||
source_text = re.sub('(using .+?;)\n\n([ \t]*using)', '\\1\n\\2', source_text, 0, re.I | re.M)
|
||||
source_text = re.sub(
|
||||
'([a-zA-Z_][a-zA-Z0-9_]*[ \t]+[a-zA-Z_][a-zA-Z0-9_]*[ \t]*;)' \
|
||||
+ '\n\n([ \t]*[a-zA-Z_][a-zA-Z0-9_]*[ \t]+[a-zA-Z_][a-zA-Z0-9_]*[ \t]*;)', '\\1\n\\2',
|
||||
source_text, 0, re.I | re.M)
|
||||
source_text = re.sub(blank_lines_between_returns_pattern, '\\1\n\\2', source_text, 0, re.I | re.M)
|
||||
source_text = source_text.strip() + '\n'
|
||||
if 1:
|
||||
# 'pragma once'
|
||||
toml_h = re.sub(r'^\s*#\s*pragma\s+once\s*$', '', toml_h, 0, re.I | re.M)
|
||||
# trailing whitespace
|
||||
toml_h = re.sub('([^ \t])[ \t]+\n', r'\1\n', toml_h)
|
||||
# explicit 'strip this' blocks
|
||||
toml_h = re.sub(r'(?:\n[ \t]*)?//[#!][ \t]*[{][{].*?//[#!][ \t]*[}][}].*?\n', '\n', toml_h, flags=re.S)
|
||||
# spdx license identifiers
|
||||
toml_h = re.sub(r'^\s*//\s*SPDX-License-Identifier:.+?$', '', toml_h, 0, re.I | re.M)
|
||||
# magic comments
|
||||
blank_line = r'(?:[ \t]*\n)'
|
||||
comment_line = r'(?:[ \t]*//(?:[/#!<]| ?(?:---|===|\^\^\^|vvv))[^\n]*\n)'
|
||||
toml_h = re.sub(rf'\n{comment_line}{blank_line}+{comment_line}', '\n', toml_h)
|
||||
toml_h = re.sub(rf'([{{,])\s*\n(?:{comment_line}|{blank_line})+', r'\1\n', toml_h)
|
||||
toml_h = re.sub(rf'{comment_line}+', '\n', toml_h)
|
||||
# trailing whitespace
|
||||
toml_h = re.sub('([^ \t])[ \t]+\n', r'\1\n', toml_h)
|
||||
# double blank lines
|
||||
toml_h = re.sub('\n(?:[ \t]*\n[ \t]*)+\n', '\n\n', toml_h)
|
||||
# weird spacing edge case between } and pp directives
|
||||
toml_h = re.sub('\n[}]\n#', r'\n}\n\n#', toml_h, re.S)
|
||||
# blank lines following opening brackets or a comma
|
||||
toml_h = re.sub(r'([^@][({,])\n\n', r'\1\n', toml_h)
|
||||
# blank lines preceeding closing brackets
|
||||
toml_h = re.sub(r'\n\n([ \t]*[})])', r'\n\1', toml_h)
|
||||
toml_h = toml_h.strip() + '\n'
|
||||
|
||||
# change TOML_LIB_SINGLE_HEADER to 1
|
||||
source_text = re.sub(
|
||||
toml_h = re.sub(
|
||||
'#\s*define\s+TOML_LIB_SINGLE_HEADER\s+[0-9]+',
|
||||
'#define TOML_LIB_SINGLE_HEADER 1',
|
||||
source_text, 0, re.I
|
||||
toml_h, 0, re.I
|
||||
)
|
||||
|
||||
# extract library version
|
||||
library_version = {
|
||||
'major': 0,
|
||||
'minor': 0,
|
||||
'patch': 0
|
||||
}
|
||||
match = re.search(r'^\s*#\s*define\s+TOML_LIB_MAJOR\s+([0-9]+)\s*$', source_text, re.I | re.M)
|
||||
if match is not None:
|
||||
library_version['major'] = match.group(1)
|
||||
match = re.search(r'^\s*#\s*define\s+TOML_LIB_MINOR\s+([0-9]+)\s*$', source_text, re.I | re.M)
|
||||
if match is not None:
|
||||
library_version['minor'] = match.group(1)
|
||||
match = re.search(r'^\s*#\s*define\s+TOML_LIB_(?:REVISION|PATCH)\s+([0-9]+)\s*$', source_text, re.I | re.M)
|
||||
if match is not None:
|
||||
library_version['patch'] = match.group(1)
|
||||
# read version number
|
||||
version_h = utils.read_all_text_from_file(Path(include_dir, 'impl/version.h'), logger=True)
|
||||
match = re.search(
|
||||
r'#\s*define\s+TOML_LIB_MAJOR\s+([0-9]+)[^0-9].*'
|
||||
+ r'#\s*define\s+TOML_LIB_MINOR\s+([0-9]+)[^0-9].*'
|
||||
+ r'#\s*define\s+TOML_LIB_PATCH\s+([0-9]+)[^0-9]',
|
||||
version_h, re.I | re.S)
|
||||
if match is None:
|
||||
raise Exception("could not find TOML_LIB_MAJOR, TOML_LIB_MINOR or TOML_LIB_PATCH impl/version.h")
|
||||
version = rf'{int(match[1])}.{int(match[2])}.{int(match[3])}'
|
||||
print(rf'Library version: {version}')
|
||||
|
||||
# build the preamble (license etc)
|
||||
preamble = []
|
||||
preamble.append('''
|
||||
// toml++ v{major}.{minor}.{patch}
|
||||
preamble.append(rf'''
|
||||
// toml++ v{version}
|
||||
// https://github.com/marzer/tomlplusplus
|
||||
// SPDX-License-Identifier: MIT'''.format(**library_version))
|
||||
preamble.append('''
|
||||
// SPDX-License-Identifier: MIT''')
|
||||
preamble.append(r'''
|
||||
// - THIS FILE WAS ASSEMBLED FROM MULTIPLE HEADER FILES BY A SCRIPT - PLEASE DON'T EDIT IT DIRECTLY -
|
||||
//
|
||||
// If you wish to submit a contribution to toml++, hooray and thanks! Before you crack on, please be aware that this
|
||||
// file was assembled from a number of smaller files by a python script, and code contributions should not be made
|
||||
// against it directly. You should instead make your changes in the relevant source file(s). The file names of the files
|
||||
// that contributed to this header can be found at the beginnings and ends of the corresponding sections of this file.''')
|
||||
preamble.append('''
|
||||
preamble.append(r'''
|
||||
// TOML Language Specifications:
|
||||
// latest: https://github.com/toml-lang/toml/blob/master/README.md
|
||||
// v1.0.0: https://toml.io/en/v1.0.0
|
||||
@ -173,52 +156,58 @@ def main():
|
||||
write(line)
|
||||
write('//')
|
||||
write(utils.make_divider())
|
||||
write(source_text)
|
||||
write(toml_h)
|
||||
write('')
|
||||
|
||||
output_str = output.getvalue().strip()
|
||||
|
||||
# analyze the output to find any potentially missing #undefs
|
||||
re_define = re.compile(r'^\s*#\s*define\s+([a-zA-Z0-9_]+)(?:$|\s|\()')
|
||||
re_undef = re.compile(r'^\s*#\s*undef\s+([a-zA-Z0-9_]+)(?:$|\s|//)')
|
||||
defines = dict()
|
||||
for output_line in output_str.splitlines():
|
||||
defined = True
|
||||
m = re_define.match(output_line)
|
||||
if not m:
|
||||
defined = False
|
||||
m = re_undef.match(output_line)
|
||||
if m:
|
||||
defines[m.group(1)] = defined
|
||||
ignore_list = ( # macros that are meant to stay public (user configs etc)
|
||||
r'INCLUDE_TOMLPLUSPLUS_H',
|
||||
r'TOML_API',
|
||||
r'TOML_UNRELEASED_FEATURES',
|
||||
r'TOML_LARGE_FILES',
|
||||
r'TOML_PARSER',
|
||||
r'TOML_WINDOWS_COMPAT',
|
||||
r'TOML_EXCEPTIONS',
|
||||
r'TOML_LIB_SINGLE_HEADER',
|
||||
r'TOML_LIB_MAJOR',
|
||||
r'TOML_LIB_MINOR',
|
||||
r'TOML_LIB_PATCH',
|
||||
r'TOML_LANG_MAJOR',
|
||||
r'TOML_LANG_MINOR',
|
||||
r'TOML_LANG_PATCH',
|
||||
r'TOML_UNDEF_MACROS',
|
||||
r'TOML_HEADER_ONLY',
|
||||
r'TOML_ALL_INLINE',
|
||||
r'TOML_MAX_NESTED_VALUES'
|
||||
)
|
||||
set_defines = []
|
||||
for define, currently_set in defines.items():
|
||||
if currently_set and define not in ignore_list:
|
||||
set_defines.append(define)
|
||||
if len(set_defines) > 0:
|
||||
set_defines.sort()
|
||||
print(f"Potentially missing #undefs:")
|
||||
for define in set_defines:
|
||||
print(f"\t#undef {define}")
|
||||
if 1:
|
||||
re_define = re.compile(r'^\s*#\s*define\s+([a-zA-Z0-9_]+)(?:$|\s|\()')
|
||||
re_undef = re.compile(r'^\s*#\s*undef\s+([a-zA-Z0-9_]+)(?:$|\s|//)')
|
||||
defines = dict()
|
||||
for output_line in output_str.splitlines():
|
||||
defined = True
|
||||
m = re_define.match(output_line)
|
||||
if not m:
|
||||
defined = False
|
||||
m = re_undef.match(output_line)
|
||||
if m:
|
||||
defines[m.group(1)] = defined
|
||||
ignore_list = ( # macros that are meant to stay public (user configs etc)
|
||||
r'INCLUDE_TOMLPLUSPLUS_H',
|
||||
r'TOML_ALL_INLINE',
|
||||
r'TOML_API',
|
||||
r'TOML_CONFIG_HEADER',
|
||||
r'TOML_EXCEPTIONS',
|
||||
r'TOML_HEADER_ONLY',
|
||||
r'TOML_LANG_MAJOR',
|
||||
r'TOML_LANG_MINOR',
|
||||
r'TOML_LANG_PATCH',
|
||||
r'TOML_LARGE_FILES',
|
||||
r'TOML_LIB_MAJOR',
|
||||
r'TOML_LIB_MINOR',
|
||||
r'TOML_LIB_PATCH',
|
||||
r'TOML_LIB_SINGLE_HEADER',
|
||||
r'TOML_MAX_NESTED_VALUES',
|
||||
r'TOML_OPTIONAL_TYPE',
|
||||
r'TOML_PARSER',
|
||||
r'TOML_SMALL_FLOAT_TYPE',
|
||||
r'TOML_SMALL_INT_TYPE',
|
||||
r'TOML_UNDEF_MACROS',
|
||||
r'TOML_UNRELEASED_FEATURES',
|
||||
r'TOML_WINDOWS_COMPAT',
|
||||
r'POXY_IMPLEMENTATION_DETAIL',
|
||||
)
|
||||
set_defines = []
|
||||
for define, currently_set in defines.items():
|
||||
if currently_set and define not in ignore_list:
|
||||
set_defines.append(define)
|
||||
if len(set_defines) > 0:
|
||||
set_defines.sort()
|
||||
print(f"Potentially missing #undefs:")
|
||||
for define in set_defines:
|
||||
print(f"\t#undef {define}")
|
||||
|
||||
# write the output file
|
||||
output_file_path = Path(utils.entry_script_dir(), '..', 'toml.hpp').resolve()
|
||||
|
@ -1,4 +1,4 @@
|
||||
misk>=0.4.0
|
||||
poxy>=0.4.1
|
||||
misk>=0.5.0
|
||||
poxy>=0.5.1
|
||||
pyyaml
|
||||
python-dateutil
|
||||
|
Loading…
Reference in New Issue
Block a user